# HG changeset patch
# User emellor@ewan
# Node ID 10759a44ce3b9431b730eadde2417777ca8f9943
# Parent eba5afe9aa37d3cb96c22cd93b8b7ec7c8e3e1ca
# Parent 28db21fb75453d80636142432b9e324fcd472c52
Merged.
diff -r eba5afe9aa37 -r 10759a44ce3b linux-2.6-xen-sparse/arch/xen/Kconfig
--- a/linux-2.6-xen-sparse/arch/xen/Kconfig Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/Kconfig Thu Sep 22 15:12:14 2005
@@ -110,13 +110,6 @@
network interfaces within another guest OS. Unless you are building a
dedicated device-driver domain, or your master control domain
(domain 0), then you almost certainly want to say Y here.
-
-config XEN_NETDEV_GRANT
- bool "Grant table substrate for network drivers (DANGEROUS)"
- default n
- help
- This introduces the use of grant tables as a data exhange mechanism
- between the frontend and backend network drivers.
config XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER
bool "Pipelined transmitter (DANGEROUS)"
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 Thu Sep
22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 Thu Sep
22 15:12:14 2005
@@ -19,7 +19,6 @@
# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_SHADOW_MODE is not set
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 Thu Sep
22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 Thu Sep
22 15:12:14 2005
@@ -19,7 +19,6 @@
# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_SHADOW_MODE is not set
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32
--- a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 Thu Sep
22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 Thu Sep
22 15:12:14 2005
@@ -16,7 +16,6 @@
# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_SHADOW_MODE is not set
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64
--- a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64 Thu Sep
22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64 Thu Sep
22 15:12:14 2005
@@ -16,7 +16,6 @@
# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_SHADOW_MODE is not set
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 Thu Sep
22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 Thu Sep
22 15:12:14 2005
@@ -19,7 +19,6 @@
# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_SHADOW_MODE is not set
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64
--- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 Thu Sep
22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 Thu Sep
22 15:12:14 2005
@@ -19,7 +19,6 @@
# CONFIG_XEN_TPMDEV_BACKEND is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
CONFIG_XEN_NETDEV_FRONTEND=y
-CONFIG_XEN_NETDEV_GRANT=y
# CONFIG_XEN_NETDEV_FRONTEND_PIPELINED_TRANSMITTER is not set
# CONFIG_XEN_BLKDEV_TAP is not set
# CONFIG_XEN_SHADOW_MODE is not set
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Thu Sep 22
15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/blkback.c Thu Sep 22
15:12:14 2005
@@ -28,12 +28,12 @@
#define BATCH_PER_DOMAIN 16
static unsigned long mmap_vstart;
-#define MMAP_PAGES \
- (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
-#define MMAP_VADDR(_req,_seg) \
- (mmap_vstart + \
- ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) + \
- ((_seg) * PAGE_SIZE))
+#define MMAP_PAGES \
+ (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
+#define MMAP_VADDR(_req,_seg) \
+ (mmap_vstart + \
+ ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) + \
+ ((_seg) * PAGE_SIZE))
/*
* Each outstanding request that we've passed to the lower device layers has a
@@ -42,12 +42,12 @@
* response queued for it, with the saved 'id' passed back.
*/
typedef struct {
- blkif_t *blkif;
- unsigned long id;
- int nr_pages;
- atomic_t pendcnt;
- unsigned short operation;
- int status;
+ blkif_t *blkif;
+ unsigned long id;
+ int nr_pages;
+ atomic_t pendcnt;
+ unsigned short operation;
+ int status;
} pending_req_t;
/*
@@ -68,14 +68,13 @@
static request_queue_t *plugged_queue;
static inline void flush_plugged_queue(void)
{
- request_queue_t *q = plugged_queue;
- if ( q != NULL )
- {
- if ( q->unplug_fn != NULL )
- q->unplug_fn(q);
- blk_put_queue(q);
- plugged_queue = NULL;
- }
+ request_queue_t *q = plugged_queue;
+ if (q != NULL) {
+ if ( q->unplug_fn != NULL )
+ q->unplug_fn(q);
+ blk_put_queue(q);
+ plugged_queue = NULL;
+ }
}
/* When using grant tables to map a frame for device access then the
@@ -106,24 +105,23 @@
static void fast_flush_area(int idx, int nr_pages)
{
- struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
- unsigned int i, invcount = 0;
- u16 handle;
-
- for ( i = 0; i < nr_pages; i++ )
- {
- if ( BLKBACK_INVALID_HANDLE != ( handle = pending_handle(idx, i) ) )
- {
- unmap[i].host_addr = MMAP_VADDR(idx, i);
- unmap[i].dev_bus_addr = 0;
- unmap[i].handle = handle;
- pending_handle(idx, i) = BLKBACK_INVALID_HANDLE;
- invcount++;
- }
- }
- if ( unlikely(HYPERVISOR_grant_table_op(
- GNTTABOP_unmap_grant_ref, unmap, invcount)))
- BUG();
+ struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+ unsigned int i, invcount = 0;
+ u16 handle;
+
+ for (i = 0; i < nr_pages; i++) {
+ handle = pending_handle(idx, i);
+ if (handle == BLKBACK_INVALID_HANDLE)
+ continue;
+ unmap[i].host_addr = MMAP_VADDR(idx, i);
+ unmap[i].dev_bus_addr = 0;
+ unmap[i].handle = handle;
+ pending_handle(idx, i) = BLKBACK_INVALID_HANDLE;
+ invcount++;
+ }
+
+ BUG_ON(HYPERVISOR_grant_table_op(
+ GNTTABOP_unmap_grant_ref, unmap, invcount));
}
@@ -136,34 +134,38 @@
static int __on_blkdev_list(blkif_t *blkif)
{
- return blkif->blkdev_list.next != NULL;
+ return blkif->blkdev_list.next != NULL;
}
static void remove_from_blkdev_list(blkif_t *blkif)
{
- unsigned long flags;
- if ( !__on_blkdev_list(blkif) ) return;
- spin_lock_irqsave(&blkio_schedule_list_lock, flags);
- if ( __on_blkdev_list(blkif) )
- {
- list_del(&blkif->blkdev_list);
- blkif->blkdev_list.next = NULL;
- blkif_put(blkif);
- }
- spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
+ unsigned long flags;
+
+ if (!__on_blkdev_list(blkif))
+ return;
+
+ spin_lock_irqsave(&blkio_schedule_list_lock, flags);
+ if (__on_blkdev_list(blkif)) {
+ list_del(&blkif->blkdev_list);
+ blkif->blkdev_list.next = NULL;
+ blkif_put(blkif);
+ }
+ spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
}
static void add_to_blkdev_list_tail(blkif_t *blkif)
{
- unsigned long flags;
- if ( __on_blkdev_list(blkif) ) return;
- spin_lock_irqsave(&blkio_schedule_list_lock, flags);
- if ( !__on_blkdev_list(blkif) && (blkif->status == CONNECTED) )
- {
- list_add_tail(&blkif->blkdev_list, &blkio_schedule_list);
- blkif_get(blkif);
- }
- spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
+ unsigned long flags;
+
+ if (__on_blkdev_list(blkif))
+ return;
+
+ spin_lock_irqsave(&blkio_schedule_list_lock, flags);
+ if (!__on_blkdev_list(blkif) && (blkif->status == CONNECTED)) {
+ list_add_tail(&blkif->blkdev_list, &blkio_schedule_list);
+ blkif_get(blkif);
+ }
+ spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
}
@@ -175,54 +177,53 @@
static int blkio_schedule(void *arg)
{
- DECLARE_WAITQUEUE(wq, current);
-
- blkif_t *blkif;
- struct list_head *ent;
-
- daemonize("xenblkd");
-
- for ( ; ; )
- {
- /* Wait for work to do. */
- add_wait_queue(&blkio_schedule_wait, &wq);
- set_current_state(TASK_INTERRUPTIBLE);
- if ( (NR_PENDING_REQS == MAX_PENDING_REQS) ||
- list_empty(&blkio_schedule_list) )
- schedule();
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&blkio_schedule_wait, &wq);
-
- /* Queue up a batch of requests. */
- while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
- !list_empty(&blkio_schedule_list) )
- {
- ent = blkio_schedule_list.next;
- blkif = list_entry(ent, blkif_t, blkdev_list);
- blkif_get(blkif);
- remove_from_blkdev_list(blkif);
- if ( do_block_io_op(blkif, BATCH_PER_DOMAIN) )
- add_to_blkdev_list_tail(blkif);
- blkif_put(blkif);
- }
-
- /* Push the batch through to disc. */
- flush_plugged_queue();
- }
+ DECLARE_WAITQUEUE(wq, current);
+
+ blkif_t *blkif;
+ struct list_head *ent;
+
+ daemonize("xenblkd");
+
+ for (;;) {
+ /* Wait for work to do. */
+ add_wait_queue(&blkio_schedule_wait, &wq);
+ set_current_state(TASK_INTERRUPTIBLE);
+ if ( (NR_PENDING_REQS == MAX_PENDING_REQS) ||
+ list_empty(&blkio_schedule_list) )
+ schedule();
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&blkio_schedule_wait, &wq);
+
+ /* Queue up a batch of requests. */
+ while ((NR_PENDING_REQS < MAX_PENDING_REQS) &&
+ !list_empty(&blkio_schedule_list)) {
+ ent = blkio_schedule_list.next;
+ blkif = list_entry(ent, blkif_t, blkdev_list);
+ blkif_get(blkif);
+ remove_from_blkdev_list(blkif);
+ if (do_block_io_op(blkif, BATCH_PER_DOMAIN))
+ add_to_blkdev_list_tail(blkif);
+ blkif_put(blkif);
+ }
+
+ /* Push the batch through to disc. */
+ flush_plugged_queue();
+ }
}
static void maybe_trigger_blkio_schedule(void)
{
- /*
- * Needed so that two processes, who together make the following predicate
- * true, don't both read stale values and evaluate the predicate
- * incorrectly. Incredibly unlikely to stall the scheduler on x86, but...
- */
- smp_mb();
-
- if ( (NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
- !list_empty(&blkio_schedule_list) )
- wake_up(&blkio_schedule_wait);
+ /*
+ * Needed so that two processes, which together make the following
+ * predicate true, don't both read stale values and evaluate the
+ * predicate incorrectly. Incredibly unlikely to stall the scheduler
+ * on x86, but...
+ */
+ smp_mb();
+
+ if ((NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
+ !list_empty(&blkio_schedule_list))
+ wake_up(&blkio_schedule_wait);
}
@@ -233,36 +234,34 @@
static void __end_block_io_op(pending_req_t *pending_req, int uptodate)
{
- unsigned long flags;
-
- /* An error fails the entire request. */
- if ( !uptodate )
- {
- DPRINTK("Buffer not up-to-date at end of operation\n");
- pending_req->status = BLKIF_RSP_ERROR;
- }
-
- if ( atomic_dec_and_test(&pending_req->pendcnt) )
- {
- int pending_idx = pending_req - pending_reqs;
- fast_flush_area(pending_idx, pending_req->nr_pages);
- make_response(pending_req->blkif, pending_req->id,
- pending_req->operation, pending_req->status);
- blkif_put(pending_req->blkif);
- spin_lock_irqsave(&pend_prod_lock, flags);
- pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
- spin_unlock_irqrestore(&pend_prod_lock, flags);
- maybe_trigger_blkio_schedule();
- }
+ unsigned long flags;
+
+ /* An error fails the entire request. */
+ if (!uptodate) {
+ DPRINTK("Buffer not up-to-date at end of operation\n");
+ pending_req->status = BLKIF_RSP_ERROR;
+ }
+
+ if (atomic_dec_and_test(&pending_req->pendcnt)) {
+ int pending_idx = pending_req - pending_reqs;
+ fast_flush_area(pending_idx, pending_req->nr_pages);
+ make_response(pending_req->blkif, pending_req->id,
+ pending_req->operation, pending_req->status);
+ blkif_put(pending_req->blkif);
+ spin_lock_irqsave(&pend_prod_lock, flags);
+ pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
+ spin_unlock_irqrestore(&pend_prod_lock, flags);
+ maybe_trigger_blkio_schedule();
+ }
}
static int end_block_io_op(struct bio *bio, unsigned int done, int error)
{
- if ( bio->bi_size != 0 )
- return 1;
- __end_block_io_op(bio->bi_private, !error);
- bio_put(bio);
- return error;
+ if (bio->bi_size != 0)
+ return 1;
+ __end_block_io_op(bio->bi_private, !error);
+ bio_put(bio);
+ return error;
}
@@ -272,10 +271,10 @@
irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs)
{
- blkif_t *blkif = dev_id;
- add_to_blkdev_list_tail(blkif);
- maybe_trigger_blkio_schedule();
- return IRQ_HANDLED;
+ blkif_t *blkif = dev_id;
+ add_to_blkdev_list_tail(blkif);
+ maybe_trigger_blkio_schedule();
+ return IRQ_HANDLED;
}
@@ -286,183 +285,174 @@
static int do_block_io_op(blkif_t *blkif, int max_to_do)
{
- blkif_back_ring_t *blk_ring = &blkif->blk_ring;
- blkif_request_t *req;
- RING_IDX i, rp;
- int more_to_do = 0;
-
- rp = blk_ring->sring->req_prod;
- rmb(); /* Ensure we see queued requests up to 'rp'. */
-
- for ( i = blk_ring->req_cons;
- (i != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, i);
- i++ )
- {
- if ( (max_to_do-- == 0) || (NR_PENDING_REQS == MAX_PENDING_REQS) )
- {
- more_to_do = 1;
- break;
- }
+ blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+ blkif_request_t *req;
+ RING_IDX i, rp;
+ int more_to_do = 0;
+
+ rp = blk_ring->sring->req_prod;
+ rmb(); /* Ensure we see queued requests up to 'rp'. */
+
+ for (i = blk_ring->req_cons;
+ (i != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, i);
+ i++) {
+ if ((max_to_do-- == 0) ||
+ (NR_PENDING_REQS == MAX_PENDING_REQS)) {
+ more_to_do = 1;
+ break;
+ }
- req = RING_GET_REQUEST(blk_ring, i);
- switch ( req->operation )
- {
- case BLKIF_OP_READ:
- case BLKIF_OP_WRITE:
- dispatch_rw_block_io(blkif, req);
- break;
-
- default:
- DPRINTK("error: unknown block io operation [%d]\n",
- req->operation);
- make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
- break;
- }
- }
-
- blk_ring->req_cons = i;
- return more_to_do;
+ req = RING_GET_REQUEST(blk_ring, i);
+ switch (req->operation) {
+ case BLKIF_OP_READ:
+ case BLKIF_OP_WRITE:
+ dispatch_rw_block_io(blkif, req);
+ break;
+
+ default:
+ DPRINTK("error: unknown block io operation [%d]\n",
+ req->operation);
+ make_response(blkif, req->id, req->operation,
+ BLKIF_RSP_ERROR);
+ break;
+ }
+ }
+
+ blk_ring->req_cons = i;
+ return more_to_do;
}
static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
{
- extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]);
- int operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ;
- unsigned long fas = 0;
- int i, pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
- pending_req_t *pending_req;
- struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST];
- struct phys_req preq;
- struct {
- unsigned long buf; unsigned int nsec;
- } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
- unsigned int nseg;
- struct bio *bio = NULL, *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST];
- int nbio = 0;
- request_queue_t *q;
-
- /* Check that number of segments is sane. */
- nseg = req->nr_segments;
- if ( unlikely(nseg == 0) ||
- unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST) )
- {
- DPRINTK("Bad number of segments in request (%d)\n", nseg);
- goto bad_descriptor;
- }
-
- preq.dev = req->handle;
- preq.sector_number = req->sector_number;
- preq.nr_sects = 0;
-
- for ( i = 0; i < nseg; i++ )
- {
- fas = req->frame_and_sects[i];
- seg[i].nsec = blkif_last_sect(fas) - blkif_first_sect(fas) + 1;
-
- if ( seg[i].nsec <= 0 )
- goto bad_descriptor;
- preq.nr_sects += seg[i].nsec;
-
- map[i].host_addr = MMAP_VADDR(pending_idx, i);
- map[i].dom = blkif->domid;
- map[i].ref = blkif_gref_from_fas(fas);
- map[i].flags = GNTMAP_host_map;
- if ( operation == WRITE )
- map[i].flags |= GNTMAP_readonly;
- }
-
- if ( unlikely(HYPERVISOR_grant_table_op(
- GNTTABOP_map_grant_ref, map, nseg)))
- BUG();
-
- for ( i = 0; i < nseg; i++ )
- {
- if ( unlikely(map[i].handle < 0) )
- {
- DPRINTK("invalid buffer -- could not remap it\n");
- fast_flush_area(pending_idx, nseg);
- goto bad_descriptor;
- }
-
- phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] =
- FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT);
-
- pending_handle(pending_idx, i) = map[i].handle;
- }
-
- for ( i = 0; i < nseg; i++ )
- {
- fas = req->frame_and_sects[i];
- seg[i].buf = map[i].dev_bus_addr | (blkif_first_sect(fas) << 9);
- }
-
- if ( vbd_translate(&preq, blkif, operation) != 0 )
- {
- DPRINTK("access denied: %s of [%llu,%llu] on dev=%04x\n",
- operation == READ ? "read" : "write", preq.sector_number,
- preq.sector_number + preq.nr_sects, preq.dev);
- goto bad_descriptor;
- }
-
- pending_req = &pending_reqs[pending_idx];
- pending_req->blkif = blkif;
- pending_req->id = req->id;
- pending_req->operation = operation;
- pending_req->status = BLKIF_RSP_OKAY;
- pending_req->nr_pages = nseg;
-
- for ( i = 0; i < nseg; i++ )
- {
- if ( ((int)preq.sector_number|(int)seg[i].nsec) &
- ((bdev_hardsect_size(preq.bdev) >> 9) - 1) )
- {
- DPRINTK("Misaligned I/O request from domain %d", blkif->domid);
- goto cleanup_and_fail;
- }
-
- while ( (bio == NULL) ||
- (bio_add_page(bio,
- virt_to_page(MMAP_VADDR(pending_idx, i)),
- seg[i].nsec << 9,
- seg[i].buf & ~PAGE_MASK) == 0) )
- {
- bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, nseg-i);
- if ( unlikely(bio == NULL) )
- {
- cleanup_and_fail:
- for ( i = 0; i < (nbio-1); i++ )
- bio_put(biolist[i]);
- fast_flush_area(pending_idx, nseg);
- goto bad_descriptor;
- }
+ extern void ll_rw_block(int rw, int nr, struct buffer_head * bhs[]);
+ int operation = (req->operation == BLKIF_OP_WRITE) ? WRITE : READ;
+ unsigned long fas = 0;
+ int i, pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
+ pending_req_t *pending_req;
+ struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+ struct phys_req preq;
+ struct {
+ unsigned long buf; unsigned int nsec;
+ } seg[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+ unsigned int nseg;
+ struct bio *bio = NULL, *biolist[BLKIF_MAX_SEGMENTS_PER_REQUEST];
+ int nbio = 0;
+ request_queue_t *q;
+
+ /* Check that number of segments is sane. */
+ nseg = req->nr_segments;
+ if (unlikely(nseg == 0) ||
+ unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
+ DPRINTK("Bad number of segments in request (%d)\n", nseg);
+ goto bad_descriptor;
+ }
+
+ preq.dev = req->handle;
+ preq.sector_number = req->sector_number;
+ preq.nr_sects = 0;
+
+ for (i = 0; i < nseg; i++) {
+ fas = req->frame_and_sects[i];
+ seg[i].nsec = blkif_last_sect(fas) - blkif_first_sect(fas) + 1;
+
+ if (seg[i].nsec <= 0)
+ goto bad_descriptor;
+ preq.nr_sects += seg[i].nsec;
+
+ map[i].host_addr = MMAP_VADDR(pending_idx, i);
+ map[i].dom = blkif->domid;
+ map[i].ref = blkif_gref_from_fas(fas);
+ map[i].flags = GNTMAP_host_map;
+ if ( operation == WRITE )
+ map[i].flags |= GNTMAP_readonly;
+ }
+
+ BUG_ON(HYPERVISOR_grant_table_op(
+ GNTTABOP_map_grant_ref, map, nseg));
+
+ for (i = 0; i < nseg; i++) {
+ if (unlikely(map[i].handle < 0)) {
+ DPRINTK("invalid buffer -- could not remap it\n");
+ fast_flush_area(pending_idx, nseg);
+ goto bad_descriptor;
+ }
+
+ phys_to_machine_mapping[__pa(MMAP_VADDR(
+ pending_idx, i)) >> PAGE_SHIFT] =
+ FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT);
+
+ pending_handle(pending_idx, i) = map[i].handle;
+ }
+
+ for (i = 0; i < nseg; i++) {
+ fas = req->frame_and_sects[i];
+ seg[i].buf = map[i].dev_bus_addr |
+ (blkif_first_sect(fas) << 9);
+ }
+
+ if (vbd_translate(&preq, blkif, operation) != 0) {
+ DPRINTK("access denied: %s of [%llu,%llu] on dev=%04x\n",
+ operation == READ ? "read" : "write",
+ preq.sector_number,
+ preq.sector_number + preq.nr_sects, preq.dev);
+ goto bad_descriptor;
+ }
+
+ pending_req = &pending_reqs[pending_idx];
+ pending_req->blkif = blkif;
+ pending_req->id = req->id;
+ pending_req->operation = operation;
+ pending_req->status = BLKIF_RSP_OKAY;
+ pending_req->nr_pages = nseg;
+
+ for (i = 0; i < nseg; i++) {
+ if (((int)preq.sector_number|(int)seg[i].nsec) &
+ ((bdev_hardsect_size(preq.bdev) >> 9) - 1)) {
+ DPRINTK("Misaligned I/O request from domain %d",
+ blkif->domid);
+ goto cleanup_and_fail;
+ }
+
+ while ((bio == NULL) ||
+ (bio_add_page(bio,
+ virt_to_page(MMAP_VADDR(pending_idx, i)),
+ seg[i].nsec << 9,
+ seg[i].buf & ~PAGE_MASK) == 0)) {
+ bio = biolist[nbio++] = bio_alloc(GFP_KERNEL, nseg-i);
+ if (unlikely(bio == NULL)) {
+ cleanup_and_fail:
+ for (i = 0; i < (nbio-1); i++)
+ bio_put(biolist[i]);
+ fast_flush_area(pending_idx, nseg);
+ goto bad_descriptor;
+ }
- bio->bi_bdev = preq.bdev;
- bio->bi_private = pending_req;
- bio->bi_end_io = end_block_io_op;
- bio->bi_sector = preq.sector_number;
- }
-
- preq.sector_number += seg[i].nsec;
- }
-
- if ( (q = bdev_get_queue(bio->bi_bdev)) != plugged_queue )
- {
- flush_plugged_queue();
- blk_get_queue(q);
- plugged_queue = q;
- }
-
- atomic_set(&pending_req->pendcnt, nbio);
- pending_cons++;
- blkif_get(blkif);
-
- for ( i = 0; i < nbio; i++ )
- submit_bio(operation, biolist[i]);
-
- return;
+ bio->bi_bdev = preq.bdev;
+ bio->bi_private = pending_req;
+ bio->bi_end_io = end_block_io_op;
+ bio->bi_sector = preq.sector_number;
+ }
+
+ preq.sector_number += seg[i].nsec;
+ }
+
+ if ((q = bdev_get_queue(bio->bi_bdev)) != plugged_queue) {
+ flush_plugged_queue();
+ blk_get_queue(q);
+ plugged_queue = q;
+ }
+
+ atomic_set(&pending_req->pendcnt, nbio);
+ pending_cons++;
+ blkif_get(blkif);
+
+ for (i = 0; i < nbio; i++)
+ submit_bio(operation, biolist[i]);
+
+ return;
bad_descriptor:
- make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
+ make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
}
@@ -475,66 +465,71 @@
static void make_response(blkif_t *blkif, unsigned long id,
unsigned short op, int st)
{
- blkif_response_t *resp;
- unsigned long flags;
- blkif_back_ring_t *blk_ring = &blkif->blk_ring;
-
- /* Place on the response ring for the relevant domain. */
- spin_lock_irqsave(&blkif->blk_ring_lock, flags);
- resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt);
- resp->id = id;
- resp->operation = op;
- resp->status = st;
- wmb(); /* Ensure other side can see the response fields. */
- blk_ring->rsp_prod_pvt++;
- RING_PUSH_RESPONSES(blk_ring);
- spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
-
- /* Kick the relevant domain. */
- notify_via_evtchn(blkif->evtchn);
+ blkif_response_t *resp;
+ unsigned long flags;
+ blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+
+ /* Place on the response ring for the relevant domain. */
+ spin_lock_irqsave(&blkif->blk_ring_lock, flags);
+ resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt);
+ resp->id = id;
+ resp->operation = op;
+ resp->status = st;
+ wmb(); /* Ensure other side can see the response fields. */
+ blk_ring->rsp_prod_pvt++;
+ RING_PUSH_RESPONSES(blk_ring);
+ spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
+
+ /* Kick the relevant domain. */
+ notify_via_evtchn(blkif->evtchn);
}
void blkif_deschedule(blkif_t *blkif)
{
- remove_from_blkdev_list(blkif);
+ remove_from_blkdev_list(blkif);
}
static int __init blkif_init(void)
{
- int i;
- struct page *page;
-
- if ( !(xen_start_info->flags & SIF_INITDOMAIN) &&
- !(xen_start_info->flags & SIF_BLK_BE_DOMAIN) )
- return 0;
-
- blkif_interface_init();
-
- page = balloon_alloc_empty_page_range(MMAP_PAGES);
- BUG_ON(page == NULL);
- mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
-
- pending_cons = 0;
- pending_prod = MAX_PENDING_REQS;
- memset(pending_reqs, 0, sizeof(pending_reqs));
- for ( i = 0; i < MAX_PENDING_REQS; i++ )
- pending_ring[i] = i;
+ int i;
+ struct page *page;
+
+ if (!(xen_start_info->flags & SIF_INITDOMAIN) &&
+ !(xen_start_info->flags & SIF_BLK_BE_DOMAIN))
+ return 0;
+
+ blkif_interface_init();
+
+ page = balloon_alloc_empty_page_range(MMAP_PAGES);
+ BUG_ON(page == NULL);
+ mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
+
+ pending_cons = 0;
+ pending_prod = MAX_PENDING_REQS;
+ memset(pending_reqs, 0, sizeof(pending_reqs));
+ for (i = 0; i < MAX_PENDING_REQS; i++)
+ pending_ring[i] = i;
- spin_lock_init(&blkio_schedule_list_lock);
- INIT_LIST_HEAD(&blkio_schedule_list);
-
- if ( kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0 )
- BUG();
-
- blkif_xenbus_init();
-
- memset( pending_grant_handles, BLKBACK_INVALID_HANDLE, MMAP_PAGES );
-
-#ifdef CONFIG_XEN_BLKDEV_TAP_BE
- printk(KERN_ALERT "NOTE: Blkif backend is running with tap support on!\n");
-#endif
-
- return 0;
+ spin_lock_init(&blkio_schedule_list_lock);
+ INIT_LIST_HEAD(&blkio_schedule_list);
+
+ BUG_ON(kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0);
+
+ blkif_xenbus_init();
+
+ memset(pending_grant_handles, BLKBACK_INVALID_HANDLE, MMAP_PAGES);
+
+ return 0;
}
__initcall(blkif_init);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/blkback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/common.h Thu Sep 22 15:12:14 2005
@@ -31,39 +31,39 @@
#endif
struct vbd {
- blkif_vdev_t handle; /* what the domain refers to this vbd as */
- unsigned char readonly; /* Non-zero -> read-only */
- unsigned char type; /* VDISK_xxx */
- u32 pdevice; /* phys device that this vbd maps to */
- struct block_device *bdev;
+ blkif_vdev_t handle; /* what the domain refers to this vbd as */
+ unsigned char readonly; /* Non-zero -> read-only */
+ unsigned char type; /* VDISK_xxx */
+ u32 pdevice; /* phys device that this vbd maps to */
+ struct block_device *bdev;
};
typedef struct blkif_st {
- /* Unique identifier for this interface. */
- domid_t domid;
- unsigned int handle;
- /* Physical parameters of the comms window. */
- unsigned int evtchn;
- unsigned int remote_evtchn;
- /* Comms information. */
- blkif_back_ring_t blk_ring;
- struct vm_struct *blk_ring_area;
- /* VBDs attached to this interface. */
- struct vbd vbd;
- /* Private fields. */
- enum { DISCONNECTED, CONNECTED } status;
+ /* Unique identifier for this interface. */
+ domid_t domid;
+ unsigned int handle;
+ /* Physical parameters of the comms window. */
+ unsigned int evtchn;
+ unsigned int remote_evtchn;
+ /* Comms information. */
+ blkif_back_ring_t blk_ring;
+ struct vm_struct *blk_ring_area;
+ /* VBDs attached to this interface. */
+ struct vbd vbd;
+ /* Private fields. */
+ enum { DISCONNECTED, CONNECTED } status;
#ifdef CONFIG_XEN_BLKDEV_TAP_BE
- /* Is this a blktap frontend */
- unsigned int is_blktap;
+ /* Is this a blktap frontend */
+ unsigned int is_blktap;
#endif
- struct list_head blkdev_list;
- spinlock_t blk_ring_lock;
- atomic_t refcnt;
+ struct list_head blkdev_list;
+ spinlock_t blk_ring_lock;
+ atomic_t refcnt;
- struct work_struct free_work;
+ struct work_struct free_work;
- u16 shmem_handle;
- grant_ref_t shmem_ref;
+ u16 shmem_handle;
+ grant_ref_t shmem_ref;
} blkif_t;
blkif_t *alloc_blkif(domid_t domid);
@@ -71,11 +71,11 @@
int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn);
#define blkif_get(_b) (atomic_inc(&(_b)->refcnt))
-#define blkif_put(_b) \
- do { \
- if ( atomic_dec_and_test(&(_b)->refcnt) ) \
- free_blkif_callback(_b); \
- } while (0)
+#define blkif_put(_b) \
+ do { \
+ if (atomic_dec_and_test(&(_b)->refcnt)) \
+ free_blkif_callback(_b); \
+ } while (0)
/* Create a vbd. */
int vbd_create(blkif_t *blkif, blkif_vdev_t vdevice, u32 pdevice,
@@ -87,10 +87,10 @@
unsigned long vbd_secsize(struct vbd *vbd);
struct phys_req {
- unsigned short dev;
- unsigned short nr_sects;
- struct block_device *bdev;
- blkif_sector_t sector_number;
+ unsigned short dev;
+ unsigned short nr_sects;
+ struct block_device *bdev;
+ blkif_sector_t sector_number;
};
int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation);
@@ -104,3 +104,13 @@
irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs);
#endif /* __BLKIF__BACKEND__COMMON_H__ */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/blkback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Thu Sep 22
15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/interface.c Thu Sep 22
15:12:14 2005
@@ -13,134 +13,144 @@
blkif_t *alloc_blkif(domid_t domid)
{
- blkif_t *blkif;
+ blkif_t *blkif;
- blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL);
- if (!blkif)
- return ERR_PTR(-ENOMEM);
+ blkif = kmem_cache_alloc(blkif_cachep, GFP_KERNEL);
+ if (!blkif)
+ return ERR_PTR(-ENOMEM);
- memset(blkif, 0, sizeof(*blkif));
- blkif->domid = domid;
- blkif->status = DISCONNECTED;
- spin_lock_init(&blkif->blk_ring_lock);
- atomic_set(&blkif->refcnt, 1);
+ memset(blkif, 0, sizeof(*blkif));
+ blkif->domid = domid;
+ blkif->status = DISCONNECTED;
+ spin_lock_init(&blkif->blk_ring_lock);
+ atomic_set(&blkif->refcnt, 1);
- return blkif;
+ return blkif;
}
static int map_frontend_page(blkif_t *blkif, unsigned long shared_page)
{
- struct gnttab_map_grant_ref op;
+ struct gnttab_map_grant_ref op;
- op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
- op.flags = GNTMAP_host_map;
- op.ref = shared_page;
- op.dom = blkif->domid;
+ op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
+ op.flags = GNTMAP_host_map;
+ op.ref = shared_page;
+ op.dom = blkif->domid;
- lock_vm_area(blkif->blk_ring_area);
- BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
- unlock_vm_area(blkif->blk_ring_area);
+ lock_vm_area(blkif->blk_ring_area);
+ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1));
+ unlock_vm_area(blkif->blk_ring_area);
- if (op.handle < 0) {
- DPRINTK(" Grant table operation failure !\n");
- return op.handle;
- }
+ if (op.handle < 0) {
+ DPRINTK(" Grant table operation failure !\n");
+ return op.handle;
+ }
- blkif->shmem_ref = shared_page;
- blkif->shmem_handle = op.handle;
+ blkif->shmem_ref = shared_page;
+ blkif->shmem_handle = op.handle;
- return 0;
+ return 0;
}
static void unmap_frontend_page(blkif_t *blkif)
{
- struct gnttab_unmap_grant_ref op;
+ struct gnttab_unmap_grant_ref op;
- op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
- op.handle = blkif->shmem_handle;
- op.dev_bus_addr = 0;
+ op.host_addr = (unsigned long)blkif->blk_ring_area->addr;
+ op.handle = blkif->shmem_handle;
+ op.dev_bus_addr = 0;
- lock_vm_area(blkif->blk_ring_area);
- BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
- unlock_vm_area(blkif->blk_ring_area);
+ lock_vm_area(blkif->blk_ring_area);
+ BUG_ON(HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1));
+ unlock_vm_area(blkif->blk_ring_area);
}
int blkif_map(blkif_t *blkif, unsigned long shared_page, unsigned int evtchn)
{
- blkif_sring_t *sring;
- evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
- int err;
+ blkif_sring_t *sring;
+ evtchn_op_t op = { .cmd = EVTCHNOP_bind_interdomain };
+ int err;
- BUG_ON(blkif->remote_evtchn);
+ BUG_ON(blkif->remote_evtchn);
- if ( (blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL )
- return -ENOMEM;
+ if ( (blkif->blk_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL )
+ return -ENOMEM;
- err = map_frontend_page(blkif, shared_page);
- if (err) {
- free_vm_area(blkif->blk_ring_area);
- return err;
- }
+ err = map_frontend_page(blkif, shared_page);
+ if (err) {
+ free_vm_area(blkif->blk_ring_area);
+ return err;
+ }
- op.u.bind_interdomain.dom1 = DOMID_SELF;
- op.u.bind_interdomain.dom2 = blkif->domid;
- op.u.bind_interdomain.port1 = 0;
- op.u.bind_interdomain.port2 = evtchn;
- err = HYPERVISOR_event_channel_op(&op);
- if (err) {
- unmap_frontend_page(blkif);
- free_vm_area(blkif->blk_ring_area);
- return err;
- }
+ op.u.bind_interdomain.dom1 = DOMID_SELF;
+ op.u.bind_interdomain.dom2 = blkif->domid;
+ op.u.bind_interdomain.port1 = 0;
+ op.u.bind_interdomain.port2 = evtchn;
+ err = HYPERVISOR_event_channel_op(&op);
+ if (err) {
+ unmap_frontend_page(blkif);
+ free_vm_area(blkif->blk_ring_area);
+ return err;
+ }
- blkif->evtchn = op.u.bind_interdomain.port1;
- blkif->remote_evtchn = evtchn;
+ blkif->evtchn = op.u.bind_interdomain.port1;
+ blkif->remote_evtchn = evtchn;
- sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
- SHARED_RING_INIT(sring);
- BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);
+ sring = (blkif_sring_t *)blkif->blk_ring_area->addr;
+ SHARED_RING_INIT(sring);
+ BACK_RING_INIT(&blkif->blk_ring, sring, PAGE_SIZE);
- bind_evtchn_to_irqhandler(blkif->evtchn, blkif_be_int, 0, "blkif-backend",
- blkif);
- blkif->status = CONNECTED;
+ bind_evtchn_to_irqhandler(
+ blkif->evtchn, blkif_be_int, 0, "blkif-backend", blkif);
+ blkif->status = CONNECTED;
- return 0;
+ return 0;
}
static void free_blkif(void *arg)
{
- evtchn_op_t op = { .cmd = EVTCHNOP_close };
- blkif_t *blkif = (blkif_t *)arg;
+ evtchn_op_t op = { .cmd = EVTCHNOP_close };
+ blkif_t *blkif = (blkif_t *)arg;
- op.u.close.port = blkif->evtchn;
- op.u.close.dom = DOMID_SELF;
- HYPERVISOR_event_channel_op(&op);
- op.u.close.port = blkif->remote_evtchn;
- op.u.close.dom = blkif->domid;
- HYPERVISOR_event_channel_op(&op);
+ op.u.close.port = blkif->evtchn;
+ op.u.close.dom = DOMID_SELF;
+ HYPERVISOR_event_channel_op(&op);
+ op.u.close.port = blkif->remote_evtchn;
+ op.u.close.dom = blkif->domid;
+ HYPERVISOR_event_channel_op(&op);
- vbd_free(&blkif->vbd);
+ vbd_free(&blkif->vbd);
- if (blkif->evtchn)
- unbind_evtchn_from_irqhandler(blkif->evtchn, blkif);
+ if (blkif->evtchn)
+ unbind_evtchn_from_irqhandler(blkif->evtchn, blkif);
- if (blkif->blk_ring.sring) {
- unmap_frontend_page(blkif);
- free_vm_area(blkif->blk_ring_area);
- blkif->blk_ring.sring = NULL;
- }
+ if (blkif->blk_ring.sring) {
+ unmap_frontend_page(blkif);
+ free_vm_area(blkif->blk_ring_area);
+ blkif->blk_ring.sring = NULL;
+ }
- kmem_cache_free(blkif_cachep, blkif);
+ kmem_cache_free(blkif_cachep, blkif);
}
void free_blkif_callback(blkif_t *blkif)
{
- INIT_WORK(&blkif->free_work, free_blkif, (void *)blkif);
- schedule_work(&blkif->free_work);
+ INIT_WORK(&blkif->free_work, free_blkif, (void *)blkif);
+ schedule_work(&blkif->free_work);
}
void __init blkif_interface_init(void)
{
- blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t),
- 0, 0, NULL, NULL);
+ blkif_cachep = kmem_cache_create("blkif_cache", sizeof(blkif_t),
+ 0, 0, NULL, NULL);
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/vbd.c Thu Sep 22 15:12:14 2005
@@ -11,10 +11,10 @@
static inline dev_t vbd_map_devnum(u32 cookie)
{
- return MKDEV(BLKIF_MAJOR(cookie), BLKIF_MINOR(cookie));
+ return MKDEV(BLKIF_MAJOR(cookie), BLKIF_MINOR(cookie));
}
-#define vbd_sz(_v) ((_v)->bdev->bd_part ? \
- (_v)->bdev->bd_part->nr_sects : (_v)->bdev->bd_disk->capacity)
+#define vbd_sz(_v) ((_v)->bdev->bd_part ? \
+ (_v)->bdev->bd_part->nr_sects : (_v)->bdev->bd_disk->capacity)
#define bdev_put(_b) blkdev_put(_b)
unsigned long vbd_size(struct vbd *vbd)
@@ -35,63 +35,73 @@
int vbd_create(blkif_t *blkif, blkif_vdev_t handle,
u32 pdevice, int readonly)
{
- struct vbd *vbd;
+ struct vbd *vbd;
- vbd = &blkif->vbd;
- vbd->handle = handle;
- vbd->readonly = readonly;
- vbd->type = 0;
+ vbd = &blkif->vbd;
+ vbd->handle = handle;
+ vbd->readonly = readonly;
+ vbd->type = 0;
- vbd->pdevice = pdevice;
+ vbd->pdevice = pdevice;
- vbd->bdev = open_by_devnum(
- vbd_map_devnum(vbd->pdevice),
- vbd->readonly ? FMODE_READ : FMODE_WRITE);
- if ( IS_ERR(vbd->bdev) )
- {
- DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice);
- return -ENOENT;
- }
+ vbd->bdev = open_by_devnum(
+ vbd_map_devnum(vbd->pdevice),
+ vbd->readonly ? FMODE_READ : FMODE_WRITE);
+ if (IS_ERR(vbd->bdev)) {
+ DPRINTK("vbd_creat: device %08x doesn't exist.\n",
+ vbd->pdevice);
+ return -ENOENT;
+ }
- if ( (vbd->bdev->bd_disk == NULL) )
- {
- DPRINTK("vbd_creat: device %08x doesn't exist.\n", vbd->pdevice);
- vbd_free(vbd);
- return -ENOENT;
- }
+ if (vbd->bdev->bd_disk == NULL) {
+ DPRINTK("vbd_creat: device %08x doesn't exist.\n",
+ vbd->pdevice);
+ vbd_free(vbd);
+ return -ENOENT;
+ }
- if ( vbd->bdev->bd_disk->flags & GENHD_FL_CD )
- vbd->type |= VDISK_CDROM;
- if ( vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE )
- vbd->type |= VDISK_REMOVABLE;
+ if (vbd->bdev->bd_disk->flags & GENHD_FL_CD)
+ vbd->type |= VDISK_CDROM;
+ if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE)
+ vbd->type |= VDISK_REMOVABLE;
- DPRINTK("Successful creation of handle=%04x (dom=%u)\n",
- handle, blkif->domid);
- return 0;
+ DPRINTK("Successful creation of handle=%04x (dom=%u)\n",
+ handle, blkif->domid);
+ return 0;
}
void vbd_free(struct vbd *vbd)
{
- if (vbd->bdev)
- bdev_put(vbd->bdev);
- vbd->bdev = NULL;
+ if (vbd->bdev)
+ bdev_put(vbd->bdev);
+ vbd->bdev = NULL;
}
int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation)
{
- struct vbd *vbd = &blkif->vbd;
- int rc = -EACCES;
+ struct vbd *vbd = &blkif->vbd;
+ int rc = -EACCES;
- if ((operation == WRITE) && vbd->readonly)
- goto out;
+ if ((operation == WRITE) && vbd->readonly)
+ goto out;
- if (unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd)))
- goto out;
+ if (unlikely((req->sector_number + req->nr_sects) > vbd_sz(vbd)))
+ goto out;
- req->dev = vbd->pdevice;
- req->bdev = vbd->bdev;
- rc = 0;
+ req->dev = vbd->pdevice;
+ req->bdev = vbd->bdev;
+ rc = 0;
out:
- return rc;
+ return rc;
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c Thu Sep 22 15:12:14 2005
@@ -124,7 +124,7 @@
return;
-abort:
+ abort:
xenbus_transaction_end(1);
}
@@ -278,3 +278,13 @@
{
xenbus_register_backend(&blkback);
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/blkfront/block.h
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h Thu Sep 22 15:12:14 2005
@@ -146,4 +146,15 @@
int xlvbd_add(blkif_sector_t capacity, int device,
u16 vdisk_info, u16 sector_size, struct blkfront_info *info);
void xlvbd_del(struct blkfront_info *info);
+
#endif /* __XEN_DRIVERS_BLOCK_H__ */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c
--- a/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c Thu Sep 22 15:12:14 2005
@@ -65,7 +65,7 @@
};
static struct xlbd_major_info *major_info[NUM_IDE_MAJORS + NUM_SCSI_MAJORS +
- NUM_VBD_MAJORS];
+ NUM_VBD_MAJORS];
#define XLBD_MAJOR_IDE_START 0
#define XLBD_MAJOR_SCSI_START (NUM_IDE_MAJORS)
@@ -309,3 +309,13 @@
bdput(bd);
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/blktap.c Thu Sep 22 15:12:14 2005
@@ -4,7 +4,6 @@
* This is a modified version of the block backend driver that remaps requests
* to a user-space memory region. It is intended to be used to write
* application-level servers that provide block interfaces to client VMs.
- *
*/
#include <linux/kernel.h>
@@ -67,20 +66,19 @@
static inline int BLKTAP_MODE_VALID(unsigned long arg)
{
- return (
- ( arg == BLKTAP_MODE_PASSTHROUGH ) ||
- ( arg == BLKTAP_MODE_INTERCEPT_FE ) ||
- ( arg == BLKTAP_MODE_INTERPOSE ) );
+ return ((arg == BLKTAP_MODE_PASSTHROUGH ) ||
+ (arg == BLKTAP_MODE_INTERCEPT_FE) ||
+ (arg == BLKTAP_MODE_INTERPOSE ));
/*
- return (
- ( arg == BLKTAP_MODE_PASSTHROUGH ) ||
- ( arg == BLKTAP_MODE_INTERCEPT_FE ) ||
- ( arg == BLKTAP_MODE_INTERCEPT_BE ) ||
- ( arg == BLKTAP_MODE_INTERPOSE ) ||
- ( (arg & ~BLKTAP_MODE_COPY_FE_PAGES) == BLKTAP_MODE_COPY_FE ) ||
- ( (arg & ~BLKTAP_MODE_COPY_BE_PAGES) == BLKTAP_MODE_COPY_BE ) ||
- ( (arg & ~BLKTAP_MODE_COPY_BOTH_PAGES) == BLKTAP_MODE_COPY_BOTH )
- );
+ return (
+ ( arg == BLKTAP_MODE_PASSTHROUGH ) ||
+ ( arg == BLKTAP_MODE_INTERCEPT_FE ) ||
+ ( arg == BLKTAP_MODE_INTERCEPT_BE ) ||
+ ( arg == BLKTAP_MODE_INTERPOSE ) ||
+ ( (arg & ~BLKTAP_MODE_COPY_FE_PAGES) == BLKTAP_MODE_COPY_FE ) ||
+ ( (arg & ~BLKTAP_MODE_COPY_BE_PAGES) == BLKTAP_MODE_COPY_BE ) ||
+ ( (arg & ~BLKTAP_MODE_COPY_BOTH_PAGES) == BLKTAP_MODE_COPY_BOTH )
+ );
*/
}
@@ -110,14 +108,12 @@
unsigned long rings_vstart; /* start of mmaped vma */
unsigned long user_vstart; /* start of user mappings */
-#define MMAP_PAGES \
- (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
-#define MMAP_VADDR(_start, _req,_seg) \
- (_start + \
- ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) + \
- ((_seg) * PAGE_SIZE))
-
-
+#define MMAP_PAGES \
+ (MAX_PENDING_REQS * BLKIF_MAX_SEGMENTS_PER_REQUEST)
+#define MMAP_VADDR(_start, _req,_seg) \
+ (_start + \
+ ((_req) * BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE) + \
+ ((_seg) * PAGE_SIZE))
/*
* Each outstanding request that we've passed to the lower device layers has a
@@ -126,12 +122,12 @@
* response queued for it, with the saved 'id' passed back.
*/
typedef struct {
- blkif_t *blkif;
- unsigned long id;
- int nr_pages;
- atomic_t pendcnt;
- unsigned short operation;
- int status;
+ blkif_t *blkif;
+ unsigned long id;
+ int nr_pages;
+ atomic_t pendcnt;
+ unsigned short operation;
+ int status;
} pending_req_t;
/*
@@ -156,17 +152,17 @@
static inline unsigned long MAKE_ID(domid_t fe_dom, PEND_RING_IDX idx)
{
- return ( (fe_dom << 16) | MASK_PEND_IDX(idx) );
+ return ((fe_dom << 16) | MASK_PEND_IDX(idx));
}
extern inline PEND_RING_IDX ID_TO_IDX(unsigned long id)
{
- return (PEND_RING_IDX)( id & 0x0000ffff );
+ return (PEND_RING_IDX)(id & 0x0000ffff);
}
extern inline domid_t ID_TO_DOM(unsigned long id)
{
- return (domid_t)(id >> 16);
+ return (domid_t)(id >> 16);
}
@@ -181,8 +177,8 @@
*/
struct grant_handle_pair
{
- u16 kernel;
- u16 user;
+ u16 kernel;
+ u16 user;
};
static struct grant_handle_pair pending_grant_handles[MMAP_PAGES];
#define pending_handle(_idx, _i) \
@@ -199,21 +195,20 @@
*/
static struct page *blktap_nopage(struct vm_area_struct *vma,
- unsigned long address,
- int *type)
-{
- /*
- * if the page has not been mapped in by the driver then generate
- * a SIGBUS to the domain.
- */
-
- force_sig(SIGBUS, current);
-
- return 0;
+ unsigned long address,
+ int *type)
+{
+ /*
+ * if the page has not been mapped in by the driver then generate
+ * a SIGBUS to the domain.
+ */
+ force_sig(SIGBUS, current);
+
+ return 0;
}
struct vm_operations_struct blktap_vm_ops = {
- nopage: blktap_nopage,
+ nopage: blktap_nopage,
};
/******************************************************************
@@ -222,44 +217,45 @@
static int blktap_open(struct inode *inode, struct file *filp)
{
- blkif_sring_t *sring;
+ blkif_sring_t *sring;
+
+ if (test_and_set_bit(0, &blktap_dev_inuse))
+ return -EBUSY;
- if ( test_and_set_bit(0, &blktap_dev_inuse) )
- return -EBUSY;
+ /* Allocate the fe ring. */
+ sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
+ if (sring == NULL)
+ goto fail_nomem;
+
+ SetPageReserved(virt_to_page(sring));
- /* Allocate the fe ring. */
- sring = (blkif_sring_t *)get_zeroed_page(GFP_KERNEL);
- if (sring == NULL)
- goto fail_nomem;
-
- SetPageReserved(virt_to_page(sring));
-
- SHARED_RING_INIT(sring);
- FRONT_RING_INIT(&blktap_ufe_ring, sring, PAGE_SIZE);
-
- return 0;
+ SHARED_RING_INIT(sring);
+ FRONT_RING_INIT(&blktap_ufe_ring, sring, PAGE_SIZE);
+
+ return 0;
fail_nomem:
- return -ENOMEM;
+ return -ENOMEM;
}
static int blktap_release(struct inode *inode, struct file *filp)
{
- blktap_dev_inuse = 0;
- blktap_ring_ok = 0;
-
- /* Free the ring page. */
- ClearPageReserved(virt_to_page(blktap_ufe_ring.sring));
- free_page((unsigned long) blktap_ufe_ring.sring);
-
- /* Clear any active mappings and free foreign map table */
- if (blktap_vma != NULL) {
- zap_page_range(blktap_vma, blktap_vma->vm_start,
- blktap_vma->vm_end - blktap_vma->vm_start, NULL);
- blktap_vma = NULL;
- }
-
- return 0;
+ blktap_dev_inuse = 0;
+ blktap_ring_ok = 0;
+
+ /* Free the ring page. */
+ ClearPageReserved(virt_to_page(blktap_ufe_ring.sring));
+ free_page((unsigned long) blktap_ufe_ring.sring);
+
+ /* Clear any active mappings and free foreign map table */
+ if (blktap_vma != NULL) {
+ zap_page_range(
+ blktap_vma, blktap_vma->vm_start,
+ blktap_vma->vm_end - blktap_vma->vm_start, NULL);
+ blktap_vma = NULL;
+ }
+
+ return 0;
}
@@ -283,128 +279,124 @@
*/
static int blktap_mmap(struct file *filp, struct vm_area_struct *vma)
{
- int size;
- struct page **map;
- int i;
-
- DPRINTK(KERN_ALERT "blktap mmap (%lx, %lx)\n",
- vma->vm_start, vma->vm_end);
-
- vma->vm_flags |= VM_RESERVED;
- vma->vm_ops = &blktap_vm_ops;
-
- size = vma->vm_end - vma->vm_start;
- if ( size != ( (MMAP_PAGES + RING_PAGES) << PAGE_SHIFT ) ) {
- printk(KERN_INFO
- "blktap: you _must_ map exactly %d pages!\n",
- MMAP_PAGES + RING_PAGES);
- return -EAGAIN;
- }
-
- size >>= PAGE_SHIFT;
- DPRINTK(KERN_INFO "blktap: 2 rings + %d pages.\n", size-1);
+ int size;
+ struct page **map;
+ int i;
+
+ DPRINTK(KERN_ALERT "blktap mmap (%lx, %lx)\n",
+ vma->vm_start, vma->vm_end);
+
+ vma->vm_flags |= VM_RESERVED;
+ vma->vm_ops = &blktap_vm_ops;
+
+ size = vma->vm_end - vma->vm_start;
+ if (size != ((MMAP_PAGES + RING_PAGES) << PAGE_SHIFT)) {
+ printk(KERN_INFO
+ "blktap: you _must_ map exactly %d pages!\n",
+ MMAP_PAGES + RING_PAGES);
+ return -EAGAIN;
+ }
+
+ size >>= PAGE_SHIFT;
+ DPRINTK(KERN_INFO "blktap: 2 rings + %d pages.\n", size-1);
- rings_vstart = vma->vm_start;
- user_vstart = rings_vstart + (RING_PAGES << PAGE_SHIFT);
+ rings_vstart = vma->vm_start;
+ user_vstart = rings_vstart + (RING_PAGES << PAGE_SHIFT);
- /* Map the ring pages to the start of the region and reserve it. */
-
- /* not sure if I really need to do this... */
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
- if (remap_pfn_range(vma, vma->vm_start,
- __pa(blktap_ufe_ring.sring) >> PAGE_SHIFT,
- PAGE_SIZE, vma->vm_page_prot))
- {
- WPRINTK("Mapping user ring failed!\n");
- goto fail;
- }
-
- /* Mark this VM as containing foreign pages, and set up mappings. */
- map = kmalloc(((vma->vm_end - vma->vm_start) >> PAGE_SHIFT)
- * sizeof(struct page_struct*),
- GFP_KERNEL);
- if (map == NULL)
- {
- WPRINTK("Couldn't alloc VM_FOREIGH map.\n");
- goto fail;
- }
-
- for (i=0; i<((vma->vm_end - vma->vm_start) >> PAGE_SHIFT); i++)
- map[i] = NULL;
+ /* Map the ring pages to the start of the region and reserve it. */
+
+ /* not sure if I really need to do this... */
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+ if (remap_pfn_range(vma, vma->vm_start,
+ __pa(blktap_ufe_ring.sring) >> PAGE_SHIFT,
+ PAGE_SIZE, vma->vm_page_prot)) {
+ WPRINTK("Mapping user ring failed!\n");
+ goto fail;
+ }
+
+ /* Mark this VM as containing foreign pages, and set up mappings. */
+ map = kmalloc(((vma->vm_end - vma->vm_start) >> PAGE_SHIFT)
+ * sizeof(struct page_struct*),
+ GFP_KERNEL);
+ if (map == NULL) {
+ WPRINTK("Couldn't alloc VM_FOREIGH map.\n");
+ goto fail;
+ }
+
+ for (i = 0; i < ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT); i++)
+ map[i] = NULL;
- vma->vm_private_data = map;
- vma->vm_flags |= VM_FOREIGN;
-
- blktap_vma = vma;
- blktap_ring_ok = 1;
-
- return 0;
+ vma->vm_private_data = map;
+ vma->vm_flags |= VM_FOREIGN;
+
+ blktap_vma = vma;
+ blktap_ring_ok = 1;
+
+ return 0;
fail:
- /* Clear any active mappings. */
- zap_page_range(vma, vma->vm_start,
- vma->vm_end - vma->vm_start, NULL);
-
- return -ENOMEM;
+ /* Clear any active mappings. */
+ zap_page_range(vma, vma->vm_start,
+ vma->vm_end - vma->vm_start, NULL);
+
+ return -ENOMEM;
}
static int blktap_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long arg)
{
- switch(cmd) {
- case BLKTAP_IOCTL_KICK_FE: /* There are fe messages to process. */
- return blktap_read_ufe_ring();
-
- case BLKTAP_IOCTL_SETMODE:
- if (BLKTAP_MODE_VALID(arg)) {
- blktap_mode = arg;
- /* XXX: may need to flush rings here. */
- printk(KERN_INFO "blktap: set mode to %lx\n", arg);
- return 0;
- }
- case BLKTAP_IOCTL_PRINT_IDXS:
+ switch(cmd) {
+ case BLKTAP_IOCTL_KICK_FE: /* There are fe messages to process. */
+ return blktap_read_ufe_ring();
+
+ case BLKTAP_IOCTL_SETMODE:
+ if (BLKTAP_MODE_VALID(arg)) {
+ blktap_mode = arg;
+ /* XXX: may need to flush rings here. */
+ printk(KERN_INFO "blktap: set mode to %lx\n", arg);
+ return 0;
+ }
+ case BLKTAP_IOCTL_PRINT_IDXS:
{
- //print_fe_ring_idxs();
- WPRINTK("User Rings: \n-----------\n");
- WPRINTK("UF: rsp_cons: %2d, req_prod_prv: %2d "
- "| req_prod: %2d, rsp_prod: %2d\n",
- blktap_ufe_ring.rsp_cons,
- blktap_ufe_ring.req_prod_pvt,
- blktap_ufe_ring.sring->req_prod,
- blktap_ufe_ring.sring->rsp_prod);
+ //print_fe_ring_idxs();
+ WPRINTK("User Rings: \n-----------\n");
+ WPRINTK("UF: rsp_cons: %2d, req_prod_prv: %2d "
+ "| req_prod: %2d, rsp_prod: %2d\n",
+ blktap_ufe_ring.rsp_cons,
+ blktap_ufe_ring.req_prod_pvt,
+ blktap_ufe_ring.sring->req_prod,
+ blktap_ufe_ring.sring->rsp_prod);
}
- }
- return -ENOIOCTLCMD;
+ }
+ return -ENOIOCTLCMD;
}
static unsigned int blktap_poll(struct file *file, poll_table *wait)
{
- poll_wait(file, &blktap_wait, wait);
- if ( RING_HAS_UNPUSHED_REQUESTS(&blktap_ufe_ring) )
- {
- flush_tlb_all();
-
- RING_PUSH_REQUESTS(&blktap_ufe_ring);
- return POLLIN | POLLRDNORM;
- }
-
- return 0;
+ poll_wait(file, &blktap_wait, wait);
+ if (RING_HAS_UNPUSHED_REQUESTS(&blktap_ufe_ring)) {
+ flush_tlb_all();
+ RING_PUSH_REQUESTS(&blktap_ufe_ring);
+ return POLLIN | POLLRDNORM;
+ }
+
+ return 0;
}
void blktap_kick_user(void)
{
- /* blktap_ring->req_prod = blktap_req_prod; */
- wake_up_interruptible(&blktap_wait);
+ /* blktap_ring->req_prod = blktap_req_prod; */
+ wake_up_interruptible(&blktap_wait);
}
static struct file_operations blktap_fops = {
- owner: THIS_MODULE,
- poll: blktap_poll,
- ioctl: blktap_ioctl,
- open: blktap_open,
- release: blktap_release,
- mmap: blktap_mmap,
+ owner: THIS_MODULE,
+ poll: blktap_poll,
+ ioctl: blktap_ioctl,
+ open: blktap_open,
+ release: blktap_release,
+ mmap: blktap_mmap,
};
@@ -417,44 +409,44 @@
static void fast_flush_area(int idx, int nr_pages)
{
- struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
- unsigned int i, op = 0;
- struct grant_handle_pair *handle;
- unsigned long ptep;
-
- for (i=0; i<nr_pages; i++)
- {
- handle = &pending_handle(idx, i);
- if (!BLKTAP_INVALID_HANDLE(handle))
- {
-
- unmap[op].host_addr = MMAP_VADDR(mmap_vstart, idx, i);
- unmap[op].dev_bus_addr = 0;
- unmap[op].handle = handle->kernel;
- op++;
-
- if (create_lookup_pte_addr(blktap_vma->vm_mm,
- MMAP_VADDR(user_vstart, idx, i),
- &ptep) !=0) {
- DPRINTK("Couldn't get a pte addr!\n");
- return;
- }
- unmap[op].host_addr = ptep;
- unmap[op].dev_bus_addr = 0;
- unmap[op].handle = handle->user;
- op++;
+ struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
+ unsigned int i, op = 0;
+ struct grant_handle_pair *handle;
+ unsigned long ptep;
+
+ for ( i = 0; i < nr_pages; i++)
+ {
+ handle = &pending_handle(idx, i);
+ if (BLKTAP_INVALID_HANDLE(handle))
+ continue;
+
+ unmap[op].host_addr = MMAP_VADDR(mmap_vstart, idx, i);
+ unmap[op].dev_bus_addr = 0;
+ unmap[op].handle = handle->kernel;
+ op++;
+
+ if (create_lookup_pte_addr(
+ blktap_vma->vm_mm,
+ MMAP_VADDR(user_vstart, idx, i),
+ &ptep) !=0) {
+ DPRINTK("Couldn't get a pte addr!\n");
+ return;
+ }
+ unmap[op].host_addr = ptep;
+ unmap[op].dev_bus_addr = 0;
+ unmap[op].handle = handle->user;
+ op++;
- BLKTAP_INVALIDATE_HANDLE(handle);
- }
- }
- if ( unlikely(HYPERVISOR_grant_table_op(
- GNTTABOP_unmap_grant_ref, unmap, op)))
- BUG();
-
- if (blktap_vma != NULL)
- zap_page_range(blktap_vma,
- MMAP_VADDR(user_vstart, idx, 0),
- nr_pages << PAGE_SHIFT, NULL);
+ BLKTAP_INVALIDATE_HANDLE(handle);
+ }
+
+ BUG_ON(HYPERVISOR_grant_table_op(
+ GNTTABOP_unmap_grant_ref, unmap, op));
+
+ if (blktap_vma != NULL)
+ zap_page_range(blktap_vma,
+ MMAP_VADDR(user_vstart, idx, 0),
+ nr_pages << PAGE_SHIFT, NULL);
}
/******************************************************************
@@ -466,34 +458,38 @@
static int __on_blkdev_list(blkif_t *blkif)
{
- return blkif->blkdev_list.next != NULL;
+ return blkif->blkdev_list.next != NULL;
}
static void remove_from_blkdev_list(blkif_t *blkif)
{
- unsigned long flags;
- if ( !__on_blkdev_list(blkif) ) return;
- spin_lock_irqsave(&blkio_schedule_list_lock, flags);
- if ( __on_blkdev_list(blkif) )
- {
- list_del(&blkif->blkdev_list);
- blkif->blkdev_list.next = NULL;
- blkif_put(blkif);
- }
- spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
+ unsigned long flags;
+
+ if (!__on_blkdev_list(blkif))
+ return;
+
+ spin_lock_irqsave(&blkio_schedule_list_lock, flags);
+ if (__on_blkdev_list(blkif)) {
+ list_del(&blkif->blkdev_list);
+ blkif->blkdev_list.next = NULL;
+ blkif_put(blkif);
+ }
+ spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
}
static void add_to_blkdev_list_tail(blkif_t *blkif)
{
- unsigned long flags;
- if ( __on_blkdev_list(blkif) ) return;
- spin_lock_irqsave(&blkio_schedule_list_lock, flags);
- if ( !__on_blkdev_list(blkif) && (blkif->status == CONNECTED) )
- {
- list_add_tail(&blkif->blkdev_list, &blkio_schedule_list);
- blkif_get(blkif);
- }
- spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
+ unsigned long flags;
+
+ if (__on_blkdev_list(blkif))
+ return;
+
+ spin_lock_irqsave(&blkio_schedule_list_lock, flags);
+ if (!__on_blkdev_list(blkif) && (blkif->status == CONNECTED)) {
+ list_add_tail(&blkif->blkdev_list, &blkio_schedule_list);
+ blkif_get(blkif);
+ }
+ spin_unlock_irqrestore(&blkio_schedule_list_lock, flags);
}
@@ -505,51 +501,50 @@
static int blkio_schedule(void *arg)
{
- DECLARE_WAITQUEUE(wq, current);
-
- blkif_t *blkif;
- struct list_head *ent;
-
- daemonize("xenblkd");
-
- for ( ; ; )
- {
- /* Wait for work to do. */
- add_wait_queue(&blkio_schedule_wait, &wq);
- set_current_state(TASK_INTERRUPTIBLE);
- if ( (NR_PENDING_REQS == MAX_PENDING_REQS) ||
- list_empty(&blkio_schedule_list) )
- schedule();
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&blkio_schedule_wait, &wq);
-
- /* Queue up a batch of requests. */
- while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
- !list_empty(&blkio_schedule_list) )
- {
- ent = blkio_schedule_list.next;
- blkif = list_entry(ent, blkif_t, blkdev_list);
- blkif_get(blkif);
- remove_from_blkdev_list(blkif);
- if ( do_block_io_op(blkif, BATCH_PER_DOMAIN) )
- add_to_blkdev_list_tail(blkif);
- blkif_put(blkif);
- }
- }
+ DECLARE_WAITQUEUE(wq, current);
+
+ blkif_t *blkif;
+ struct list_head *ent;
+
+ daemonize("xenblkd");
+
+ for (;;) {
+ /* Wait for work to do. */
+ add_wait_queue(&blkio_schedule_wait, &wq);
+ set_current_state(TASK_INTERRUPTIBLE);
+ if ((NR_PENDING_REQS == MAX_PENDING_REQS) ||
+ list_empty(&blkio_schedule_list))
+ schedule();
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&blkio_schedule_wait, &wq);
+
+ /* Queue up a batch of requests. */
+ while ((NR_PENDING_REQS < MAX_PENDING_REQS) &&
+ !list_empty(&blkio_schedule_list)) {
+ ent = blkio_schedule_list.next;
+ blkif = list_entry(ent, blkif_t, blkdev_list);
+ blkif_get(blkif);
+ remove_from_blkdev_list(blkif);
+ if (do_block_io_op(blkif, BATCH_PER_DOMAIN))
+ add_to_blkdev_list_tail(blkif);
+ blkif_put(blkif);
+ }
+ }
}
static void maybe_trigger_blkio_schedule(void)
{
- /*
- * Needed so that two processes, who together make the following predicate
- * true, don't both read stale values and evaluate the predicate
- * incorrectly. Incredibly unlikely to stall the scheduler on x86, but...
- */
- smp_mb();
-
- if ( (NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
- !list_empty(&blkio_schedule_list) )
- wake_up(&blkio_schedule_wait);
+ /*
+ * Needed so that two processes, who together make the following
+ * predicate true, don't both read stale values and evaluate the
+ * predicate incorrectly. Incredibly unlikely to stall the scheduler
+ * on the x86, but...
+ */
+ smp_mb();
+
+ if ((NR_PENDING_REQS < (MAX_PENDING_REQS/2)) &&
+ !list_empty(&blkio_schedule_list))
+ wake_up(&blkio_schedule_wait);
}
@@ -561,54 +556,53 @@
static int blktap_read_ufe_ring(void)
{
- /* This is called to read responses from the UFE ring. */
-
- RING_IDX i, j, rp;
- blkif_response_t *resp;
- blkif_t *blkif;
- int pending_idx;
- pending_req_t *pending_req;
- unsigned long flags;
-
- /* if we are forwarding from UFERring to FERing */
- if (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) {
-
- /* for each outstanding message on the UFEring */
- rp = blktap_ufe_ring.sring->rsp_prod;
- rmb();
+ /* This is called to read responses from the UFE ring. */
+
+ RING_IDX i, j, rp;
+ blkif_response_t *resp;
+ blkif_t *blkif;
+ int pending_idx;
+ pending_req_t *pending_req;
+ unsigned long flags;
+
+ /* if we are forwarding from UFERring to FERing */
+ if (blktap_mode & BLKTAP_MODE_INTERCEPT_FE) {
+
+ /* for each outstanding message on the UFEring */
+ rp = blktap_ufe_ring.sring->rsp_prod;
+ rmb();
- for ( i = blktap_ufe_ring.rsp_cons; i != rp; i++ )
- {
- resp = RING_GET_RESPONSE(&blktap_ufe_ring, i);
- pending_idx = MASK_PEND_IDX(ID_TO_IDX(resp->id));
- pending_req = &pending_reqs[pending_idx];
+ for (i = blktap_ufe_ring.rsp_cons; i != rp; i++) {
+ resp = RING_GET_RESPONSE(&blktap_ufe_ring, i);
+ pending_idx = MASK_PEND_IDX(ID_TO_IDX(resp->id));
+ pending_req = &pending_reqs[pending_idx];
- blkif = pending_req->blkif;
- for (j = 0; j < pending_req->nr_pages; j++) {
- unsigned long vaddr;
- struct page **map = blktap_vma->vm_private_data;
- int offset;
-
- vaddr = MMAP_VADDR(user_vstart, pending_idx, j);
- offset = (vaddr - blktap_vma->vm_start) >> PAGE_SHIFT;
-
- //ClearPageReserved(virt_to_page(vaddr));
- ClearPageReserved((struct page *)map[offset]);
- map[offset] = NULL;
- }
-
- fast_flush_area(pending_idx, pending_req->nr_pages);
- make_response(blkif, pending_req->id, resp->operation,
- resp->status);
- blkif_put(pending_req->blkif);
- spin_lock_irqsave(&pend_prod_lock, flags);
- pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
- spin_unlock_irqrestore(&pend_prod_lock, flags);
- }
- blktap_ufe_ring.rsp_cons = i;
- maybe_trigger_blkio_schedule();
- }
- return 0;
+ blkif = pending_req->blkif;
+ for (j = 0; j < pending_req->nr_pages; j++) {
+ unsigned long vaddr;
+ struct page **map = blktap_vma->vm_private_data;
+ int offset;
+
+ vaddr = MMAP_VADDR(user_vstart, pending_idx,
j);
+ offset = (vaddr - blktap_vma->vm_start) >>
PAGE_SHIFT;
+
+ //ClearPageReserved(virt_to_page(vaddr));
+ ClearPageReserved((struct page *)map[offset]);
+ map[offset] = NULL;
+ }
+
+ fast_flush_area(pending_idx, pending_req->nr_pages);
+ make_response(blkif, pending_req->id, resp->operation,
+ resp->status);
+ blkif_put(pending_req->blkif);
+ spin_lock_irqsave(&pend_prod_lock, flags);
+ pending_ring[MASK_PEND_IDX(pending_prod++)] =
pending_idx;
+ spin_unlock_irqrestore(&pend_prod_lock, flags);
+ }
+ blktap_ufe_ring.rsp_cons = i;
+ maybe_trigger_blkio_schedule();
+ }
+ return 0;
}
@@ -618,10 +612,10 @@
irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs)
{
- blkif_t *blkif = dev_id;
- add_to_blkdev_list_tail(blkif);
- maybe_trigger_blkio_schedule();
- return IRQ_HANDLED;
+ blkif_t *blkif = dev_id;
+ add_to_blkdev_list_tail(blkif);
+ maybe_trigger_blkio_schedule();
+ return IRQ_HANDLED;
}
@@ -632,199 +626,194 @@
static int do_block_io_op(blkif_t *blkif, int max_to_do)
{
- blkif_back_ring_t *blk_ring = &blkif->blk_ring;
- blkif_request_t *req;
- RING_IDX i, rp;
- int more_to_do = 0;
+ blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+ blkif_request_t *req;
+ RING_IDX i, rp;
+ int more_to_do = 0;
- rp = blk_ring->sring->req_prod;
- rmb(); /* Ensure we see queued requests up to 'rp'. */
-
- for ( i = blk_ring->req_cons;
- (i != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, i);
- i++ )
- {
- if ( (max_to_do-- == 0) || (NR_PENDING_REQS == MAX_PENDING_REQS) )
- {
- more_to_do = 1;
- break;
- }
+ rp = blk_ring->sring->req_prod;
+ rmb(); /* Ensure we see queued requests up to 'rp'. */
+
+ for (i = blk_ring->req_cons;
+ (i != rp) && !RING_REQUEST_CONS_OVERFLOW(blk_ring, i);
+ i++ ) {
+ if ((max_to_do-- == 0) ||
+ (NR_PENDING_REQS == MAX_PENDING_REQS)) {
+ more_to_do = 1;
+ break;
+ }
- req = RING_GET_REQUEST(blk_ring, i);
- switch ( req->operation )
- {
- case BLKIF_OP_READ:
- case BLKIF_OP_WRITE:
- dispatch_rw_block_io(blkif, req);
- break;
-
- default:
- DPRINTK("error: unknown block io operation [%d]\n",
- req->operation);
- make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
- break;
- }
- }
-
- blk_ring->req_cons = i;
- blktap_kick_user();
-
- return more_to_do;
+ req = RING_GET_REQUEST(blk_ring, i);
+ switch (req->operation) {
+ case BLKIF_OP_READ:
+ case BLKIF_OP_WRITE:
+ dispatch_rw_block_io(blkif, req);
+ break;
+
+ default:
+ DPRINTK("error: unknown block io operation [%d]\n",
+ req->operation);
+ make_response(blkif, req->id, req->operation,
+ BLKIF_RSP_ERROR);
+ break;
+ }
+ }
+
+ blk_ring->req_cons = i;
+ blktap_kick_user();
+
+ return more_to_do;
}
static void dispatch_rw_block_io(blkif_t *blkif, blkif_request_t *req)
{
- blkif_request_t *target;
- int i, pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
- pending_req_t *pending_req;
- struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
- int op, ret;
- unsigned int nseg;
-
- /* Check that number of segments is sane. */
- nseg = req->nr_segments;
- if ( unlikely(nseg == 0) ||
- unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST) )
- {
- DPRINTK("Bad number of segments in request (%d)\n", nseg);
- goto bad_descriptor;
- }
-
- /* Make sure userspace is ready. */
- if (!blktap_ring_ok) {
- DPRINTK("blktap: ring not ready for requests!\n");
- goto bad_descriptor;
- }
+ blkif_request_t *target;
+ int i, pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
+ pending_req_t *pending_req;
+ struct gnttab_map_grant_ref map[BLKIF_MAX_SEGMENTS_PER_REQUEST*2];
+ int op, ret;
+ unsigned int nseg;
+
+ /* Check that number of segments is sane. */
+ nseg = req->nr_segments;
+ if (unlikely(nseg == 0) ||
+ unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
+ DPRINTK("Bad number of segments in request (%d)\n", nseg);
+ goto bad_descriptor;
+ }
+
+ /* Make sure userspace is ready. */
+ if (!blktap_ring_ok) {
+ DPRINTK("blktap: ring not ready for requests!\n");
+ goto bad_descriptor;
+ }
- if ( RING_FULL(&blktap_ufe_ring) ) {
- WPRINTK("blktap: fe_ring is full, can't add (very broken!).\n");
- goto bad_descriptor;
- }
-
- flush_cache_all(); /* a noop on intel... */
-
- /* Map the foreign pages directly in to the application */
- op = 0;
- for (i=0; i<req->nr_segments; i++) {
-
- unsigned long uvaddr;
- unsigned long kvaddr;
- unsigned long ptep;
-
- uvaddr = MMAP_VADDR(user_vstart, pending_idx, i);
- kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i);
-
- /* Map the remote page to kernel. */
- map[op].host_addr = kvaddr;
- map[op].dom = blkif->domid;
- map[op].ref = blkif_gref_from_fas(req->frame_and_sects[i]);
- map[op].flags = GNTMAP_host_map;
- /* This needs a bit more thought in terms of interposition:
- * If we want to be able to modify pages during write using
- * grant table mappings, the guest will either need to allow
- * it, or we'll need to incur a copy. Bit of an fbufs moment. ;) */
- if (req->operation == BLKIF_OP_WRITE)
- map[op].flags |= GNTMAP_readonly;
- op++;
-
- /* Now map it to user. */
- ret = create_lookup_pte_addr(blktap_vma->vm_mm, uvaddr, &ptep);
- if (ret)
- {
- DPRINTK("Couldn't get a pte addr!\n");
- fast_flush_area(pending_idx, req->nr_segments);
- goto bad_descriptor;
- }
-
- map[op].host_addr = ptep;
- map[op].dom = blkif->domid;
- map[op].ref = blkif_gref_from_fas(req->frame_and_sects[i]);
- map[op].flags = GNTMAP_host_map | GNTMAP_application_map
- | GNTMAP_contains_pte;
- /* Above interposition comment applies here as well. */
- if (req->operation == BLKIF_OP_WRITE)
- map[op].flags |= GNTMAP_readonly;
- op++;
- }
-
- if ( unlikely(HYPERVISOR_grant_table_op(
- GNTTABOP_map_grant_ref, map, op)))
- BUG();
-
- op = 0;
- for (i=0; i<(req->nr_segments*2); i+=2) {
- unsigned long uvaddr;
- unsigned long kvaddr;
- unsigned long offset;
- int cancel = 0;
-
- uvaddr = MMAP_VADDR(user_vstart, pending_idx, i/2);
- kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i/2);
-
- if ( unlikely(map[i].handle < 0) )
- {
- DPRINTK("Error on kernel grant mapping (%d)\n", map[i].handle);
- ret = map[i].handle;
- cancel = 1;
- }
-
- if ( unlikely(map[i+1].handle < 0) )
- {
- DPRINTK("Error on user grant mapping (%d)\n", map[i+1].handle);
- ret = map[i+1].handle;
- cancel = 1;
- }
-
- if (cancel)
- {
- fast_flush_area(pending_idx, req->nr_segments);
- goto bad_descriptor;
- }
-
- /* Set the necessary mappings in p2m and in the VM_FOREIGN
- * vm_area_struct to allow user vaddr -> struct page lookups
- * to work. This is needed for direct IO to foreign pages. */
- phys_to_machine_mapping[__pa(kvaddr) >> PAGE_SHIFT] =
- FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT);
-
- offset = (uvaddr - blktap_vma->vm_start) >> PAGE_SHIFT;
- ((struct page **)blktap_vma->vm_private_data)[offset] =
- pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
-
- /* Save handles for unmapping later. */
- pending_handle(pending_idx, i/2).kernel = map[i].handle;
- pending_handle(pending_idx, i/2).user = map[i+1].handle;
- }
-
- /* Mark mapped pages as reserved: */
- for ( i = 0; i < req->nr_segments; i++ )
- {
- unsigned long kvaddr;
-
- kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i);
- SetPageReserved(pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT));
- }
-
- pending_req = &pending_reqs[pending_idx];
- pending_req->blkif = blkif;
- pending_req->id = req->id;
- pending_req->operation = req->operation;
- pending_req->status = BLKIF_RSP_OKAY;
- pending_req->nr_pages = nseg;
- req->id = MAKE_ID(blkif->domid, pending_idx);
- //atomic_set(&pending_req->pendcnt, nbio);
- pending_cons++;
- blkif_get(blkif);
-
- /* Finally, write the request message to the user ring. */
- target = RING_GET_REQUEST(&blktap_ufe_ring, blktap_ufe_ring.req_prod_pvt);
- memcpy(target, req, sizeof(*req));
- blktap_ufe_ring.req_prod_pvt++;
- return;
+ if (RING_FULL(&blktap_ufe_ring)) {
+ WPRINTK("blktap: fe_ring is full, can't add "
+ "(very broken!).\n");
+ goto bad_descriptor;
+ }
+
+ flush_cache_all(); /* a noop on intel... */
+
+ /* Map the foreign pages directly in to the application */
+ op = 0;
+ for (i = 0; i < req->nr_segments; i++) {
+
+ unsigned long uvaddr;
+ unsigned long kvaddr;
+ unsigned long ptep;
+
+ uvaddr = MMAP_VADDR(user_vstart, pending_idx, i);
+ kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i);
+
+ /* Map the remote page to kernel. */
+ map[op].host_addr = kvaddr;
+ map[op].dom = blkif->domid;
+ map[op].ref = blkif_gref_from_fas(req->frame_and_sects[i]);
+ map[op].flags = GNTMAP_host_map;
+ /* This needs a bit more thought in terms of interposition:
+ * If we want to be able to modify pages during write using
+ * grant table mappings, the guest will either need to allow
+ * it, or we'll need to incur a copy. Bit of an fbufs moment.
;) */
+ if (req->operation == BLKIF_OP_WRITE)
+ map[op].flags |= GNTMAP_readonly;
+ op++;
+
+ /* Now map it to user. */
+ ret = create_lookup_pte_addr(blktap_vma->vm_mm, uvaddr, &ptep);
+ if (ret) {
+ DPRINTK("Couldn't get a pte addr!\n");
+ fast_flush_area(pending_idx, req->nr_segments);
+ goto bad_descriptor;
+ }
+
+ map[op].host_addr = ptep;
+ map[op].dom = blkif->domid;
+ map[op].ref =
blkif_gref_from_fas(req->frame_and_sects[i]);
+ map[op].flags = GNTMAP_host_map | GNTMAP_application_map
+ | GNTMAP_contains_pte;
+ /* Above interposition comment applies here as well. */
+ if (req->operation == BLKIF_OP_WRITE)
+ map[op].flags |= GNTMAP_readonly;
+ op++;
+ }
+
+ BUG_ON(HYPERVISOR_grant_table_op(
+ GNTTABOP_map_grant_ref, map, op));
+
+ op = 0;
+ for (i = 0; i < (req->nr_segments*2); i += 2) {
+ unsigned long uvaddr;
+ unsigned long kvaddr;
+ unsigned long offset;
+ int cancel = 0;
+
+ uvaddr = MMAP_VADDR(user_vstart, pending_idx, i/2);
+ kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i/2);
+
+ if (unlikely(map[i].handle < 0)) {
+ DPRINTK("Error on kernel grant mapping (%d)\n",
+ map[i].handle);
+ ret = map[i].handle;
+ cancel = 1;
+ }
+
+ if (unlikely(map[i+1].handle < 0)) {
+ DPRINTK("Error on user grant mapping (%d)\n",
+ map[i+1].handle);
+ ret = map[i+1].handle;
+ cancel = 1;
+ }
+
+ if (cancel) {
+ fast_flush_area(pending_idx, req->nr_segments);
+ goto bad_descriptor;
+ }
+
+ /* Set the necessary mappings in p2m and in the VM_FOREIGN
+ * vm_area_struct to allow user vaddr -> struct page lookups
+ * to work. This is needed for direct IO to foreign pages. */
+ phys_to_machine_mapping[__pa(kvaddr) >> PAGE_SHIFT] =
+ FOREIGN_FRAME(map[i].dev_bus_addr >> PAGE_SHIFT);
+
+ offset = (uvaddr - blktap_vma->vm_start) >> PAGE_SHIFT;
+ ((struct page **)blktap_vma->vm_private_data)[offset] =
+ pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
+
+ /* Save handles for unmapping later. */
+ pending_handle(pending_idx, i/2).kernel = map[i].handle;
+ pending_handle(pending_idx, i/2).user = map[i+1].handle;
+ }
+
+ /* Mark mapped pages as reserved: */
+ for (i = 0; i < req->nr_segments; i++) {
+ unsigned long kvaddr;
+ kvaddr = MMAP_VADDR(mmap_vstart, pending_idx, i);
+ SetPageReserved(pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT));
+ }
+
+ pending_req = &pending_reqs[pending_idx];
+ pending_req->blkif = blkif;
+ pending_req->id = req->id;
+ pending_req->operation = req->operation;
+ pending_req->status = BLKIF_RSP_OKAY;
+ pending_req->nr_pages = nseg;
+ req->id = MAKE_ID(blkif->domid, pending_idx);
+ //atomic_set(&pending_req->pendcnt, nbio);
+ pending_cons++;
+ blkif_get(blkif);
+
+ /* Finally, write the request message to the user ring. */
+ target = RING_GET_REQUEST(&blktap_ufe_ring,
+ blktap_ufe_ring.req_prod_pvt);
+ memcpy(target, req, sizeof(*req));
+ blktap_ufe_ring.req_prod_pvt++;
+ return;
bad_descriptor:
- make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
+ make_response(blkif, req->id, req->operation, BLKIF_RSP_ERROR);
}
@@ -837,80 +826,89 @@
static void make_response(blkif_t *blkif, unsigned long id,
unsigned short op, int st)
{
- blkif_response_t *resp;
- unsigned long flags;
- blkif_back_ring_t *blk_ring = &blkif->blk_ring;
-
- /* Place on the response ring for the relevant domain. */
- spin_lock_irqsave(&blkif->blk_ring_lock, flags);
- resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt);
- resp->id = id;
- resp->operation = op;
- resp->status = st;
- wmb(); /* Ensure other side can see the response fields. */
- blk_ring->rsp_prod_pvt++;
- RING_PUSH_RESPONSES(blk_ring);
- spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
-
- /* Kick the relevant domain. */
- notify_via_evtchn(blkif->evtchn);
+ blkif_response_t *resp;
+ unsigned long flags;
+ blkif_back_ring_t *blk_ring = &blkif->blk_ring;
+
+ /* Place on the response ring for the relevant domain. */
+ spin_lock_irqsave(&blkif->blk_ring_lock, flags);
+ resp = RING_GET_RESPONSE(blk_ring, blk_ring->rsp_prod_pvt);
+ resp->id = id;
+ resp->operation = op;
+ resp->status = st;
+ wmb(); /* Ensure other side can see the response fields. */
+ blk_ring->rsp_prod_pvt++;
+ RING_PUSH_RESPONSES(blk_ring);
+ spin_unlock_irqrestore(&blkif->blk_ring_lock, flags);
+
+ /* Kick the relevant domain. */
+ notify_via_evtchn(blkif->evtchn);
}
static struct miscdevice blktap_miscdev = {
- .minor = BLKTAP_MINOR,
- .name = "blktap",
- .fops = &blktap_fops,
- .devfs_name = "misc/blktap",
+ .minor = BLKTAP_MINOR,
+ .name = "blktap",
+ .fops = &blktap_fops,
+ .devfs_name = "misc/blktap",
};
void blkif_deschedule(blkif_t *blkif)
{
- remove_from_blkdev_list(blkif);
+ remove_from_blkdev_list(blkif);
}
static int __init blkif_init(void)
{
- int i, j, err;
- struct page *page;
+ int i, j, err;
+ struct page *page;
/*
- if ( !(xen_start_info->flags & SIF_INITDOMAIN) &&
- !(xen_start_info->flags & SIF_BLK_BE_DOMAIN) )
- return 0;
+ if ( !(xen_start_info->flags & SIF_INITDOMAIN) &&
+ !(xen_start_info->flags & SIF_BLK_BE_DOMAIN) )
+ return 0;
*/
- blkif_interface_init();
-
- page = balloon_alloc_empty_page_range(MMAP_PAGES);
- BUG_ON(page == NULL);
- mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
-
- pending_cons = 0;
- pending_prod = MAX_PENDING_REQS;
- memset(pending_reqs, 0, sizeof(pending_reqs));
- for ( i = 0; i < MAX_PENDING_REQS; i++ )
- pending_ring[i] = i;
+ blkif_interface_init();
+
+ page = balloon_alloc_empty_page_range(MMAP_PAGES);
+ BUG_ON(page == NULL);
+ mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
+
+ pending_cons = 0;
+ pending_prod = MAX_PENDING_REQS;
+ memset(pending_reqs, 0, sizeof(pending_reqs));
+ for ( i = 0; i < MAX_PENDING_REQS; i++ )
+ pending_ring[i] = i;
- spin_lock_init(&blkio_schedule_list_lock);
- INIT_LIST_HEAD(&blkio_schedule_list);
-
- if ( kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0 )
- BUG();
-
- blkif_xenbus_init();
-
- for (i=0; i<MAX_PENDING_REQS ; i++)
- for (j=0; j<BLKIF_MAX_SEGMENTS_PER_REQUEST; j++)
- BLKTAP_INVALIDATE_HANDLE(&pending_handle(i, j));
-
- err = misc_register(&blktap_miscdev);
- if ( err != 0 )
- {
- printk(KERN_ALERT "Couldn't register /dev/misc/blktap (%d)\n", err);
- return err;
- }
-
- init_waitqueue_head(&blktap_wait);
-
- return 0;
+ spin_lock_init(&blkio_schedule_list_lock);
+ INIT_LIST_HEAD(&blkio_schedule_list);
+
+ BUG_ON(kernel_thread(blkio_schedule, 0, CLONE_FS | CLONE_FILES) < 0);
+
+ blkif_xenbus_init();
+
+ for (i = 0; i < MAX_PENDING_REQS ; i++)
+ for (j = 0; j < BLKIF_MAX_SEGMENTS_PER_REQUEST; j++)
+ BLKTAP_INVALIDATE_HANDLE(&pending_handle(i, j));
+
+ err = misc_register(&blktap_miscdev);
+ if (err != 0) {
+ printk(KERN_ALERT "Couldn't register /dev/misc/blktap (%d)\n",
+ err);
+ return err;
+ }
+
+ init_waitqueue_head(&blktap_wait);
+
+ return 0;
}
__initcall(blkif_init);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/blktap/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/common.h Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/common.h Thu Sep 22 15:12:14 2005
@@ -33,39 +33,39 @@
#define WPRINTK(fmt, args...) printk(KERN_WARNING "blk_tap: " fmt, ##args)
struct vbd {
- blkif_vdev_t handle; /* what the domain refers to this vbd as */
- unsigned char readonly; /* Non-zero -> read-only */
- unsigned char type; /* VDISK_xxx */
- u32 pdevice; /* phys device that this vbd maps to */
- struct block_device *bdev;
+ blkif_vdev_t handle; /* what the domain refers to this vbd as */
+ unsigned char readonly; /* Non-zero -> read-only */
+ unsigned char type; /* VDISK_xxx */
+ u32 pdevice; /* phys device that this vbd maps to */
+ struct block_device *bdev;
};
typedef struct blkif_st {
- /* Unique identifier for this interface. */
- domid_t domid;
- unsigned int handle;
- /* Physical parameters of the comms window. */
- unsigned int evtchn;
- unsigned int remote_evtchn;
- /* Comms information. */
- blkif_back_ring_t blk_ring;
- struct vm_struct *blk_ring_area;
- /* VBDs attached to this interface. */
- struct vbd vbd;
- /* Private fields. */
- enum { DISCONNECTED, CONNECTED } status;
+ /* Unique identifier for this interface. */
+ domid_t domid;
+ unsigned int handle;
+ /* Physical parameters of the comms window. */
+ unsigned int evtchn;
+ unsigned int remote_evtchn;
+ /* Comms information. */
+ blkif_back_ring_t blk_ring;
+ struct vm_struct *blk_ring_area;
+ /* VBDs attached to this interface. */
+ struct vbd vbd;
+ /* Private fields. */
+ enum { DISCONNECTED, CONNECTED } status;
#ifdef CONFIG_XEN_BLKDEV_TAP_BE
- /* Is this a blktap frontend */
- unsigned int is_blktap;
+ /* Is this a blktap frontend */
+ unsigned int is_blktap;
#endif
- struct list_head blkdev_list;
- spinlock_t blk_ring_lock;
- atomic_t refcnt;
+ struct list_head blkdev_list;
+ spinlock_t blk_ring_lock;
+ atomic_t refcnt;
- struct work_struct free_work;
+ struct work_struct free_work;
- u16 shmem_handle;
- grant_ref_t shmem_ref;
+ u16 shmem_handle;
+ grant_ref_t shmem_ref;
} blkif_t;
blkif_t *alloc_blkif(domid_t domid);
@@ -89,10 +89,10 @@
unsigned long vbd_secsize(struct vbd *vbd);
struct phys_req {
- unsigned short dev;
- unsigned short nr_sects;
- struct block_device *bdev;
- blkif_sector_t sector_number;
+ unsigned short dev;
+ unsigned short nr_sects;
+ struct block_device *bdev;
+ blkif_sector_t sector_number;
};
int vbd_translate(struct phys_req *req, blkif_t *blkif, int operation);
@@ -106,3 +106,13 @@
irqreturn_t blkif_be_int(int irq, void *dev_id, struct pt_regs *regs);
#endif /* __BLKIF__BACKEND__COMMON_H__ */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c Thu Sep 22 15:12:14 2005
@@ -222,3 +222,13 @@
{
xenbus_register_backend(&blkback);
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/console/console.c
--- a/linux-2.6-xen-sparse/drivers/xen/console/console.c Thu Sep 22
15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/console.c Thu Sep 22
15:12:14 2005
@@ -75,31 +75,33 @@
static int __init xencons_setup(char *str)
{
- char *q;
- int n;
-
- if ( !strncmp(str, "ttyS", 4) )
- xc_mode = XC_SERIAL;
- else if ( !strncmp(str, "tty", 3) )
- xc_mode = XC_TTY;
- else if ( !strncmp(str, "off", 3) )
- xc_mode = XC_OFF;
-
- switch ( xc_mode )
- {
- case XC_SERIAL:
- n = simple_strtol( str+4, &q, 10 );
- if ( q > (str + 4) ) xc_num = n;
- break;
- case XC_TTY:
- n = simple_strtol( str+3, &q, 10 );
- if ( q > (str + 3) ) xc_num = n;
- break;
- default:
- break;
- }
-
- return 1;
+ char *q;
+ int n;
+
+ if (!strncmp(str, "ttyS", 4))
+ xc_mode = XC_SERIAL;
+ else if (!strncmp(str, "tty", 3))
+ xc_mode = XC_TTY;
+ else if (!strncmp(str, "off", 3))
+ xc_mode = XC_OFF;
+
+ switch ( xc_mode )
+ {
+ case XC_SERIAL:
+ n = simple_strtol(str+4, &q, 10);
+ if (q > (str + 4))
+ xc_num = n;
+ break;
+ case XC_TTY:
+ n = simple_strtol(str+3, &q, 10);
+ if (q > (str + 3))
+ xc_num = n;
+ break;
+ default:
+ break;
+ }
+
+ return 1;
}
__setup("xencons=", xencons_setup);
@@ -111,11 +113,11 @@
static int __init xencons_bufsz_setup(char *str)
{
- unsigned int goal;
- goal = simple_strtoul(str, NULL, 0);
- while ( wbuf_size < goal )
- wbuf_size <<= 1;
- return 1;
+ unsigned int goal;
+ goal = simple_strtoul(str, NULL, 0);
+ while (wbuf_size < goal)
+ wbuf_size <<= 1;
+ return 1;
}
__setup("xencons_bufsz=", xencons_bufsz_setup);
@@ -135,57 +137,55 @@
/******************** Kernel console driver ********************************/
static void kcons_write(
- struct console *c, const char *s, unsigned int count)
-{
- int i;
- unsigned long flags;
-
- spin_lock_irqsave(&xencons_lock, flags);
+ struct console *c, const char *s, unsigned int count)
+{
+ int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&xencons_lock, flags);
- for ( i = 0; i < count; i++ )
- {
- if ( (wp - wc) >= (wbuf_size - 1) )
- break;
- if ( (wbuf[WBUF_MASK(wp++)] = s[i]) == '\n' )
- wbuf[WBUF_MASK(wp++)] = '\r';
- }
-
- __xencons_tx_flush();
-
- spin_unlock_irqrestore(&xencons_lock, flags);
+ for (i = 0; i < count; i++) {
+ if ((wp - wc) >= (wbuf_size - 1))
+ break;
+ if ((wbuf[WBUF_MASK(wp++)] = s[i]) == '\n')
+ wbuf[WBUF_MASK(wp++)] = '\r';
+ }
+
+ __xencons_tx_flush();
+
+ spin_unlock_irqrestore(&xencons_lock, flags);
}
static void kcons_write_dom0(
- struct console *c, const char *s, unsigned int count)
-{
- int rc;
-
- while ( (count > 0) &&
- ((rc = HYPERVISOR_console_io(
- CONSOLEIO_write, count, (char *)s)) > 0) )
- {
- count -= rc;
- s += rc;
- }
+ struct console *c, const char *s, unsigned int count)
+{
+ int rc;
+
+ while ((count > 0) &&
+ ((rc = HYPERVISOR_console_io(
+ CONSOLEIO_write, count, (char *)s)) > 0)) {
+ count -= rc;
+ s += rc;
+ }
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
static struct tty_driver *kcons_device(struct console *c, int *index)
{
- *index = c->index;
- return xencons_driver;
+ *index = c->index;
+ return xencons_driver;
}
#else
static kdev_t kcons_device(struct console *c)
{
- return MKDEV(TTY_MAJOR, (xc_mode == XC_SERIAL) ? 64 : 1);
+ return MKDEV(TTY_MAJOR, (xc_mode == XC_SERIAL) ? 64 : 1);
}
#endif
static struct console kcons_info = {
- .device = kcons_device,
- .flags = CON_PRINTBUFFER,
- .index = -1,
+ .device = kcons_device,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
};
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
@@ -196,44 +196,42 @@
void xen_console_init(void)
#endif
{
- if ( xen_start_info->flags & SIF_INITDOMAIN )
- {
- if ( xc_mode == XC_DEFAULT )
- xc_mode = XC_SERIAL;
- kcons_info.write = kcons_write_dom0;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- if ( xc_mode == XC_SERIAL )
- kcons_info.flags |= CON_ENABLED;
-#endif
- }
- else
- {
- if ( xc_mode == XC_DEFAULT )
- xc_mode = XC_TTY;
- kcons_info.write = kcons_write;
- }
-
- switch ( xc_mode )
- {
- case XC_SERIAL:
- strcpy(kcons_info.name, "ttyS");
- if ( xc_num == -1 ) xc_num = 0;
- break;
-
- case XC_TTY:
- strcpy(kcons_info.name, "tty");
- if ( xc_num == -1 ) xc_num = 1;
- break;
-
- default:
- return __RETCODE;
- }
-
- wbuf = alloc_bootmem(wbuf_size);
-
- register_console(&kcons_info);
-
- return __RETCODE;
+ if (xen_start_info->flags & SIF_INITDOMAIN) {
+ if (xc_mode == XC_DEFAULT)
+ xc_mode = XC_SERIAL;
+ kcons_info.write = kcons_write_dom0;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ if (xc_mode == XC_SERIAL)
+ kcons_info.flags |= CON_ENABLED;
+#endif
+ } else {
+ if (xc_mode == XC_DEFAULT)
+ xc_mode = XC_TTY;
+ kcons_info.write = kcons_write;
+ }
+
+ switch (xc_mode) {
+ case XC_SERIAL:
+ strcpy(kcons_info.name, "ttyS");
+ if (xc_num == -1)
+ xc_num = 0;
+ break;
+
+ case XC_TTY:
+ strcpy(kcons_info.name, "tty");
+ if (xc_num == -1)
+ xc_num = 1;
+ break;
+
+ default:
+ return __RETCODE;
+ }
+
+ wbuf = alloc_bootmem(wbuf_size);
+
+ register_console(&kcons_info);
+
+ return __RETCODE;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
console_initcall(xen_console_init);
@@ -246,41 +244,40 @@
asmlinkage int xprintk(const char *fmt, ...)
#endif
{
- va_list args;
- int printk_len;
- static char printk_buf[1024];
+ va_list args;
+ int printk_len;
+ static char printk_buf[1024];
- /* Emit the output into the temporary buffer */
- va_start(args, fmt);
- printk_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
- va_end(args);
-
- /* Send the processed output directly to Xen. */
- kcons_write_dom0(NULL, printk_buf, printk_len);
-
- return 0;
+ /* Emit the output into the temporary buffer */
+ va_start(args, fmt);
+ printk_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
+ va_end(args);
+
+ /* Send the processed output directly to Xen. */
+ kcons_write_dom0(NULL, printk_buf, printk_len);
+
+ return 0;
}
/*** Forcibly flush console data before dying. ***/
void xencons_force_flush(void)
{
- int sz;
-
- /* Emergency console is synchronous, so there's nothing to flush. */
- if ( xen_start_info->flags & SIF_INITDOMAIN )
- return;
-
-
- /* Spin until console data is flushed through to the domain controller. */
- while ( (wc != wp) )
- {
- int sent = 0;
- if ( (sz = wp - wc) == 0 )
- continue;
- sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
- if (sent > 0)
- wc += sent;
- }
+ int sz;
+
+ /* Emergency console is synchronous, so there's nothing to flush. */
+ if (xen_start_info->flags & SIF_INITDOMAIN)
+ return;
+
+
+ /* Spin until console data is flushed through to the daemon. */
+ while (wc != wp) {
+ int sent = 0;
+ if ((sz = wp - wc) == 0)
+ continue;
+ sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
+ if (sent > 0)
+ wc += sent;
+ }
}
@@ -305,362 +302,358 @@
/* Non-privileged receive callback. */
static void xencons_rx(char *buf, unsigned len, struct pt_regs *regs)
{
- int i;
- unsigned long flags;
-
- spin_lock_irqsave(&xencons_lock, flags);
- if ( xencons_tty != NULL )
- {
- for ( i = 0; i < len; i++ ) {
+ int i;
+ unsigned long flags;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ if (xencons_tty == NULL)
+ goto out;
+
+ for (i = 0; i < len; i++) {
#ifdef CONFIG_MAGIC_SYSRQ
- if (sysrq_enabled) {
- if (buf[i] == '\x0f') { /* ^O */
- sysrq_requested = jiffies;
- continue; /* don't print the sysrq key */
- } else if (sysrq_requested) {
- unsigned long sysrq_timeout = sysrq_requested + HZ*2;
- sysrq_requested = 0;
- /* if it's been less than a timeout, do the sysrq */
- if (time_before(jiffies, sysrq_timeout)) {
- spin_unlock_irqrestore(&xencons_lock, flags);
- handle_sysrq(buf[i], regs, xencons_tty);
- spin_lock_irqsave(&xencons_lock, flags);
- continue;
- }
- }
- }
-#endif
- tty_insert_flip_char(xencons_tty, buf[i], 0);
- }
- tty_flip_buffer_push(xencons_tty);
- }
- spin_unlock_irqrestore(&xencons_lock, flags);
-
+ if (sysrq_enabled) {
+ if (buf[i] == '\x0f') { /* ^O */
+ sysrq_requested = jiffies;
+ continue; /* don't print the sysrq key */
+ } else if (sysrq_requested) {
+ unsigned long sysrq_timeout =
+ sysrq_requested + HZ*2;
+ sysrq_requested = 0;
+ if (time_before(jiffies, sysrq_timeout)) {
+ spin_unlock_irqrestore(
+ &xencons_lock, flags);
+ handle_sysrq(
+ buf[i], regs, xencons_tty);
+ spin_lock_irqsave(
+ &xencons_lock, flags);
+ continue;
+ }
+ }
+ }
+#endif
+ tty_insert_flip_char(xencons_tty, buf[i], 0);
+ }
+ tty_flip_buffer_push(xencons_tty);
+
+ out:
+ spin_unlock_irqrestore(&xencons_lock, flags);
}
/* Privileged and non-privileged transmit worker. */
static void __xencons_tx_flush(void)
{
- int sz, work_done = 0;
-
- if ( xen_start_info->flags & SIF_INITDOMAIN )
- {
- if ( x_char )
- {
- kcons_write_dom0(NULL, &x_char, 1);
- x_char = 0;
- work_done = 1;
- }
-
- while ( wc != wp )
- {
- sz = wp - wc;
- if ( sz > (wbuf_size - WBUF_MASK(wc)) )
- sz = wbuf_size - WBUF_MASK(wc);
- kcons_write_dom0(NULL, &wbuf[WBUF_MASK(wc)], sz);
- wc += sz;
- work_done = 1;
- }
- }
- else
- {
- while ( x_char )
- {
- if (xencons_ring_send(&x_char, 1) == 1) {
- x_char = 0;
- work_done = 1;
- }
- }
-
- while ( wc != wp )
- {
- int sent;
- sz = wp - wc;
- if ( sz > (wbuf_size - WBUF_MASK(wc)) )
- sz = wbuf_size - WBUF_MASK(wc);
- sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
- if ( sent > 0 ) {
- wc += sent;
- work_done = 1;
- }
- }
- }
-
- if ( work_done && (xencons_tty != NULL) )
- {
- wake_up_interruptible(&xencons_tty->write_wait);
- if ( (xencons_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- (xencons_tty->ldisc.write_wakeup != NULL) )
- (xencons_tty->ldisc.write_wakeup)(xencons_tty);
- }
+ int sz, work_done = 0;
+
+ if (xen_start_info->flags & SIF_INITDOMAIN) {
+ if (x_char) {
+ kcons_write_dom0(NULL, &x_char, 1);
+ x_char = 0;
+ work_done = 1;
+ }
+
+ while (wc != wp) {
+ sz = wp - wc;
+ if (sz > (wbuf_size - WBUF_MASK(wc)))
+ sz = wbuf_size - WBUF_MASK(wc);
+ kcons_write_dom0(NULL, &wbuf[WBUF_MASK(wc)], sz);
+ wc += sz;
+ work_done = 1;
+ }
+ } else {
+ while (x_char) {
+ if (xencons_ring_send(&x_char, 1) == 1) {
+ x_char = 0;
+ work_done = 1;
+ }
+ }
+
+ while (wc != wp) {
+ int sent;
+ sz = wp - wc;
+ if (sz > (wbuf_size - WBUF_MASK(wc)))
+ sz = wbuf_size - WBUF_MASK(wc);
+ sent = xencons_ring_send(&wbuf[WBUF_MASK(wc)], sz);
+ if (sent > 0) {
+ wc += sent;
+ work_done = 1;
+ }
+ }
+ }
+
+ if (work_done && (xencons_tty != NULL))
+ {
+ wake_up_interruptible(&xencons_tty->write_wait);
+ if ((xencons_tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ (xencons_tty->ldisc.write_wakeup != NULL))
+ (xencons_tty->ldisc.write_wakeup)(xencons_tty);
+ }
}
/* Privileged receive callback and transmit kicker. */
static irqreturn_t xencons_priv_interrupt(int irq, void *dev_id,
struct pt_regs *regs)
{
- static char rbuf[16];
- int i, l;
- unsigned long flags;
-
- spin_lock_irqsave(&xencons_lock, flags);
-
- if ( xencons_tty != NULL )
- {
- /* Receive work. */
- while ( (l = HYPERVISOR_console_io(CONSOLEIO_read, 16, rbuf)) > 0 )
- for ( i = 0; i < l; i++ )
- tty_insert_flip_char(xencons_tty, rbuf[i], 0);
- if ( xencons_tty->flip.count != 0 )
- tty_flip_buffer_push(xencons_tty);
- }
-
- /* Transmit work. */
- __xencons_tx_flush();
-
- spin_unlock_irqrestore(&xencons_lock, flags);
-
- return IRQ_HANDLED;
+ static char rbuf[16];
+ int i, l;
+ unsigned long flags;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+
+ if (xencons_tty != NULL)
+ {
+ /* Receive work. */
+ while ((l = HYPERVISOR_console_io(
+ CONSOLEIO_read, 16, rbuf)) > 0)
+ for (i = 0; i < l; i++)
+ tty_insert_flip_char(xencons_tty, rbuf[i], 0);
+ if (xencons_tty->flip.count != 0)
+ tty_flip_buffer_push(xencons_tty);
+ }
+
+ /* Transmit work. */
+ __xencons_tx_flush();
+
+ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ return IRQ_HANDLED;
}
static int xencons_write_room(struct tty_struct *tty)
{
- return wbuf_size - (wp - wc);
+ return wbuf_size - (wp - wc);
}
static int xencons_chars_in_buffer(struct tty_struct *tty)
{
- return wp - wc;
+ return wp - wc;
}
static void xencons_send_xchar(struct tty_struct *tty, char ch)
{
- unsigned long flags;
-
- if ( TTY_INDEX(tty) != 0 )
- return;
-
- spin_lock_irqsave(&xencons_lock, flags);
- x_char = ch;
- __xencons_tx_flush();
- spin_unlock_irqrestore(&xencons_lock, flags);
+ unsigned long flags;
+
+ if (TTY_INDEX(tty) != 0)
+ return;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ x_char = ch;
+ __xencons_tx_flush();
+ spin_unlock_irqrestore(&xencons_lock, flags);
}
static void xencons_throttle(struct tty_struct *tty)
{
- if ( TTY_INDEX(tty) != 0 )
- return;
-
- if ( I_IXOFF(tty) )
- xencons_send_xchar(tty, STOP_CHAR(tty));
+ if (TTY_INDEX(tty) != 0)
+ return;
+
+ if (I_IXOFF(tty))
+ xencons_send_xchar(tty, STOP_CHAR(tty));
}
static void xencons_unthrottle(struct tty_struct *tty)
{
- if ( TTY_INDEX(tty) != 0 )
- return;
-
- if ( I_IXOFF(tty) )
- {
- if ( x_char != 0 )
- x_char = 0;
- else
- xencons_send_xchar(tty, START_CHAR(tty));
- }
+ if (TTY_INDEX(tty) != 0)
+ return;
+
+ if (I_IXOFF(tty)) {
+ if (x_char != 0)
+ x_char = 0;
+ else
+ xencons_send_xchar(tty, START_CHAR(tty));
+ }
}
static void xencons_flush_buffer(struct tty_struct *tty)
{
- unsigned long flags;
-
- if ( TTY_INDEX(tty) != 0 )
- return;
-
- spin_lock_irqsave(&xencons_lock, flags);
- wc = wp = 0;
- spin_unlock_irqrestore(&xencons_lock, flags);
+ unsigned long flags;
+
+ if (TTY_INDEX(tty) != 0)
+ return;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ wc = wp = 0;
+ spin_unlock_irqrestore(&xencons_lock, flags);
}
static inline int __xencons_put_char(int ch)
{
- char _ch = (char)ch;
- if ( (wp - wc) == wbuf_size )
- return 0;
- wbuf[WBUF_MASK(wp++)] = _ch;
- return 1;
+ char _ch = (char)ch;
+ if ((wp - wc) == wbuf_size)
+ return 0;
+ wbuf[WBUF_MASK(wp++)] = _ch;
+ return 1;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
static int xencons_write(
- struct tty_struct *tty,
- const unsigned char *buf,
- int count)
-{
- int i;
- unsigned long flags;
-
- if ( TTY_INDEX(tty) != 0 )
- return count;
-
- spin_lock_irqsave(&xencons_lock, flags);
-
- for ( i = 0; i < count; i++ )
- if ( !__xencons_put_char(buf[i]) )
- break;
-
- if ( i != 0 )
- __xencons_tx_flush();
-
- spin_unlock_irqrestore(&xencons_lock, flags);
-
- return i;
+ struct tty_struct *tty,
+ const unsigned char *buf,
+ int count)
+{
+ int i;
+ unsigned long flags;
+
+ if (TTY_INDEX(tty) != 0)
+ return count;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+
+ for (i = 0; i < count; i++)
+ if (!__xencons_put_char(buf[i]))
+ break;
+
+ if (i != 0)
+ __xencons_tx_flush();
+
+ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ return i;
}
#else
static int xencons_write(
- struct tty_struct *tty,
- int from_user,
- const u_char *buf,
- int count)
-{
- int i;
- unsigned long flags;
-
- if ( from_user && verify_area(VERIFY_READ, buf, count) )
- return -EINVAL;
-
- if ( TTY_INDEX(tty) != 0 )
- return count;
-
- spin_lock_irqsave(&xencons_lock, flags);
-
- for ( i = 0; i < count; i++ )
- {
- char ch;
- if ( from_user )
- __get_user(ch, buf + i);
- else
- ch = buf[i];
- if ( !__xencons_put_char(ch) )
- break;
- }
-
- if ( i != 0 )
- __xencons_tx_flush();
-
- spin_unlock_irqrestore(&xencons_lock, flags);
-
- return i;
+ struct tty_struct *tty,
+ int from_user,
+ const u_char *buf,
+ int count)
+{
+ int i;
+ unsigned long flags;
+
+ if (from_user && verify_area(VERIFY_READ, buf, count))
+ return -EINVAL;
+
+ if (TTY_INDEX(tty) != 0)
+ return count;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+
+ for (i = 0; i < count; i++) {
+ char ch;
+ if (from_user)
+ __get_user(ch, buf + i);
+ else
+ ch = buf[i];
+ if (!__xencons_put_char(ch))
+ break;
+ }
+
+ if (i != 0)
+ __xencons_tx_flush();
+
+ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ return i;
}
#endif
static void xencons_put_char(struct tty_struct *tty, u_char ch)
{
- unsigned long flags;
-
- if ( TTY_INDEX(tty) != 0 )
- return;
-
- spin_lock_irqsave(&xencons_lock, flags);
- (void)__xencons_put_char(ch);
- spin_unlock_irqrestore(&xencons_lock, flags);
+ unsigned long flags;
+
+ if (TTY_INDEX(tty) != 0)
+ return;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ (void)__xencons_put_char(ch);
+ spin_unlock_irqrestore(&xencons_lock, flags);
}
static void xencons_flush_chars(struct tty_struct *tty)
{
- unsigned long flags;
-
- if ( TTY_INDEX(tty) != 0 )
- return;
-
- spin_lock_irqsave(&xencons_lock, flags);
- __xencons_tx_flush();
- spin_unlock_irqrestore(&xencons_lock, flags);
+ unsigned long flags;
+
+ if (TTY_INDEX(tty) != 0)
+ return;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ __xencons_tx_flush();
+ spin_unlock_irqrestore(&xencons_lock, flags);
}
static void xencons_wait_until_sent(struct tty_struct *tty, int timeout)
{
- unsigned long orig_jiffies = jiffies;
-
- if ( TTY_INDEX(tty) != 0 )
- return;
-
- while ( DRV(tty->driver)->chars_in_buffer(tty) )
- {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- if ( signal_pending(current) )
- break;
- if ( (timeout != 0) && time_after(jiffies, orig_jiffies + timeout) )
- break;
- }
+ unsigned long orig_jiffies = jiffies;
+
+ if (TTY_INDEX(tty) != 0)
+ return;
+
+ while (DRV(tty->driver)->chars_in_buffer(tty))
+ {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(1);
+ if (signal_pending(current))
+ break;
+ if ( (timeout != 0) &&
+ time_after(jiffies, orig_jiffies + timeout) )
+ break;
+ }
- set_current_state(TASK_RUNNING);
+ set_current_state(TASK_RUNNING);
}
static int xencons_open(struct tty_struct *tty, struct file *filp)
{
- unsigned long flags;
-
- if ( TTY_INDEX(tty) != 0 )
- return 0;
-
- spin_lock_irqsave(&xencons_lock, flags);
- tty->driver_data = NULL;
- if ( xencons_tty == NULL )
- xencons_tty = tty;
- __xencons_tx_flush();
- spin_unlock_irqrestore(&xencons_lock, flags);
-
- return 0;
+ unsigned long flags;
+
+ if (TTY_INDEX(tty) != 0)
+ return 0;
+
+ spin_lock_irqsave(&xencons_lock, flags);
+ tty->driver_data = NULL;
+ if (xencons_tty == NULL)
+ xencons_tty = tty;
+ __xencons_tx_flush();
+ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ return 0;
}
static void xencons_close(struct tty_struct *tty, struct file *filp)
{
- unsigned long flags;
-
- if ( TTY_INDEX(tty) != 0 )
- return;
-
- if ( tty->count == 1 )
- {
- tty->closing = 1;
- tty_wait_until_sent(tty, 0);
- if ( DRV(tty->driver)->flush_buffer != NULL )
- DRV(tty->driver)->flush_buffer(tty);
- if ( tty->ldisc.flush_buffer != NULL )
- tty->ldisc.flush_buffer(tty);
- tty->closing = 0;
- spin_lock_irqsave(&xencons_lock, flags);
- xencons_tty = NULL;
- spin_unlock_irqrestore(&xencons_lock, flags);
- }
+ unsigned long flags;
+
+ if (TTY_INDEX(tty) != 0)
+ return;
+
+ if (tty->count == 1) {
+ tty->closing = 1;
+ tty_wait_until_sent(tty, 0);
+ if (DRV(tty->driver)->flush_buffer != NULL)
+ DRV(tty->driver)->flush_buffer(tty);
+ if (tty->ldisc.flush_buffer != NULL)
+ tty->ldisc.flush_buffer(tty);
+ tty->closing = 0;
+ spin_lock_irqsave(&xencons_lock, flags);
+ xencons_tty = NULL;
+ spin_unlock_irqrestore(&xencons_lock, flags);
+ }
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
static struct tty_operations xencons_ops = {
- .open = xencons_open,
- .close = xencons_close,
- .write = xencons_write,
- .write_room = xencons_write_room,
- .put_char = xencons_put_char,
- .flush_chars = xencons_flush_chars,
- .chars_in_buffer = xencons_chars_in_buffer,
- .send_xchar = xencons_send_xchar,
- .flush_buffer = xencons_flush_buffer,
- .throttle = xencons_throttle,
- .unthrottle = xencons_unthrottle,
- .wait_until_sent = xencons_wait_until_sent,
+ .open = xencons_open,
+ .close = xencons_close,
+ .write = xencons_write,
+ .write_room = xencons_write_room,
+ .put_char = xencons_put_char,
+ .flush_chars = xencons_flush_chars,
+ .chars_in_buffer = xencons_chars_in_buffer,
+ .send_xchar = xencons_send_xchar,
+ .flush_buffer = xencons_flush_buffer,
+ .throttle = xencons_throttle,
+ .unthrottle = xencons_unthrottle,
+ .wait_until_sent = xencons_wait_until_sent,
};
#ifdef CONFIG_XEN_PRIVILEGED_GUEST
static const char *xennullcon_startup(void)
{
- return NULL;
+ return NULL;
}
static int xennullcon_dummy(void)
{
- return 0;
+ return 0;
}
#define DUMMY (void *)xennullcon_dummy
@@ -672,122 +665,128 @@
*/
const struct consw xennull_con = {
- .owner = THIS_MODULE,
- .con_startup = xennullcon_startup,
- .con_init = DUMMY,
- .con_deinit = DUMMY,
- .con_clear = DUMMY,
- .con_putc = DUMMY,
- .con_putcs = DUMMY,
- .con_cursor = DUMMY,
- .con_scroll = DUMMY,
- .con_bmove = DUMMY,
- .con_switch = DUMMY,
- .con_blank = DUMMY,
- .con_font_set = DUMMY,
- .con_font_get = DUMMY,
- .con_font_default = DUMMY,
- .con_font_copy = DUMMY,
- .con_set_palette = DUMMY,
- .con_scrolldelta = DUMMY,
+ .owner = THIS_MODULE,
+ .con_startup = xennullcon_startup,
+ .con_init = DUMMY,
+ .con_deinit = DUMMY,
+ .con_clear = DUMMY,
+ .con_putc = DUMMY,
+ .con_putcs = DUMMY,
+ .con_cursor = DUMMY,
+ .con_scroll = DUMMY,
+ .con_bmove = DUMMY,
+ .con_switch = DUMMY,
+ .con_blank = DUMMY,
+ .con_font_set = DUMMY,
+ .con_font_get = DUMMY,
+ .con_font_default = DUMMY,
+ .con_font_copy = DUMMY,
+ .con_set_palette = DUMMY,
+ .con_scrolldelta = DUMMY,
};
#endif
#endif
static int __init xencons_init(void)
{
- int rc;
-
- if ( xc_mode == XC_OFF )
- return 0;
-
- xencons_ring_init();
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- xencons_driver = alloc_tty_driver((xc_mode == XC_SERIAL) ?
- 1 : MAX_NR_CONSOLES);
- if ( xencons_driver == NULL )
- return -ENOMEM;
+ int rc;
+
+ if (xc_mode == XC_OFF)
+ return 0;
+
+ xencons_ring_init();
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ xencons_driver = alloc_tty_driver((xc_mode == XC_SERIAL) ?
+ 1 : MAX_NR_CONSOLES);
+ if (xencons_driver == NULL)
+ return -ENOMEM;
#else
- memset(&xencons_driver, 0, sizeof(struct tty_driver));
- xencons_driver.magic = TTY_DRIVER_MAGIC;
- xencons_driver.refcount = &xencons_refcount;
- xencons_driver.table = xencons_table;
- xencons_driver.num = (xc_mode == XC_SERIAL) ? 1 : MAX_NR_CONSOLES;
-#endif
-
- DRV(xencons_driver)->major = TTY_MAJOR;
- DRV(xencons_driver)->type = TTY_DRIVER_TYPE_SERIAL;
- DRV(xencons_driver)->subtype = SERIAL_TYPE_NORMAL;
- DRV(xencons_driver)->init_termios = tty_std_termios;
- DRV(xencons_driver)->flags =
- TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_NO_DEVFS;
- DRV(xencons_driver)->termios = xencons_termios;
- DRV(xencons_driver)->termios_locked = xencons_termios_locked;
-
- if ( xc_mode == XC_SERIAL )
- {
- DRV(xencons_driver)->name = "ttyS";
- DRV(xencons_driver)->minor_start = 64 + xc_num;
- DRV(xencons_driver)->name_base = 0 + xc_num;
- }
- else
- {
- DRV(xencons_driver)->name = "tty";
- DRV(xencons_driver)->minor_start = xc_num;
- DRV(xencons_driver)->name_base = xc_num;
- }
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- tty_set_operations(xencons_driver, &xencons_ops);
+ memset(&xencons_driver, 0, sizeof(struct tty_driver));
+ xencons_driver.magic = TTY_DRIVER_MAGIC;
+ xencons_driver.refcount = &xencons_refcount;
+ xencons_driver.table = xencons_table;
+ xencons_driver.num =
+ (xc_mode == XC_SERIAL) ? 1 : MAX_NR_CONSOLES;
+#endif
+
+ DRV(xencons_driver)->major = TTY_MAJOR;
+ DRV(xencons_driver)->type = TTY_DRIVER_TYPE_SERIAL;
+ DRV(xencons_driver)->subtype = SERIAL_TYPE_NORMAL;
+ DRV(xencons_driver)->init_termios = tty_std_termios;
+ DRV(xencons_driver)->flags =
+ TTY_DRIVER_REAL_RAW |
+ TTY_DRIVER_RESET_TERMIOS |
+ TTY_DRIVER_NO_DEVFS;
+ DRV(xencons_driver)->termios = xencons_termios;
+ DRV(xencons_driver)->termios_locked = xencons_termios_locked;
+
+ if (xc_mode == XC_SERIAL)
+ {
+ DRV(xencons_driver)->name = "ttyS";
+ DRV(xencons_driver)->minor_start = 64 + xc_num;
+ DRV(xencons_driver)->name_base = 0 + xc_num;
+ } else {
+ DRV(xencons_driver)->name = "tty";
+ DRV(xencons_driver)->minor_start = xc_num;
+ DRV(xencons_driver)->name_base = xc_num;
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ tty_set_operations(xencons_driver, &xencons_ops);
#else
- xencons_driver.open = xencons_open;
- xencons_driver.close = xencons_close;
- xencons_driver.write = xencons_write;
- xencons_driver.write_room = xencons_write_room;
- xencons_driver.put_char = xencons_put_char;
- xencons_driver.flush_chars = xencons_flush_chars;
- xencons_driver.chars_in_buffer = xencons_chars_in_buffer;
- xencons_driver.send_xchar = xencons_send_xchar;
- xencons_driver.flush_buffer = xencons_flush_buffer;
- xencons_driver.throttle = xencons_throttle;
- xencons_driver.unthrottle = xencons_unthrottle;
- xencons_driver.wait_until_sent = xencons_wait_until_sent;
-#endif
-
- if ( (rc = tty_register_driver(DRV(xencons_driver))) != 0 )
- {
- printk("WARNING: Failed to register Xen virtual "
- "console driver as '%s%d'\n",
- DRV(xencons_driver)->name, DRV(xencons_driver)->name_base);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- put_tty_driver(xencons_driver);
- xencons_driver = NULL;
-#endif
- return rc;
- }
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- tty_register_device(xencons_driver, 0, NULL);
-#endif
-
- if ( xen_start_info->flags & SIF_INITDOMAIN )
- {
- xencons_priv_irq = bind_virq_to_irq(VIRQ_CONSOLE);
- (void)request_irq(xencons_priv_irq,
- xencons_priv_interrupt, 0, "console", NULL);
- }
- else
- {
-
- xencons_ring_register_receiver(xencons_rx);
- }
-
- printk("Xen virtual console successfully installed as %s%d\n",
- DRV(xencons_driver)->name,
- DRV(xencons_driver)->name_base );
+ xencons_driver.open = xencons_open;
+ xencons_driver.close = xencons_close;
+ xencons_driver.write = xencons_write;
+ xencons_driver.write_room = xencons_write_room;
+ xencons_driver.put_char = xencons_put_char;
+ xencons_driver.flush_chars = xencons_flush_chars;
+ xencons_driver.chars_in_buffer = xencons_chars_in_buffer;
+ xencons_driver.send_xchar = xencons_send_xchar;
+ xencons_driver.flush_buffer = xencons_flush_buffer;
+ xencons_driver.throttle = xencons_throttle;
+ xencons_driver.unthrottle = xencons_unthrottle;
+ xencons_driver.wait_until_sent = xencons_wait_until_sent;
+#endif
+
+ if ((rc = tty_register_driver(DRV(xencons_driver))) != 0) {
+ printk("WARNING: Failed to register Xen virtual "
+ "console driver as '%s%d'\n",
+ DRV(xencons_driver)->name,
DRV(xencons_driver)->name_base);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ put_tty_driver(xencons_driver);
+ xencons_driver = NULL;
+#endif
+ return rc;
+ }
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+ tty_register_device(xencons_driver, 0, NULL);
+#endif
+
+ if (xen_start_info->flags & SIF_INITDOMAIN) {
+ xencons_priv_irq = bind_virq_to_irq(VIRQ_CONSOLE);
+ (void)request_irq(xencons_priv_irq,
+ xencons_priv_interrupt, 0, "console", NULL);
+ } else {
+ xencons_ring_register_receiver(xencons_rx);
+ }
+
+ printk("Xen virtual console successfully installed as %s%d\n",
+ DRV(xencons_driver)->name,
+ DRV(xencons_driver)->name_base );
- return 0;
+ return 0;
}
module_init(xencons_init);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c
--- a/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c Thu Sep 22
15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.c Thu Sep 22
15:12:14 2005
@@ -125,3 +125,13 @@
(void)xencons_ring_init();
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.h
--- a/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.h Thu Sep 22
15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/console/xencons_ring.h Thu Sep 22
15:12:14 2005
@@ -3,12 +3,21 @@
asmlinkage int xprintk(const char *fmt, ...);
-
int xencons_ring_init(void);
int xencons_ring_send(const char *data, unsigned len);
-typedef void (xencons_receiver_func)(char *buf, unsigned len,
- struct pt_regs *regs);
+typedef void (xencons_receiver_func)(
+ char *buf, unsigned len, struct pt_regs *regs);
void xencons_ring_register_receiver(xencons_receiver_func *f);
#endif /* _XENCONS_RING_H */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c
--- a/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/evtchn/evtchn.c Thu Sep 22 15:12:14 2005
@@ -1,9 +1,9 @@
/******************************************************************************
* evtchn.c
*
- * Xenolinux driver for receiving and demuxing event-channel signals.
- *
- * Copyright (c) 2004, K A Fraser
+ * Driver for receiving and demuxing event-channel signals.
+ *
+ * Copyright (c) 2004-2005, K A Fraser
* Multi-process extensions Copyright (c) 2004, Steven Smith
*
* This file may be distributed separately from the Linux kernel, or
@@ -46,29 +46,18 @@
#include <linux/init.h>
#define XEN_EVTCHN_MASK_OPS
#include <asm-xen/evtchn.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
-#include <linux/devfs_fs_kernel.h>
-#define OLD_DEVFS
-#else
#include <linux/gfp.h>
-#endif
-
-#ifdef OLD_DEVFS
-/* NB. This must be shared amongst drivers if more things go in /dev/xen */
-static devfs_handle_t xen_dev_dir;
-#endif
struct per_user_data {
- /* Notification ring, accessed via /dev/xen/evtchn. */
-# define EVTCHN_RING_SIZE 2048 /* 2048 16-bit entries */
-# define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
- u16 *ring;
- unsigned int ring_cons, ring_prod, ring_overflow;
-
- /* Processes wait on this queue when ring is empty. */
- wait_queue_head_t evtchn_wait;
- struct fasync_struct *evtchn_async_queue;
+ /* Notification ring, accessed via /dev/xen/evtchn. */
+#define EVTCHN_RING_SIZE 2048 /* 2048 16-bit entries */
+#define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1))
+ u16 *ring;
+ unsigned int ring_cons, ring_prod, ring_overflow;
+
+ /* Processes wait on this queue when ring is empty. */
+ wait_queue_head_t evtchn_wait;
+ struct fasync_struct *evtchn_async_queue;
};
/* Who's bound to each port? */
@@ -77,356 +66,310 @@
void evtchn_device_upcall(int port)
{
- struct per_user_data *u;
-
- spin_lock(&port_user_lock);
-
- mask_evtchn(port);
- clear_evtchn(port);
-
- if ( (u = port_user[port]) != NULL )
- {
- if ( (u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE )
- {
- u->ring[EVTCHN_RING_MASK(u->ring_prod)] = (u16)port;
- if ( u->ring_cons == u->ring_prod++ )
- {
- wake_up_interruptible(&u->evtchn_wait);
- kill_fasync(&u->evtchn_async_queue, SIGIO, POLL_IN);
- }
- }
- else
- {
- u->ring_overflow = 1;
- }
- }
-
- spin_unlock(&port_user_lock);
+ struct per_user_data *u;
+
+ spin_lock(&port_user_lock);
+
+ mask_evtchn(port);
+ clear_evtchn(port);
+
+ if ((u = port_user[port]) != NULL) {
+ if ((u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE) {
+ u->ring[EVTCHN_RING_MASK(u->ring_prod)] = (u16)port;
+ if (u->ring_cons == u->ring_prod++) {
+ wake_up_interruptible(&u->evtchn_wait);
+ kill_fasync(&u->evtchn_async_queue, SIGIO,
POLL_IN);
+ }
+ } else {
+ u->ring_overflow = 1;
+ }
+ }
+
+ spin_unlock(&port_user_lock);
}
static ssize_t evtchn_read(struct file *file, char *buf,
size_t count, loff_t *ppos)
{
- int rc;
- unsigned int c, p, bytes1 = 0, bytes2 = 0;
- DECLARE_WAITQUEUE(wait, current);
- struct per_user_data *u = file->private_data;
-
- add_wait_queue(&u->evtchn_wait, &wait);
-
- count &= ~1; /* even number of bytes */
-
- if ( count == 0 )
- {
- rc = 0;
- goto out;
- }
-
- if ( count > PAGE_SIZE )
- count = PAGE_SIZE;
-
- for ( ; ; )
- {
- set_current_state(TASK_INTERRUPTIBLE);
-
- if ( (c = u->ring_cons) != (p = u->ring_prod) )
- break;
-
- if ( u->ring_overflow )
- {
- rc = -EFBIG;
- goto out;
- }
-
- if ( file->f_flags & O_NONBLOCK )
- {
- rc = -EAGAIN;
- goto out;
- }
-
- if ( signal_pending(current) )
- {
- rc = -ERESTARTSYS;
- goto out;
- }
-
- schedule();
- }
-
- /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
- if ( ((c ^ p) & EVTCHN_RING_SIZE) != 0 )
- {
- bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) * sizeof(u16);
- bytes2 = EVTCHN_RING_MASK(p) * sizeof(u16);
- }
- else
- {
- bytes1 = (p - c) * sizeof(u16);
- bytes2 = 0;
- }
-
- /* Truncate chunks according to caller's maximum byte count. */
- if ( bytes1 > count )
- {
- bytes1 = count;
- bytes2 = 0;
- }
- else if ( (bytes1 + bytes2) > count )
- {
- bytes2 = count - bytes1;
- }
-
- if ( copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) ||
- ((bytes2 != 0) && copy_to_user(&buf[bytes1], &u->ring[0], bytes2)) )
- {
- rc = -EFAULT;
- goto out;
- }
-
- u->ring_cons += (bytes1 + bytes2) / sizeof(u16);
-
- rc = bytes1 + bytes2;
+ int rc;
+ unsigned int c, p, bytes1 = 0, bytes2 = 0;
+ DECLARE_WAITQUEUE(wait, current);
+ struct per_user_data *u = file->private_data;
+
+ add_wait_queue(&u->evtchn_wait, &wait);
+
+ count &= ~1; /* even number of bytes */
+
+ if (count == 0) {
+ rc = 0;
+ goto out;
+ }
+
+ if (count > PAGE_SIZE)
+ count = PAGE_SIZE;
+
+ for (;;) {
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if ((c = u->ring_cons) != (p = u->ring_prod))
+ break;
+
+ if (u->ring_overflow) {
+ rc = -EFBIG;
+ goto out;
+ }
+
+ if (file->f_flags & O_NONBLOCK) {
+ rc = -EAGAIN;
+ goto out;
+ }
+
+ if (signal_pending(current)) {
+ rc = -ERESTARTSYS;
+ goto out;
+ }
+
+ schedule();
+ }
+
+ /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */
+ if (((c ^ p) & EVTCHN_RING_SIZE) != 0) {
+ bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) *
+ sizeof(u16);
+ bytes2 = EVTCHN_RING_MASK(p) * sizeof(u16);
+ } else {
+ bytes1 = (p - c) * sizeof(u16);
+ bytes2 = 0;
+ }
+
+ /* Truncate chunks according to caller's maximum byte count. */
+ if (bytes1 > count) {
+ bytes1 = count;
+ bytes2 = 0;
+ } else if ((bytes1 + bytes2) > count) {
+ bytes2 = count - bytes1;
+ }
+
+ if (copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) ||
+ ((bytes2 != 0) &&
+ copy_to_user(&buf[bytes1], &u->ring[0], bytes2))) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ u->ring_cons += (bytes1 + bytes2) / sizeof(u16);
+
+ rc = bytes1 + bytes2;
out:
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&u->evtchn_wait, &wait);
- return rc;
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&u->evtchn_wait, &wait);
+ return rc;
}
static ssize_t evtchn_write(struct file *file, const char *buf,
size_t count, loff_t *ppos)
{
- int rc, i;
- u16 *kbuf = (u16 *)__get_free_page(GFP_KERNEL);
- struct per_user_data *u = file->private_data;
-
- if ( kbuf == NULL )
- return -ENOMEM;
-
- count &= ~1; /* even number of bytes */
-
- if ( count == 0 )
- {
- rc = 0;
- goto out;
- }
-
- if ( count > PAGE_SIZE )
- count = PAGE_SIZE;
-
- if ( copy_from_user(kbuf, buf, count) != 0 )
- {
- rc = -EFAULT;
- goto out;
- }
-
- spin_lock_irq(&port_user_lock);
- for ( i = 0; i < (count/2); i++ )
- if ( (kbuf[i] < NR_EVENT_CHANNELS) && (port_user[kbuf[i]] == u) )
- unmask_evtchn(kbuf[i]);
- spin_unlock_irq(&port_user_lock);
-
- rc = count;
+ int rc, i;
+ u16 *kbuf = (u16 *)__get_free_page(GFP_KERNEL);
+ struct per_user_data *u = file->private_data;
+
+ if (kbuf == NULL)
+ return -ENOMEM;
+
+ count &= ~1; /* even number of bytes */
+
+ if (count == 0) {
+ rc = 0;
+ goto out;
+ }
+
+ if (count > PAGE_SIZE)
+ count = PAGE_SIZE;
+
+ if (copy_from_user(kbuf, buf, count) != 0) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ spin_lock_irq(&port_user_lock);
+ for (i = 0; i < (count/2); i++)
+ if ((kbuf[i] < NR_EVENT_CHANNELS) && (port_user[kbuf[i]] == u))
+ unmask_evtchn(kbuf[i]);
+ spin_unlock_irq(&port_user_lock);
+
+ rc = count;
out:
- free_page((unsigned long)kbuf);
- return rc;
+ free_page((unsigned long)kbuf);
+ return rc;
}
static int evtchn_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- int rc = 0;
- struct per_user_data *u = file->private_data;
-
- spin_lock_irq(&port_user_lock);
+ int rc = 0;
+ struct per_user_data *u = file->private_data;
+
+ spin_lock_irq(&port_user_lock);
- switch ( cmd )
- {
- case EVTCHN_RESET:
- /* Initialise the ring to empty. Clear errors. */
- u->ring_cons = u->ring_prod = u->ring_overflow = 0;
- break;
-
- case EVTCHN_BIND:
- if ( arg >= NR_EVENT_CHANNELS )
- {
- rc = -EINVAL;
- }
- else if ( port_user[arg] != NULL )
- {
- rc = -EISCONN;
- }
- else
- {
- port_user[arg] = u;
- unmask_evtchn(arg);
- }
- break;
-
- case EVTCHN_UNBIND:
- if ( arg >= NR_EVENT_CHANNELS )
- {
- rc = -EINVAL;
- }
- else if ( port_user[arg] != u )
- {
- rc = -ENOTCONN;
- }
- else
- {
- port_user[arg] = NULL;
- mask_evtchn(arg);
- }
- break;
-
- default:
- rc = -ENOSYS;
- break;
- }
-
- spin_unlock_irq(&port_user_lock);
-
- return rc;
+ switch (cmd) {
+ case EVTCHN_RESET:
+ /* Initialise the ring to empty. Clear errors. */
+ u->ring_cons = u->ring_prod = u->ring_overflow = 0;
+ break;
+
+ case EVTCHN_BIND:
+ if (arg >= NR_EVENT_CHANNELS) {
+ rc = -EINVAL;
+ } else if (port_user[arg] != NULL) {
+ rc = -EISCONN;
+ } else {
+ port_user[arg] = u;
+ unmask_evtchn(arg);
+ }
+ break;
+
+ case EVTCHN_UNBIND:
+ if (arg >= NR_EVENT_CHANNELS) {
+ rc = -EINVAL;
+ } else if (port_user[arg] != u) {
+ rc = -ENOTCONN;
+ } else {
+ port_user[arg] = NULL;
+ mask_evtchn(arg);
+ }
+ break;
+
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+
+ spin_unlock_irq(&port_user_lock);
+
+ return rc;
}
static unsigned int evtchn_poll(struct file *file, poll_table *wait)
{
- unsigned int mask = POLLOUT | POLLWRNORM;
- struct per_user_data *u = file->private_data;
-
- poll_wait(file, &u->evtchn_wait, wait);
- if ( u->ring_cons != u->ring_prod )
- mask |= POLLIN | POLLRDNORM;
- if ( u->ring_overflow )
- mask = POLLERR;
- return mask;
+ unsigned int mask = POLLOUT | POLLWRNORM;
+ struct per_user_data *u = file->private_data;
+
+ poll_wait(file, &u->evtchn_wait, wait);
+ if (u->ring_cons != u->ring_prod)
+ mask |= POLLIN | POLLRDNORM;
+ if (u->ring_overflow)
+ mask = POLLERR;
+ return mask;
}
static int evtchn_fasync(int fd, struct file *filp, int on)
{
- struct per_user_data *u = filp->private_data;
- return fasync_helper(fd, filp, on, &u->evtchn_async_queue);
+ struct per_user_data *u = filp->private_data;
+ return fasync_helper(fd, filp, on, &u->evtchn_async_queue);
}
static int evtchn_open(struct inode *inode, struct file *filp)
{
- struct per_user_data *u;
-
- if ( (u = kmalloc(sizeof(*u), GFP_KERNEL)) == NULL )
- return -ENOMEM;
-
- memset(u, 0, sizeof(*u));
- init_waitqueue_head(&u->evtchn_wait);
-
- if ( (u->ring = (u16 *)__get_free_page(GFP_KERNEL)) == NULL )
- {
- kfree(u);
- return -ENOMEM;
- }
-
- filp->private_data = u;
-
- return 0;
+ struct per_user_data *u;
+
+ if ((u = kmalloc(sizeof(*u), GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+
+ memset(u, 0, sizeof(*u));
+ init_waitqueue_head(&u->evtchn_wait);
+
+ if ((u->ring = (u16 *)__get_free_page(GFP_KERNEL)) == NULL)
+ {
+ kfree(u);
+ return -ENOMEM;
+ }
+
+ filp->private_data = u;
+
+ return 0;
}
static int evtchn_release(struct inode *inode, struct file *filp)
{
- int i;
- struct per_user_data *u = filp->private_data;
-
- spin_lock_irq(&port_user_lock);
-
- free_page((unsigned long)u->ring);
-
- for ( i = 0; i < NR_EVENT_CHANNELS; i++ )
- {
- if ( port_user[i] == u )
- {
- port_user[i] = NULL;
- mask_evtchn(i);
- }
- }
-
- spin_unlock_irq(&port_user_lock);
-
- kfree(u);
-
- return 0;
+ int i;
+ struct per_user_data *u = filp->private_data;
+
+ spin_lock_irq(&port_user_lock);
+
+ free_page((unsigned long)u->ring);
+
+ for (i = 0; i < NR_EVENT_CHANNELS; i++)
+ {
+ if (port_user[i] == u)
+ {
+ port_user[i] = NULL;
+ mask_evtchn(i);
+ }
+ }
+
+ spin_unlock_irq(&port_user_lock);
+
+ kfree(u);
+
+ return 0;
}
static struct file_operations evtchn_fops = {
- .owner = THIS_MODULE,
- .read = evtchn_read,
- .write = evtchn_write,
- .ioctl = evtchn_ioctl,
- .poll = evtchn_poll,
- .fasync = evtchn_fasync,
- .open = evtchn_open,
- .release = evtchn_release,
+ .owner = THIS_MODULE,
+ .read = evtchn_read,
+ .write = evtchn_write,
+ .ioctl = evtchn_ioctl,
+ .poll = evtchn_poll,
+ .fasync = evtchn_fasync,
+ .open = evtchn_open,
+ .release = evtchn_release,
};
static struct miscdevice evtchn_miscdev = {
- .minor = EVTCHN_MINOR,
- .name = "evtchn",
- .fops = &evtchn_fops,
+ .minor = EVTCHN_MINOR,
+ .name = "evtchn",
+ .fops = &evtchn_fops,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
- .devfs_name = "misc/evtchn",
+ .devfs_name = "misc/evtchn",
#endif
};
static int __init evtchn_init(void)
{
-#ifdef OLD_DEVFS
- devfs_handle_t symlink_handle;
- int pos;
- char link_dest[64];
-#endif
- int err;
-
- spin_lock_init(&port_user_lock);
- memset(port_user, 0, sizeof(port_user));
-
- /* (DEVFS) create '/dev/misc/evtchn'. */
- err = misc_register(&evtchn_miscdev);
- if ( err != 0 )
- {
- printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
- return err;
- }
-
-#ifdef OLD_DEVFS
- /* (DEVFS) create directory '/dev/xen'. */
- xen_dev_dir = devfs_mk_dir(NULL, "xen", NULL);
-
- /* (DEVFS) &link_dest[pos] == '../misc/evtchn'. */
- pos = devfs_generate_path(evtchn_miscdev.devfs_handle,
- &link_dest[3],
- sizeof(link_dest) - 3);
- if ( pos >= 0 )
- strncpy(&link_dest[pos], "../", 3);
-
- /* (DEVFS) symlink '/dev/xen/evtchn' -> '../misc/evtchn'. */
- (void)devfs_mk_symlink(xen_dev_dir,
- "evtchn",
- DEVFS_FL_DEFAULT,
- &link_dest[pos],
- &symlink_handle,
- NULL);
-
- /* (DEVFS) automatically destroy the symlink with its destination. */
- devfs_auto_unregister(evtchn_miscdev.devfs_handle, symlink_handle);
-#endif
-
- printk("Event-channel device installed.\n");
-
- return 0;
+ int err;
+
+ spin_lock_init(&port_user_lock);
+ memset(port_user, 0, sizeof(port_user));
+
+ /* (DEVFS) create '/dev/misc/evtchn'. */
+ err = misc_register(&evtchn_miscdev);
+ if (err != 0)
+ {
+ printk(KERN_ALERT "Could not register /dev/misc/evtchn\n");
+ return err;
+ }
+
+ printk("Event-channel device installed.\n");
+
+ return 0;
}
static void evtchn_cleanup(void)
{
- misc_deregister(&evtchn_miscdev);
+ misc_deregister(&evtchn_miscdev);
}
module_init(evtchn_init);
module_exit(evtchn_cleanup);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/netback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/netback/common.h Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/common.h Thu Sep 22 15:12:14 2005
@@ -62,9 +62,7 @@
/* Private indexes into shared ring. */
NETIF_RING_IDX rx_req_cons;
NETIF_RING_IDX rx_resp_prod; /* private version of shared variable */
-#ifdef CONFIG_XEN_NETDEV_GRANT
NETIF_RING_IDX rx_resp_prod_copy;
-#endif
NETIF_RING_IDX tx_req_cons;
NETIF_RING_IDX tx_resp_prod; /* private version of shared variable */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/netback/netback.c
--- a/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Thu Sep 22
15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netback/netback.c Thu Sep 22
15:12:14 2005
@@ -23,7 +23,7 @@
static int make_rx_response(netif_t *netif,
u16 id,
s8 st,
- unsigned long addr,
+ u16 offset,
u16 size,
u16 csum_valid);
@@ -41,11 +41,7 @@
static multicall_entry_t rx_mcl[NETIF_RX_RING_SIZE*2+1];
static mmu_update_t rx_mmu[NETIF_RX_RING_SIZE];
-#ifdef CONFIG_XEN_NETDEV_GRANT
static gnttab_transfer_t grant_rx_op[MAX_PENDING_REQS];
-#else
-static struct mmuext_op rx_mmuext[NETIF_RX_RING_SIZE];
-#endif
static unsigned char rx_notify[NR_EVENT_CHANNELS];
/* Don't currently gate addition of an interface to the tx scheduling list. */
@@ -72,14 +68,9 @@
static struct sk_buff_head tx_queue;
-#ifdef CONFIG_XEN_NETDEV_GRANT
static u16 grant_tx_ref[MAX_PENDING_REQS];
static gnttab_unmap_grant_ref_t tx_unmap_ops[MAX_PENDING_REQS];
static gnttab_map_grant_ref_t tx_map_ops[MAX_PENDING_REQS];
-
-#else
-static multicall_entry_t tx_mcl[MAX_PENDING_REQS];
-#endif
static struct list_head net_schedule_list;
static spinlock_t net_schedule_list_lock;
@@ -108,7 +99,7 @@
return mfn;
}
-#ifndef CONFIG_XEN_NETDEV_GRANT
+#if 0
static void free_mfn(unsigned long mfn)
{
unsigned long flags;
@@ -180,18 +171,7 @@
dev_kfree_skb(skb);
skb = nskb;
}
-#ifdef CONFIG_XEN_NETDEV_GRANT
-#ifdef DEBUG_GRANT
- printk(KERN_ALERT "#### be_xmit: req_prod=%d req_cons=%d "
- "id=%04x gr=%04x\n",
- netif->rx->req_prod,
- netif->rx_req_cons,
- netif->rx->ring[
- MASK_NETIF_RX_IDX(netif->rx_req_cons)].req.id,
- netif->rx->ring[
- MASK_NETIF_RX_IDX(netif->rx_req_cons)].req.gref);
-#endif
-#endif
+
netif->rx_req_cons++;
netif_get(netif);
@@ -232,11 +212,7 @@
u16 size, id, evtchn;
multicall_entry_t *mcl;
mmu_update_t *mmu;
-#ifdef CONFIG_XEN_NETDEV_GRANT
gnttab_transfer_t *gop;
-#else
- struct mmuext_op *mmuext;
-#endif
unsigned long vdata, old_mfn, new_mfn;
struct sk_buff_head rxq;
struct sk_buff *skb;
@@ -247,11 +223,7 @@
mcl = rx_mcl;
mmu = rx_mmu;
-#ifdef CONFIG_XEN_NETDEV_GRANT
gop = grant_rx_op;
-#else
- mmuext = rx_mmuext;
-#endif
while ((skb = skb_dequeue(&rx_queue)) != NULL) {
netif = netdev_priv(skb->dev);
@@ -277,25 +249,13 @@
pfn_pte_ma(new_mfn, PAGE_KERNEL), 0);
mcl++;
-#ifdef CONFIG_XEN_NETDEV_GRANT
gop->mfn = old_mfn;
gop->domid = netif->domid;
gop->ref = netif->rx->ring[
MASK_NETIF_RX_IDX(netif->rx_resp_prod_copy)].req.gref;
netif->rx_resp_prod_copy++;
gop++;
-#else
- mcl->op = __HYPERVISOR_mmuext_op;
- mcl->args[0] = (unsigned long)mmuext;
- mcl->args[1] = 1;
- mcl->args[2] = 0;
- mcl->args[3] = netif->domid;
- mcl++;
-
- mmuext->cmd = MMUEXT_REASSIGN_PAGE;
- mmuext->arg1.mfn = old_mfn;
- mmuext++;
-#endif
+
mmu->ptr = ((maddr_t)new_mfn << PAGE_SHIFT) |
MMU_MACHPHYS_UPDATE;
mmu->val = __pa(vdata) >> PAGE_SHIFT;
@@ -303,9 +263,6 @@
__skb_queue_tail(&rxq, skb);
-#ifdef DEBUG_GRANT
- dump_packet('a', old_mfn, vdata);
-#endif
/* Filled the batch queue? */
if ((mcl - rx_mcl) == ARRAY_SIZE(rx_mcl))
break;
@@ -321,17 +278,12 @@
mcl->args[3] = DOMID_SELF;
mcl++;
-#ifdef CONFIG_XEN_NETDEV_GRANT
mcl[-2].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
-#else
- mcl[-3].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
-#endif
BUG_ON(HYPERVISOR_multicall(rx_mcl, mcl - rx_mcl) != 0);
mcl = rx_mcl;
-#ifdef CONFIG_XEN_NETDEV_GRANT
- if(HYPERVISOR_grant_table_op(GNTTABOP_transfer, grant_rx_op,
- gop - grant_rx_op)) {
+ if( HYPERVISOR_grant_table_op(GNTTABOP_transfer, grant_rx_op,
+ gop - grant_rx_op)) {
/*
* The other side has given us a bad grant ref, or has no
* headroom, or has gone away. Unfortunately the current grant
@@ -343,20 +295,14 @@
grant_rx_op[0].domid, gop - grant_rx_op);
}
gop = grant_rx_op;
-#else
- mmuext = rx_mmuext;
-#endif
+
while ((skb = __skb_dequeue(&rxq)) != NULL) {
netif = netdev_priv(skb->dev);
size = skb->tail - skb->data;
/* Rederive the machine addresses. */
new_mfn = mcl[0].args[1] >> PAGE_SHIFT;
-#ifdef CONFIG_XEN_NETDEV_GRANT
old_mfn = 0; /* XXX Fix this so we can free_mfn() on error! */
-#else
- old_mfn = mmuext[0].arg1.mfn;
-#endif
atomic_set(&(skb_shinfo(skb)->dataref), 1);
skb_shinfo(skb)->nr_frags = 0;
skb_shinfo(skb)->frag_list = NULL;
@@ -369,27 +315,17 @@
/* Check the reassignment error code. */
status = NETIF_RSP_OKAY;
-#ifdef CONFIG_XEN_NETDEV_GRANT
if(gop->status != 0) {
DPRINTK("Bad status %d from grant transfer to DOM%u\n",
gop->status, netif->domid);
/* XXX SMH: should free 'old_mfn' here */
status = NETIF_RSP_ERROR;
}
-#else
- if (unlikely(mcl[1].result != 0)) {
- DPRINTK("Failed MMU update transferring to DOM%u\n",
- netif->domid);
- free_mfn(old_mfn);
- status = NETIF_RSP_ERROR;
- }
-#endif
evtchn = netif->evtchn;
id = netif->rx->ring[
MASK_NETIF_RX_IDX(netif->rx_resp_prod)].req.id;
if (make_rx_response(netif, id, status,
- (old_mfn << PAGE_SHIFT) | /* XXX */
- ((unsigned long)skb->data & ~PAGE_MASK),
+ (unsigned long)skb->data & ~PAGE_MASK,
size, skb->proto_csum_valid) &&
(rx_notify[evtchn] == 0)) {
rx_notify[evtchn] = 1;
@@ -398,13 +334,8 @@
netif_put(netif);
dev_kfree_skb(skb);
-#ifdef CONFIG_XEN_NETDEV_GRANT
mcl++;
gop++;
-#else
- mcl += 2;
- mmuext += 1;
-#endif
}
while (notify_nr != 0) {
@@ -486,11 +417,7 @@
inline static void net_tx_action_dealloc(void)
{
-#ifdef CONFIG_XEN_NETDEV_GRANT
gnttab_unmap_grant_ref_t *gop;
-#else
- multicall_entry_t *mcl;
-#endif
u16 pending_idx;
PEND_RING_IDX dc, dp;
netif_t *netif;
@@ -498,7 +425,6 @@
dc = dealloc_cons;
dp = dealloc_prod;
-#ifdef CONFIG_XEN_NETDEV_GRANT
/*
* Free up any grants we have finished using
*/
@@ -513,26 +439,8 @@
}
BUG_ON(HYPERVISOR_grant_table_op(
GNTTABOP_unmap_grant_ref, tx_unmap_ops, gop - tx_unmap_ops));
-#else
- mcl = tx_mcl;
- while (dc != dp) {
- pending_idx = dealloc_ring[MASK_PEND_IDX(dc++)];
- MULTI_update_va_mapping(mcl, MMAP_VADDR(pending_idx),
- __pte(0), 0);
- mcl++;
- }
-
- mcl[-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
- BUG_ON(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0);
-
- mcl = tx_mcl;
-#endif
+
while (dealloc_cons != dp) {
-#ifndef CONFIG_XEN_NETDEV_GRANT
- /* The update_va_mapping() must not fail. */
- BUG_ON(mcl[0].result != 0);
-#endif
-
pending_idx = dealloc_ring[MASK_PEND_IDX(dealloc_cons++)];
netif = pending_tx_info[pending_idx].netif;
@@ -556,10 +464,6 @@
add_to_net_schedule_list_tail(netif);
netif_put(netif);
-
-#ifndef CONFIG_XEN_NETDEV_GRANT
- mcl++;
-#endif
}
}
@@ -572,21 +476,13 @@
netif_tx_request_t txreq;
u16 pending_idx;
NETIF_RING_IDX i;
-#ifdef CONFIG_XEN_NETDEV_GRANT
gnttab_map_grant_ref_t *mop;
-#else
- multicall_entry_t *mcl;
-#endif
unsigned int data_len;
if (dealloc_cons != dealloc_prod)
net_tx_action_dealloc();
-#ifdef CONFIG_XEN_NETDEV_GRANT
mop = tx_map_ops;
-#else
- mcl = tx_mcl;
-#endif
while ((NR_PENDING_REQS < MAX_PENDING_REQS) &&
!list_empty(&net_schedule_list)) {
/* Get a netif from the list with work to do. */
@@ -657,8 +553,7 @@
}
/* No crossing a page as the payload mustn't fragment. */
- if (unlikely(((txreq.addr & ~PAGE_MASK) + txreq.size) >=
- PAGE_SIZE)) {
+ if (unlikely((txreq.offset + txreq.size) >= PAGE_SIZE)) {
DPRINTK("txreq.addr: %lx, size: %u, end: %lu\n",
txreq.addr, txreq.size,
(txreq.addr &~PAGE_MASK) + txreq.size);
@@ -682,20 +577,12 @@
/* Packets passed to netif_rx() must have some headroom. */
skb_reserve(skb, 16);
-#ifdef CONFIG_XEN_NETDEV_GRANT
+
mop->host_addr = MMAP_VADDR(pending_idx);
mop->dom = netif->domid;
- mop->ref = txreq.addr >> PAGE_SHIFT;
+ mop->ref = txreq.gref;
mop->flags = GNTMAP_host_map | GNTMAP_readonly;
mop++;
-#else
- MULTI_update_va_mapping_otherdomain(
- mcl, MMAP_VADDR(pending_idx),
- pfn_pte_ma(txreq.addr >> PAGE_SHIFT, PAGE_KERNEL),
- 0, netif->domid);
-
- mcl++;
-#endif
memcpy(&pending_tx_info[pending_idx].req,
&txreq, sizeof(txreq));
@@ -706,17 +593,10 @@
pending_cons++;
-#ifdef CONFIG_XEN_NETDEV_GRANT
if ((mop - tx_map_ops) >= ARRAY_SIZE(tx_map_ops))
break;
-#else
- /* Filled the batch queue? */
- if ((mcl - tx_mcl) == ARRAY_SIZE(tx_mcl))
- break;
-#endif
- }
-
-#ifdef CONFIG_XEN_NETDEV_GRANT
+ }
+
if (mop == tx_map_ops)
return;
@@ -724,14 +604,6 @@
GNTTABOP_map_grant_ref, tx_map_ops, mop - tx_map_ops));
mop = tx_map_ops;
-#else
- if (mcl == tx_mcl)
- return;
-
- BUG_ON(HYPERVISOR_multicall(tx_mcl, mcl - tx_mcl) != 0);
-
- mcl = tx_mcl;
-#endif
while ((skb = __skb_dequeue(&tx_queue)) != NULL) {
pending_idx = *((u16 *)skb->data);
netif = pending_tx_info[pending_idx].netif;
@@ -739,7 +611,6 @@
sizeof(txreq));
/* Check the remap error code. */
-#ifdef CONFIG_XEN_NETDEV_GRANT
if (unlikely(mop->handle < 0)) {
printk(KERN_ALERT "#### netback grant fails\n");
make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
@@ -754,30 +625,13 @@
__pa(MMAP_VADDR(pending_idx)) >> PAGE_SHIFT] =
FOREIGN_FRAME(mop->dev_bus_addr >> PAGE_SHIFT);
grant_tx_ref[pending_idx] = mop->handle;
-#else
- if (unlikely(mcl[0].result != 0)) {
- DPRINTK("Bad page frame\n");
- make_tx_response(netif, txreq.id, NETIF_RSP_ERROR);
- netif_put(netif);
- kfree_skb(skb);
- mcl++;
- pending_ring[MASK_PEND_IDX(pending_prod++)] =
- pending_idx;
- continue;
- }
-
- phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx)) >>
- PAGE_SHIFT] =
- FOREIGN_FRAME(txreq.addr >> PAGE_SHIFT);
-#endif
data_len = (txreq.size > PKT_PROT_LEN) ?
PKT_PROT_LEN : txreq.size;
__skb_put(skb, data_len);
memcpy(skb->data,
- (void *)(MMAP_VADDR(pending_idx)|
- (txreq.addr&~PAGE_MASK)),
+ (void *)(MMAP_VADDR(pending_idx)|txreq.offset),
data_len);
if (data_len < txreq.size) {
/* Append the packet payload as a fragment. */
@@ -786,7 +640,7 @@
skb_shinfo(skb)->frags[0].size =
txreq.size - data_len;
skb_shinfo(skb)->frags[0].page_offset =
- (txreq.addr + data_len) & ~PAGE_MASK;
+ txreq.offset + data_len;
skb_shinfo(skb)->nr_frags = 1;
} else {
/* Schedule a response immediately. */
@@ -813,11 +667,7 @@
netif_rx(skb);
netif->dev->last_rx = jiffies;
-#ifdef CONFIG_XEN_NETDEV_GRANT
mop++;
-#else
- mcl++;
-#endif
}
}
@@ -874,7 +724,7 @@
static int make_rx_response(netif_t *netif,
u16 id,
s8 st,
- unsigned long addr,
+ u16 offset,
u16 size,
u16 csum_valid)
{
@@ -882,7 +732,7 @@
netif_rx_response_t *resp;
resp = &netif->rx->ring[MASK_NETIF_RX_IDX(i)].resp;
- resp->addr = addr;
+ resp->offset = offset;
resp->csum_valid = csum_valid;
resp->id = id;
resp->status = (s16)size;
@@ -937,9 +787,6 @@
return 0;
IPRINTK("Initialising Xen netif backend.\n");
-#ifdef CONFIG_XEN_NETDEV_GRANT
- IPRINTK("Using grant tables.\n");
-#endif
/* We can increase reservation by this much in net_rx_action(). */
balloon_update_driver_allowance(NETIF_RX_RING_SIZE);
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Thu Sep 22
15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c Thu Sep 22
15:12:14 2005
@@ -256,8 +256,8 @@
for (i = np->tx_resp_cons; i != prod; i++) {
id = np->tx->ring[MASK_NETIF_TX_IDX(i)].resp.id;
skb = np->tx_skbs[id];
-#ifdef CONFIG_XEN_NETDEV_GRANT
- if
(unlikely(gnttab_query_foreign_access(np->grant_tx_ref[id]) != 0)) {
+ if (unlikely(gnttab_query_foreign_access(
+ np->grant_tx_ref[id]) != 0)) {
printk(KERN_ALERT "network_tx_buf_gc: warning "
"-- grant still in use by backend "
"domain.\n");
@@ -268,7 +268,6 @@
gnttab_release_grant_reference(
&np->gref_tx_head, np->grant_tx_ref[id]);
np->grant_tx_ref[id] = GRANT_INVALID_REF;
-#endif
ADD_ID_TO_FREELIST(np->tx_skbs, id);
dev_kfree_skb_irq(skb);
}
@@ -287,10 +286,7 @@
mb();
} while (prod != np->tx->resp_prod);
-#ifdef CONFIG_XEN_NETDEV_GRANT
out:
-#endif
-
if (np->tx_full && ((np->tx->req_prod - prod) < NETIF_TX_RING_SIZE)) {
np->tx_full = 0;
if (np->user_state == UST_OPEN)
@@ -307,9 +303,7 @@
int i, batch_target;
NETIF_RING_IDX req_prod = np->rx->req_prod;
struct xen_memory_reservation reservation;
-#ifdef CONFIG_XEN_NETDEV_GRANT
grant_ref_t ref;
-#endif
if (unlikely(np->backend_state != BEST_CONNECTED))
return;
@@ -343,13 +337,11 @@
np->rx_skbs[id] = skb;
np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.id = id;
-#ifdef CONFIG_XEN_NETDEV_GRANT
ref = gnttab_claim_grant_reference(&np->gref_rx_head);
BUG_ON((signed short)ref < 0);
np->grant_rx_ref[id] = ref;
gnttab_grant_foreign_transfer_ref(ref, np->backend_id);
np->rx->ring[MASK_NETIF_RX_IDX(req_prod + i)].req.gref = ref;
-#endif
rx_pfn_array[i] = virt_to_mfn(skb->head);
/* Remove this page from map before passing back to Xen. */
@@ -400,10 +392,8 @@
struct net_private *np = netdev_priv(dev);
netif_tx_request_t *tx;
NETIF_RING_IDX i;
-#ifdef CONFIG_XEN_NETDEV_GRANT
grant_ref_t ref;
unsigned long mfn;
-#endif
if (unlikely(np->tx_full)) {
printk(KERN_ALERT "%s: full queue wasn't stopped!\n",
@@ -439,18 +429,13 @@
tx = &np->tx->ring[MASK_NETIF_TX_IDX(i)].req;
tx->id = id;
-#ifdef CONFIG_XEN_NETDEV_GRANT
ref = gnttab_claim_grant_reference(&np->gref_tx_head);
BUG_ON((signed short)ref < 0);
mfn = virt_to_mfn(skb->data);
gnttab_grant_foreign_access_ref(
ref, np->backend_id, mfn, GNTMAP_readonly);
- tx->addr = ref << PAGE_SHIFT;
- np->grant_tx_ref[id] = ref;
-#else
- tx->addr = virt_to_mfn(skb->data) << PAGE_SHIFT;
-#endif
- tx->addr |= (unsigned long)skb->data & ~PAGE_MASK;
+ tx->gref = np->grant_tx_ref[id] = ref;
+ tx->offset = (unsigned long)skb->data & ~PAGE_MASK;
tx->size = skb->len;
tx->csum_blank = (skb->ip_summed == CHECKSUM_HW);
@@ -511,10 +496,8 @@
int work_done, budget, more_to_do = 1;
struct sk_buff_head rxq;
unsigned long flags;
-#ifdef CONFIG_XEN_NETDEV_GRANT
unsigned long mfn;
grant_ref_t ref;
-#endif
spin_lock(&np->rx_lock);
@@ -550,7 +533,6 @@
continue;
}
-#ifdef CONFIG_XEN_NETDEV_GRANT
ref = np->grant_rx_ref[rx->id];
if(ref == GRANT_INVALID_REF) {
@@ -568,17 +550,12 @@
np->grant_rx_ref[rx->id] = GRANT_INVALID_REF;
mfn = gnttab_end_foreign_transfer_ref(ref);
gnttab_release_grant_reference(&np->gref_rx_head, ref);
-#endif
skb = np->rx_skbs[rx->id];
ADD_ID_TO_FREELIST(np->rx_skbs, rx->id);
/* NB. We handle skb overflow later. */
-#ifdef CONFIG_XEN_NETDEV_GRANT
- skb->data = skb->head + rx->addr;
-#else
- skb->data = skb->head + (rx->addr & ~PAGE_MASK);
-#endif
+ skb->data = skb->head + rx->offset;
skb->len = rx->status;
skb->tail = skb->data + skb->len;
@@ -589,30 +566,14 @@
np->stats.rx_bytes += rx->status;
/* Remap the page. */
-#ifdef CONFIG_XEN_NETDEV_GRANT
mmu->ptr = ((maddr_t)mfn << PAGE_SHIFT) | MMU_MACHPHYS_UPDATE;
-#else
- mmu->ptr = (rx->addr & PAGE_MASK) | MMU_MACHPHYS_UPDATE;
-#endif
mmu->val = __pa(skb->head) >> PAGE_SHIFT;
mmu++;
-#ifdef CONFIG_XEN_NETDEV_GRANT
MULTI_update_va_mapping(mcl, (unsigned long)skb->head,
pfn_pte_ma(mfn, PAGE_KERNEL), 0);
-#else
- MULTI_update_va_mapping(mcl, (unsigned long)skb->head,
- pfn_pte_ma(rx->addr >> PAGE_SHIFT,
- PAGE_KERNEL), 0);
-#endif
mcl++;
-#ifdef CONFIG_XEN_NETDEV_GRANT
phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] = mfn;
-#else
- phys_to_machine_mapping[__pa(skb->head) >> PAGE_SHIFT] =
- rx->addr >> PAGE_SHIFT;
-#endif
-
__skb_queue_tail(&rxq, skb);
}
@@ -773,16 +734,12 @@
tx = &np->tx->ring[requeue_idx++].req;
tx->id = i;
-#ifdef CONFIG_XEN_NETDEV_GRANT
gnttab_grant_foreign_access_ref(
np->grant_tx_ref[i], np->backend_id,
virt_to_mfn(np->tx_skbs[i]->data),
GNTMAP_readonly);
- tx->addr = np->grant_tx_ref[i] << PAGE_SHIFT;
-#else
- tx->addr = virt_to_mfn(skb->data) << PAGE_SHIFT;
-#endif
- tx->addr |= (unsigned long)skb->data & ~PAGE_MASK;
+ tx->gref = np->grant_tx_ref[i];
+ tx->offset = (unsigned long)skb->data & ~PAGE_MASK;
tx->size = skb->len;
np->stats.tx_bytes += skb->len;
@@ -795,12 +752,10 @@
/* Rebuild the RX buffer freelist and the RX ring itself. */
for (requeue_idx = 0, i = 1; i <= NETIF_RX_RING_SIZE; i++) {
if ((unsigned long)np->rx_skbs[i] >= __PAGE_OFFSET) {
-#ifdef CONFIG_XEN_NETDEV_GRANT
gnttab_grant_foreign_transfer_ref(
np->grant_rx_ref[i], np->backend_id);
np->rx->ring[requeue_idx].req.gref =
np->grant_rx_ref[i];
-#endif
np->rx->ring[requeue_idx].req.id = i;
requeue_idx++;
}
@@ -862,11 +817,9 @@
static void netif_uninit(struct net_device *dev)
{
-#ifdef CONFIG_XEN_NETDEV_GRANT
struct net_private *np = netdev_priv(dev);
gnttab_free_grant_references(np->gref_tx_head);
gnttab_free_grant_references(np->gref_rx_head);
-#endif
}
static struct ethtool_ops network_ethtool_ops =
@@ -911,19 +864,14 @@
/* Initialise {tx,rx}_skbs as a free chain containing every entry. */
for (i = 0; i <= NETIF_TX_RING_SIZE; i++) {
np->tx_skbs[i] = (void *)((unsigned long) i+1);
-#ifdef CONFIG_XEN_NETDEV_GRANT
np->grant_tx_ref[i] = GRANT_INVALID_REF;
-#endif
}
for (i = 0; i <= NETIF_RX_RING_SIZE; i++) {
np->rx_skbs[i] = (void *)((unsigned long) i+1);
-#ifdef CONFIG_XEN_NETDEV_GRANT
np->grant_rx_ref[i] = GRANT_INVALID_REF;
-#endif
- }
-
-#ifdef CONFIG_XEN_NETDEV_GRANT
+ }
+
/* A grant for every tx ring slot */
if (gnttab_alloc_grant_references(NETIF_TX_RING_SIZE,
&np->gref_tx_head) < 0) {
@@ -937,7 +885,6 @@
gnttab_free_grant_references(np->gref_tx_head);
goto exit;
}
-#endif
netdev->open = network_open;
netdev->hard_start_xmit = network_start_xmit;
@@ -971,10 +918,8 @@
return err;
exit_free_grefs:
-#ifdef CONFIG_XEN_NETDEV_GRANT
gnttab_free_grant_references(np->gref_tx_head);
gnttab_free_grant_references(np->gref_rx_head);
-#endif
goto exit;
}
@@ -1024,10 +969,8 @@
evtchn_op_t op = { .cmd = EVTCHNOP_alloc_unbound };
int err;
-#ifdef CONFIG_XEN_NETDEV_GRANT
info->tx_ring_ref = GRANT_INVALID_REF;
info->rx_ring_ref = GRANT_INVALID_REF;
-#endif
info->tx = (netif_tx_interface_t *)__get_free_page(GFP_KERNEL);
if (info->tx == 0) {
@@ -1045,7 +988,6 @@
memset(info->rx, 0, PAGE_SIZE);
info->backend_state = BEST_DISCONNECTED;
-#ifdef CONFIG_XEN_NETDEV_GRANT
err = gnttab_grant_foreign_access(info->backend_id,
virt_to_mfn(info->tx), 0);
if (err < 0) {
@@ -1061,11 +1003,6 @@
goto out;
}
info->rx_ring_ref = err;
-
-#else
- info->tx_ring_ref = virt_to_mfn(info->tx);
- info->rx_ring_ref = virt_to_mfn(info->rx);
-#endif
op.u.alloc_unbound.dom = info->backend_id;
err = HYPERVISOR_event_channel_op(&op);
@@ -1084,7 +1021,6 @@
free_page((unsigned long)info->rx);
info->rx = 0;
-#ifdef CONFIG_XEN_NETDEV_GRANT
if (info->tx_ring_ref != GRANT_INVALID_REF)
gnttab_end_foreign_access(info->tx_ring_ref, 0);
info->tx_ring_ref = GRANT_INVALID_REF;
@@ -1092,7 +1028,6 @@
if (info->rx_ring_ref != GRANT_INVALID_REF)
gnttab_end_foreign_access(info->rx_ring_ref, 0);
info->rx_ring_ref = GRANT_INVALID_REF;
-#endif
return err;
}
@@ -1106,7 +1041,6 @@
free_page((unsigned long)info->rx);
info->rx = 0;
-#ifdef CONFIG_XEN_NETDEV_GRANT
if (info->tx_ring_ref != GRANT_INVALID_REF)
gnttab_end_foreign_access(info->tx_ring_ref, 0);
info->tx_ring_ref = GRANT_INVALID_REF;
@@ -1114,7 +1048,6 @@
if (info->rx_ring_ref != GRANT_INVALID_REF)
gnttab_end_foreign_access(info->rx_ring_ref, 0);
info->rx_ring_ref = GRANT_INVALID_REF;
-#endif
unbind_evtchn_from_irqhandler(info->evtchn, info->netdev);
info->evtchn = 0;
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
--- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Thu Sep 22
15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Thu Sep 22
15:12:14 2005
@@ -41,232 +41,253 @@
static int privcmd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long data)
{
- int ret = -ENOSYS;
-
- switch ( cmd )
- {
- case IOCTL_PRIVCMD_HYPERCALL:
- {
- privcmd_hypercall_t hypercall;
+ int ret = -ENOSYS;
+
+ switch (cmd) {
+ case IOCTL_PRIVCMD_HYPERCALL: {
+ privcmd_hypercall_t hypercall;
- if ( copy_from_user(&hypercall, (void *)data, sizeof(hypercall)) )
- return -EFAULT;
+ if (copy_from_user(&hypercall, (void *)data,
+ sizeof(hypercall)))
+ return -EFAULT;
#if defined(__i386__)
- __asm__ __volatile__ (
- "pushl %%ebx; pushl %%ecx; pushl %%edx; pushl %%esi; pushl %%edi; "
- "movl 4(%%eax),%%ebx ;"
- "movl 8(%%eax),%%ecx ;"
- "movl 12(%%eax),%%edx ;"
- "movl 16(%%eax),%%esi ;"
- "movl 20(%%eax),%%edi ;"
- "movl (%%eax),%%eax ;"
- TRAP_INSTR "; "
- "popl %%edi; popl %%esi; popl %%edx; popl %%ecx; popl %%ebx"
- : "=a" (ret) : "0" (&hypercall) : "memory" );
+ __asm__ __volatile__ (
+ "pushl %%ebx; pushl %%ecx; pushl %%edx; "
+ "pushl %%esi; pushl %%edi; "
+ "movl 4(%%eax),%%ebx ;"
+ "movl 8(%%eax),%%ecx ;"
+ "movl 12(%%eax),%%edx ;"
+ "movl 16(%%eax),%%esi ;"
+ "movl 20(%%eax),%%edi ;"
+ "movl (%%eax),%%eax ;"
+ TRAP_INSTR "; "
+ "popl %%edi; popl %%esi; popl %%edx; "
+ "popl %%ecx; popl %%ebx"
+ : "=a" (ret) : "0" (&hypercall) : "memory" );
#elif defined (__x86_64__)
- {
- long ign1, ign2, ign3;
- __asm__ __volatile__ (
- "movq %8,%%r10; movq %9,%%r8;" TRAP_INSTR
- : "=a" (ret), "=D" (ign1), "=S" (ign2), "=d" (ign3)
- : "0" ((unsigned long)hypercall.op),
- "1" ((unsigned long)hypercall.arg[0]),
- "2" ((unsigned long)hypercall.arg[1]),
- "3" ((unsigned long)hypercall.arg[2]),
- "g" ((unsigned long)hypercall.arg[3]),
- "g" ((unsigned long)hypercall.arg[4])
- : "r11","rcx","r8","r10","memory");
- }
+ {
+ long ign1, ign2, ign3;
+ __asm__ __volatile__ (
+ "movq %8,%%r10; movq %9,%%r8;" TRAP_INSTR
+ : "=a" (ret), "=D" (ign1),
+ "=S" (ign2), "=d" (ign3)
+ : "0" ((unsigned long)hypercall.op),
+ "1" ((unsigned long)hypercall.arg[0]),
+ "2" ((unsigned long)hypercall.arg[1]),
+ "3" ((unsigned long)hypercall.arg[2]),
+ "g" ((unsigned long)hypercall.arg[3]),
+ "g" ((unsigned long)hypercall.arg[4])
+ : "r11","rcx","r8","r10","memory");
+ }
#elif defined (__ia64__)
- __asm__ __volatile__ (
- ";; mov r14=%2; mov r15=%3; mov r16=%4; mov r17=%5; mov r18=%6;"
- "mov r2=%1; break 0x1000;; mov %0=r8 ;;"
- : "=r" (ret)
- : "r" (hypercall.op),
- "r" (hypercall.arg[0]),
- "r" (hypercall.arg[1]),
- "r" (hypercall.arg[2]),
- "r" (hypercall.arg[3]),
- "r" (hypercall.arg[4])
- : "r14","r15","r16","r17","r18","r2","r8","memory");
+ __asm__ __volatile__ (
+ ";; mov r14=%2; mov r15=%3; "
+ "mov r16=%4; mov r17=%5; mov r18=%6;"
+ "mov r2=%1; break 0x1000;; mov %0=r8 ;;"
+ : "=r" (ret)
+ : "r" (hypercall.op),
+ "r" (hypercall.arg[0]),
+ "r" (hypercall.arg[1]),
+ "r" (hypercall.arg[2]),
+ "r" (hypercall.arg[3]),
+ "r" (hypercall.arg[4])
+ : "r14","r15","r16","r17","r18","r2","r8","memory");
#endif
- }
- break;
+ }
+ break;
#if defined(CONFIG_XEN_PRIVILEGED_GUEST)
- case IOCTL_PRIVCMD_MMAP:
- {
+ case IOCTL_PRIVCMD_MMAP: {
#define PRIVCMD_MMAP_SZ 32
- privcmd_mmap_t mmapcmd;
- privcmd_mmap_entry_t msg[PRIVCMD_MMAP_SZ], *p;
- int i, rc;
-
- if ( copy_from_user(&mmapcmd, (void *)data, sizeof(mmapcmd)) )
- return -EFAULT;
-
- p = mmapcmd.entry;
-
- for (i=0; i<mmapcmd.num; i+=PRIVCMD_MMAP_SZ, p+=PRIVCMD_MMAP_SZ)
- {
- int j, n = ((mmapcmd.num-i)>PRIVCMD_MMAP_SZ)?
- PRIVCMD_MMAP_SZ:(mmapcmd.num-i);
-
-
- if ( copy_from_user(&msg, p, n*sizeof(privcmd_mmap_entry_t)) )
- return -EFAULT;
+ privcmd_mmap_t mmapcmd;
+ privcmd_mmap_entry_t msg[PRIVCMD_MMAP_SZ], *p;
+ int i, rc;
+
+ if (copy_from_user(&mmapcmd, (void *)data, sizeof(mmapcmd)))
+ return -EFAULT;
+
+ p = mmapcmd.entry;
+
+ for (i = 0; i < mmapcmd.num;
+ i += PRIVCMD_MMAP_SZ, p += PRIVCMD_MMAP_SZ) {
+ int j, n = ((mmapcmd.num-i)>PRIVCMD_MMAP_SZ)?
+ PRIVCMD_MMAP_SZ:(mmapcmd.num-i);
+
+ if (copy_from_user(&msg, p,
+ n*sizeof(privcmd_mmap_entry_t)))
+ return -EFAULT;
- for ( j = 0; j < n; j++ )
- {
- struct vm_area_struct *vma =
- find_vma( current->mm, msg[j].va );
-
- if ( !vma )
- return -EINVAL;
-
- if ( msg[j].va > PAGE_OFFSET )
- return -EINVAL;
-
- if ( (msg[j].va + (msg[j].npages<<PAGE_SHIFT)) > vma->vm_end )
- return -EINVAL;
-
- if ( (rc = direct_remap_pfn_range(vma,
- msg[j].va&PAGE_MASK,
- msg[j].mfn,
- msg[j].npages<<PAGE_SHIFT,
- vma->vm_page_prot,
- mmapcmd.dom)) < 0 )
- return rc;
- }
- }
- ret = 0;
- }
- break;
-
- case IOCTL_PRIVCMD_MMAPBATCH:
- {
- mmu_update_t u;
- privcmd_mmapbatch_t m;
- struct vm_area_struct *vma = NULL;
- unsigned long *p, addr;
- unsigned long mfn, ptep;
- int i;
-
- if ( copy_from_user(&m, (void *)data, sizeof(m)) )
- { ret = -EFAULT; goto batch_err; }
-
- vma = find_vma( current->mm, m.addr );
-
- if ( !vma )
- { ret = -EINVAL; goto batch_err; }
-
- if ( m.addr > PAGE_OFFSET )
- { ret = -EFAULT; goto batch_err; }
-
- if ( (m.addr + (m.num<<PAGE_SHIFT)) > vma->vm_end )
- { ret = -EFAULT; goto batch_err; }
-
- p = m.arr;
- addr = m.addr;
- for ( i = 0; i < m.num; i++, addr += PAGE_SIZE, p++ )
- {
- if ( get_user(mfn, p) )
- return -EFAULT;
-
- ret = create_lookup_pte_addr(vma->vm_mm, addr, &ptep);
- if (ret)
- goto batch_err;
-
- u.val = pte_val_ma(pfn_pte_ma(mfn, vma->vm_page_prot));
- u.ptr = ptep;
-
- if ( unlikely(HYPERVISOR_mmu_update(&u, 1, NULL, m.dom) < 0) )
- put_user(0xF0000000 | mfn, p);
- }
-
- ret = 0;
- break;
-
- batch_err:
- printk("batch_err ret=%d vma=%p addr=%lx num=%d arr=%p %lx-%lx\n",
- ret, vma, m.addr, m.num, m.arr,
- vma ? vma->vm_start : 0, vma ? vma->vm_end : 0);
- break;
- }
- break;
+ for (j = 0; j < n; j++) {
+ struct vm_area_struct *vma =
+ find_vma( current->mm, msg[j].va );
+
+ if (!vma)
+ return -EINVAL;
+
+ if (msg[j].va > PAGE_OFFSET)
+ return -EINVAL;
+
+ if ((msg[j].va + (msg[j].npages << PAGE_SHIFT))
+ > vma->vm_end )
+ return -EINVAL;
+
+ if ((rc = direct_remap_pfn_range(
+ vma,
+ msg[j].va&PAGE_MASK,
+ msg[j].mfn,
+ msg[j].npages<<PAGE_SHIFT,
+ vma->vm_page_prot,
+ mmapcmd.dom)) < 0)
+ return rc;
+ }
+ }
+ ret = 0;
+ }
+ break;
+
+ case IOCTL_PRIVCMD_MMAPBATCH: {
+ mmu_update_t u;
+ privcmd_mmapbatch_t m;
+ struct vm_area_struct *vma = NULL;
+ unsigned long *p, addr;
+ unsigned long mfn, ptep;
+ int i;
+
+ if (copy_from_user(&m, (void *)data, sizeof(m))) {
+ ret = -EFAULT;
+ goto batch_err;
+ }
+
+ vma = find_vma( current->mm, m.addr );
+ if (!vma) {
+ ret = -EINVAL;
+ goto batch_err;
+ }
+
+ if (m.addr > PAGE_OFFSET) {
+ ret = -EFAULT;
+ goto batch_err;
+ }
+
+ if ((m.addr + (m.num<<PAGE_SHIFT)) > vma->vm_end) {
+ ret = -EFAULT;
+ goto batch_err;
+ }
+
+ p = m.arr;
+ addr = m.addr;
+ for (i = 0; i < m.num; i++, addr += PAGE_SIZE, p++) {
+ if (get_user(mfn, p))
+ return -EFAULT;
+
+ ret = create_lookup_pte_addr(vma->vm_mm, addr, &ptep);
+ if (ret)
+ goto batch_err;
+
+ u.val = pte_val_ma(pfn_pte_ma(mfn, vma->vm_page_prot));
+ u.ptr = ptep;
+
+ if (HYPERVISOR_mmu_update(&u, 1, NULL, m.dom) < 0)
+ put_user(0xF0000000 | mfn, p);
+ }
+
+ ret = 0;
+ break;
+
+ batch_err:
+ printk("batch_err ret=%d vma=%p addr=%lx "
+ "num=%d arr=%p %lx-%lx\n",
+ ret, vma, m.addr, m.num, m.arr,
+ vma ? vma->vm_start : 0, vma ? vma->vm_end : 0);
+ break;
+ }
+ break;
#endif
- case IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN:
- {
- unsigned long m2pv = (unsigned long)machine_to_phys_mapping;
- pgd_t *pgd = pgd_offset_k(m2pv);
- pud_t *pud = pud_offset(pgd, m2pv);
- pmd_t *pmd = pmd_offset(pud, m2pv);
- unsigned long m2p_start_mfn = (*(unsigned long *)pmd) >> PAGE_SHIFT;
- ret = put_user(m2p_start_mfn, (unsigned long *)data) ? -EFAULT: 0;
- }
- break;
-
- case IOCTL_PRIVCMD_INITDOMAIN_STORE:
- {
- extern int do_xenbus_probe(void*);
- unsigned long page;
-
- if (xen_start_info->store_evtchn != 0) {
- ret = xen_start_info->store_mfn;
- break;
- }
-
- /* Allocate page. */
- page = get_zeroed_page(GFP_KERNEL);
- if (!page) {
- ret = -ENOMEM;
- break;
- }
-
- /* We don't refcnt properly, so set reserved on page.
- * (this allocation is permanent) */
- SetPageReserved(virt_to_page(page));
-
- /* Initial connect. Setup channel and page. */
- xen_start_info->store_evtchn = data;
- xen_start_info->store_mfn = pfn_to_mfn(virt_to_phys((void *)page) >>
- PAGE_SHIFT);
- ret = xen_start_info->store_mfn;
-
- /* We'll return then this will wait for daemon to answer */
- kthread_run(do_xenbus_probe, NULL, "xenbus_probe");
- }
- break;
-
- default:
- ret = -EINVAL;
- break;
- }
- return ret;
+ case IOCTL_PRIVCMD_GET_MACH2PHYS_START_MFN: {
+ unsigned long m2pv = (unsigned long)machine_to_phys_mapping;
+ pgd_t *pgd = pgd_offset_k(m2pv);
+ pud_t *pud = pud_offset(pgd, m2pv);
+ pmd_t *pmd = pmd_offset(pud, m2pv);
+ unsigned long m2p_start_mfn =
+ (*(unsigned long *)pmd) >> PAGE_SHIFT;
+ ret = put_user(m2p_start_mfn, (unsigned long *)data) ?
+ -EFAULT: 0;
+ }
+ break;
+
+ case IOCTL_PRIVCMD_INITDOMAIN_STORE: {
+ extern int do_xenbus_probe(void*);
+ unsigned long page;
+
+ if (xen_start_info->store_evtchn != 0) {
+ ret = xen_start_info->store_mfn;
+ break;
+ }
+
+ /* Allocate page. */
+ page = get_zeroed_page(GFP_KERNEL);
+ if (!page) {
+ ret = -ENOMEM;
+ break;
+ }
+
+ /* We don't refcnt properly, so set reserved on page.
+ * (this allocation is permanent) */
+ SetPageReserved(virt_to_page(page));
+
+ /* Initial connect. Setup channel and page. */
+ xen_start_info->store_evtchn = data;
+ xen_start_info->store_mfn =
+ pfn_to_mfn(virt_to_phys((void *)page) >>
+ PAGE_SHIFT);
+ ret = xen_start_info->store_mfn;
+
+ /* We'll return then this will wait for daemon to answer */
+ kthread_run(do_xenbus_probe, NULL, "xenbus_probe");
+ }
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
}
static int privcmd_mmap(struct file * file, struct vm_area_struct * vma)
{
- /* DONTCOPY is essential for Xen as copy_page_range is broken. */
- vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY;
-
- return 0;
+ /* DONTCOPY is essential for Xen as copy_page_range is broken. */
+ vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTCOPY;
+
+ return 0;
}
static struct file_operations privcmd_file_ops = {
- .ioctl = privcmd_ioctl,
- .mmap = privcmd_mmap,
+ .ioctl = privcmd_ioctl,
+ .mmap = privcmd_mmap,
};
static int __init privcmd_init(void)
{
- privcmd_intf = create_xen_proc_entry("privcmd", 0400);
- if ( privcmd_intf != NULL )
- privcmd_intf->proc_fops = &privcmd_file_ops;
-
- return 0;
+ privcmd_intf = create_xen_proc_entry("privcmd", 0400);
+ if (privcmd_intf != NULL)
+ privcmd_intf->proc_fops = &privcmd_file_ops;
+
+ return 0;
}
__initcall(privcmd_init);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/tpmback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/common.h Thu Sep 22 15:12:14 2005
@@ -84,3 +84,13 @@
#define MMAP_VADDR(t,_req) ((t)->mmap_vstart + ((_req) * PAGE_SIZE))
#endif /* __TPMIF__BACKEND__COMMON_H__ */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Thu Sep 22
15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/tpmback.c Thu Sep 22
15:12:14 2005
@@ -566,7 +566,7 @@
* the more time we give the TPM to process the
request.
*/
mod_timer(&pak->processing_timer,
- jiffies + (num_frontends * 10 * HZ));
+ jiffies + (num_frontends * 60 * HZ));
dataex.copied_so_far = 0;
}
}
@@ -850,7 +850,7 @@
write_lock_irqsave(&dataex.pak_lock, flags);
list_add_tail(&pak->next, &dataex.pending_pak);
/* give the TPM some time to pick up the request */
- mod_timer(&pak->processing_timer, jiffies + (10 * HZ));
+ mod_timer(&pak->processing_timer, jiffies + (30 * HZ));
write_unlock_irqrestore(&dataex.pak_lock,
flags);
@@ -1075,3 +1075,13 @@
}
__initcall(tpmback_init);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Thu Sep 22 15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmback/xenbus.c Thu Sep 22 15:12:14 2005
@@ -268,3 +268,13 @@
{
xenbus_register_backend(&tpmback);
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Thu Sep 22
15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.c Thu Sep 22
15:12:14 2005
@@ -741,3 +741,13 @@
}
__initcall(tpmif_init);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h
--- a/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h Thu Sep 22
15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/tpmfront/tpmfront.h Thu Sep 22
15:12:14 2005
@@ -38,3 +38,13 @@
};
#endif
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Thu Sep 22
15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.c Thu Sep 22
15:12:14 2005
@@ -231,3 +231,13 @@
unbind_evtchn_from_irqhandler(xen_start_info->store_evtchn, &xb_waitq);
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h Thu Sep 22
15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_comms.h Thu Sep 22
15:12:14 2005
@@ -39,3 +39,13 @@
extern wait_queue_head_t xb_waitq;
#endif /* _XENBUS_COMMS_H */
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Thu Sep 22
15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_dev.c Thu Sep 22
15:12:14 2005
@@ -186,3 +186,13 @@
}
__initcall(xenbus_dev_init);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Thu Sep 22
15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Thu Sep 22
15:12:14 2005
@@ -687,3 +687,13 @@
}
postcore_initcall(xenbus_probe_init);
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Thu Sep 22
15:05:44 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Thu Sep 22
15:12:14 2005
@@ -566,3 +566,13 @@
return PTR_ERR(watcher);
return 0;
}
+
+/*
+ * Local variables:
+ * c-file-style: "linux"
+ * indent-tabs-mode: t
+ * c-indent-level: 8
+ * c-basic-offset: 8
+ * tab-width: 8
+ * End:
+ */
diff -r eba5afe9aa37 -r 10759a44ce3b tools/python/xen/xend/XendDomain.py
--- a/tools/python/xen/xend/XendDomain.py Thu Sep 22 15:05:44 2005
+++ b/tools/python/xen/xend/XendDomain.py Thu Sep 22 15:12:14 2005
@@ -305,6 +305,13 @@
@param vmconfig: vm configuration
"""
+ # We accept our configuration specified as ['config' [...]], which
+ # some tools or configuration files may be using. For save-restore,
+ # we use the value of XendDomainInfo.sxpr() directly, which has no
+ # such item.
+ nested = sxp.child_value(config, 'config')
+ if nested:
+ config = nested
return XendDomainInfo.restore(self.dbmap.getPath(), config)
def domain_restore(self, src, progress=False):
diff -r eba5afe9aa37 -r 10759a44ce3b xen/include/public/io/netif.h
--- a/xen/include/public/io/netif.h Thu Sep 22 15:05:44 2005
+++ b/xen/include/public/io/netif.h Thu Sep 22 15:12:14 2005
@@ -10,10 +10,11 @@
#define __XEN_PUBLIC_IO_NETIF_H__
typedef struct netif_tx_request {
- unsigned long addr; /* Machine address of packet. */
+ grant_ref_t gref; /* Reference to buffer page */
+ u16 offset:15; /* Offset within buffer page */
u16 csum_blank:1; /* Proto csum field blank? */
- u16 id:15; /* Echoed in response message. */
- u16 size; /* Packet size in bytes. */
+ u16 id; /* Echoed in response message. */
+ u16 size; /* Packet size in bytes. */
} netif_tx_request_t;
typedef struct netif_tx_response {
@@ -22,21 +23,15 @@
} netif_tx_response_t;
typedef struct {
- u16 id; /* Echoed in response message. */
-#ifdef CONFIG_XEN_NETDEV_GRANT
- grant_ref_t gref; /* 2: Reference to incoming granted frame */
-#endif
+ u16 id; /* Echoed in response message. */
+ grant_ref_t gref; /* Reference to incoming granted frame */
} netif_rx_request_t;
typedef struct {
-#ifdef CONFIG_XEN_NETDEV_GRANT
- u32 addr; /* 0: Offset in page of start of received packet */
-#else
- unsigned long addr; /* Machine address of packet. */
-#endif
- u16 csum_valid:1; /* Protocol checksum is validated? */
- u16 id:15;
- s16 status; /* -ve: BLKIF_RSP_* ; +ve: Rx'ed pkt size. */
+ u16 offset; /* Offset in page of start of received packet */
+ u16 csum_valid; /* Protocol checksum is validated? */
+ u16 id;
+ s16 status; /* -ve: BLKIF_RSP_* ; +ve: Rx'ed pkt size. */
} netif_rx_response_t;
/*
@@ -53,18 +48,8 @@
#define MASK_NETIF_RX_IDX(_i) ((_i)&(NETIF_RX_RING_SIZE-1))
#define MASK_NETIF_TX_IDX(_i) ((_i)&(NETIF_TX_RING_SIZE-1))
-#ifdef __x86_64__
-/*
- * This restriction can be lifted when we move netfront/netback to use
- * grant tables. This will remove memory_t fields from the above structures
- * and thus relax natural alignment restrictions.
- */
-#define NETIF_TX_RING_SIZE 128
-#define NETIF_RX_RING_SIZE 128
-#else
#define NETIF_TX_RING_SIZE 256
#define NETIF_RX_RING_SIZE 256
-#endif
/* This structure must fit in a memory page. */
typedef struct netif_tx_interface {
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/usbback/common.h
--- a/linux-2.6-xen-sparse/drivers/xen/usbback/common.h Thu Sep 22 15:05:44 2005
+++ /dev/null Thu Sep 22 15:12:14 2005
@@ -1,84 +0,0 @@
-
-#ifndef __USBIF__BACKEND__COMMON_H__
-#define __USBIF__BACKEND__COMMON_H__
-
-#include <linux/config.h>
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/rbtree.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/blkdev.h>
-#include <asm/io.h>
-#include <asm/setup.h>
-#include <asm/pgalloc.h>
-#include <asm/hypervisor.h>
-#include <asm-xen/driver_util.h>
-#include <asm-xen/xen-public/io/usbif.h>
-
-#if 0
-#define ASSERT(_p) \
- if ( !(_p) ) { printk("Assertion '%s' failed, line %d, file %s", #_p , \
- __LINE__, __FILE__); *(int*)0=0; }
-#define DPRINTK(_f, _a...) printk(KERN_ALERT "(file=%s, line=%d) " _f, \
- __FILE__ , __LINE__ , ## _a )
-#else
-#define ASSERT(_p) ((void)0)
-#define DPRINTK(_f, _a...) ((void)0)
-#endif
-
-typedef struct usbif_priv_st usbif_priv_t;
-
-struct usbif_priv_st {
- /* Unique identifier for this interface. */
- domid_t domid;
- unsigned int handle;
- /* Physical parameters of the comms window. */
- unsigned long shmem_frame;
- unsigned int evtchn;
- /* Comms Information */
- usbif_back_ring_t usb_ring;
- struct vm_struct *usb_ring_area;
- /* Private fields. */
- enum { DISCONNECTED, DISCONNECTING, CONNECTED } status;
- /*
- * DISCONNECT response is deferred until pending requests are ack'ed.
- * We therefore need to store the id from the original request.
- */
- u8 disconnect_rspid;
- usbif_priv_t *hash_next;
- struct list_head usbif_list;
- spinlock_t usb_ring_lock;
- atomic_t refcnt;
-
- struct work_struct work;
-};
-
-void usbif_create(usbif_be_create_t *create);
-void usbif_destroy(usbif_be_destroy_t *destroy);
-void usbif_connect(usbif_be_connect_t *connect);
-int usbif_disconnect(usbif_be_disconnect_t *disconnect, u8 rsp_id);
-void usbif_disconnect_complete(usbif_priv_t *up);
-
-void usbif_release_port(usbif_be_release_port_t *msg);
-int usbif_claim_port(usbif_be_claim_port_t *msg);
-void usbif_release_ports(usbif_priv_t *up);
-
-usbif_priv_t *usbif_find(domid_t domid);
-#define usbif_get(_b) (atomic_inc(&(_b)->refcnt))
-#define usbif_put(_b) \
- do { \
- if ( atomic_dec_and_test(&(_b)->refcnt) ) \
- usbif_disconnect_complete(_b); \
- } while (0)
-
-
-void usbif_interface_init(void);
-void usbif_ctrlif_init(void);
-
-void usbif_deschedule(usbif_priv_t *up);
-void remove_from_usbif_list(usbif_priv_t *up);
-
-irqreturn_t usbif_be_int(int irq, void *dev_id, struct pt_regs *regs);
-
-#endif /* __USBIF__BACKEND__COMMON_H__ */
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/usbback/control.c
--- a/linux-2.6-xen-sparse/drivers/xen/usbback/control.c Thu Sep 22
15:05:44 2005
+++ /dev/null Thu Sep 22 15:12:14 2005
@@ -1,61 +0,0 @@
-/******************************************************************************
- * arch/xen/drivers/usbif/backend/control.c
- *
- * Routines for interfacing with the control plane.
- *
- * Copyright (c) 2004, Keir Fraser
- */
-
-#include "common.h"
-
-static void usbif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
-{
- DPRINTK("Received usbif backend message, subtype=%d\n", msg->subtype);
-
- switch ( msg->subtype )
- {
- case CMSG_USBIF_BE_CREATE:
- usbif_create((usbif_be_create_t *)&msg->msg[0]);
- break;
- case CMSG_USBIF_BE_DESTROY:
- usbif_destroy((usbif_be_destroy_t *)&msg->msg[0]);
- break;
- case CMSG_USBIF_BE_CONNECT:
- usbif_connect((usbif_be_connect_t *)&msg->msg[0]);
- break;
- case CMSG_USBIF_BE_DISCONNECT:
- if ( !usbif_disconnect((usbif_be_disconnect_t *)&msg->msg[0],msg->id) )
- return; /* Sending the response is deferred until later. */
- break;
- case CMSG_USBIF_BE_CLAIM_PORT:
- usbif_claim_port((usbif_be_claim_port_t *)&msg->msg[0]);
- break;
- case CMSG_USBIF_BE_RELEASE_PORT:
- usbif_release_port((usbif_be_release_port_t *)&msg->msg[0]);
- break;
- default:
- DPRINTK("Parse error while reading message subtype %d, len %d\n",
- msg->subtype, msg->length);
- msg->length = 0;
- break;
- }
-
- ctrl_if_send_response(msg);
-}
-
-void usbif_ctrlif_init(void)
-{
- ctrl_msg_t cmsg;
- usbif_be_driver_status_changed_t st;
-
- (void)ctrl_if_register_receiver(CMSG_USBIF_BE, usbif_ctrlif_rx,
- CALLBACK_IN_BLOCKING_CONTEXT);
-
- /* Send a driver-UP notification to the domain controller. */
- cmsg.type = CMSG_USBIF_BE;
- cmsg.subtype = CMSG_USBIF_BE_DRIVER_STATUS_CHANGED;
- cmsg.length = sizeof(usbif_be_driver_status_changed_t);
- st.status = USBIF_DRIVER_STATUS_UP;
- memcpy(cmsg.msg, &st, sizeof(st));
- ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-}
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/usbback/interface.c
--- a/linux-2.6-xen-sparse/drivers/xen/usbback/interface.c Thu Sep 22
15:05:44 2005
+++ /dev/null Thu Sep 22 15:12:14 2005
@@ -1,241 +0,0 @@
-/******************************************************************************
- * arch/xen/drivers/usbif/backend/interface.c
- *
- * USB device interface management.
- *
- * by Mark Williamson, Copyright (c) 2004
- */
-
-#include "common.h"
-
-#define USBIF_HASHSZ 1024
-#define USBIF_HASH(_d) (((int)(_d))&(USBIF_HASHSZ-1))
-
-static kmem_cache_t *usbif_priv_cachep;
-static usbif_priv_t *usbif_priv_hash[USBIF_HASHSZ];
-
-usbif_priv_t *usbif_find(domid_t domid)
-{
- usbif_priv_t *up = usbif_priv_hash[USBIF_HASH(domid)];
- while ( (up != NULL ) && ( up->domid != domid ) )
- up = up->hash_next;
- return up;
-}
-
-static void __usbif_disconnect_complete(void *arg)
-{
- usbif_priv_t *usbif = (usbif_priv_t *)arg;
- ctrl_msg_t cmsg;
- usbif_be_disconnect_t disc;
-
- /*
- * These can't be done in usbif_disconnect() because at that point there
- * may be outstanding requests at the device whose asynchronous responses
- * must still be notified to the remote driver.
- */
- free_vm_area(usbif->usb_ring_area);
-
- /* Construct the deferred response message. */
- cmsg.type = CMSG_USBIF_BE;
- cmsg.subtype = CMSG_USBIF_BE_DISCONNECT;
- cmsg.id = usbif->disconnect_rspid;
- cmsg.length = sizeof(usbif_be_disconnect_t);
- disc.domid = usbif->domid;
- disc.status = USBIF_BE_STATUS_OKAY;
- memcpy(cmsg.msg, &disc, sizeof(disc));
-
- /*
- * Make sure message is constructed /before/ status change, because
- * after the status change the 'usbif' structure could be deallocated at
- * any time. Also make sure we send the response /after/ status change,
- * as otherwise a subsequent CONNECT request could spuriously fail if
- * another CPU doesn't see the status change yet.
- */
- mb();
- if ( usbif->status != DISCONNECTING )
- BUG();
- usbif->status = DISCONNECTED;
- mb();
-
- /* Send the successful response. */
- ctrl_if_send_response(&cmsg);
-}
-
-void usbif_disconnect_complete(usbif_priv_t *up)
-{
- INIT_WORK(&up->work, __usbif_disconnect_complete, (void *)up);
- schedule_work(&up->work);
-}
-
-void usbif_create(usbif_be_create_t *create)
-{
- domid_t domid = create->domid;
- usbif_priv_t **pup, *up;
-
- if ( (up = kmem_cache_alloc(usbif_priv_cachep, GFP_KERNEL)) == NULL )
- {
- DPRINTK("Could not create usbif: out of memory\n");
- create->status = USBIF_BE_STATUS_OUT_OF_MEMORY;
- return;
- }
-
- memset(up, 0, sizeof(*up));
- up->domid = domid;
- up->status = DISCONNECTED;
- spin_lock_init(&up->usb_ring_lock);
- atomic_set(&up->refcnt, 0);
-
- pup = &usbif_priv_hash[USBIF_HASH(domid)];
- while ( *pup != NULL )
- {
- if ( (*pup)->domid == domid )
- {
- create->status = USBIF_BE_STATUS_INTERFACE_EXISTS;
- kmem_cache_free(usbif_priv_cachep, up);
- return;
- }
- pup = &(*pup)->hash_next;
- }
-
- up->hash_next = *pup;
- *pup = up;
-
- create->status = USBIF_BE_STATUS_OKAY;
-}
-
-void usbif_destroy(usbif_be_destroy_t *destroy)
-{
- domid_t domid = destroy->domid;
- usbif_priv_t **pup, *up;
-
- pup = &usbif_priv_hash[USBIF_HASH(domid)];
- while ( (up = *pup) != NULL )
- {
- if ( up->domid == domid )
- {
- if ( up->status != DISCONNECTED )
- goto still_connected;
- goto destroy;
- }
- pup = &up->hash_next;
- }
-
- destroy->status = USBIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return;
-
- still_connected:
- destroy->status = USBIF_BE_STATUS_INTERFACE_CONNECTED;
- return;
-
- destroy:
- *pup = up->hash_next;
- usbif_release_ports(up);
- kmem_cache_free(usbif_priv_cachep, up);
- destroy->status = USBIF_BE_STATUS_OKAY;
-}
-
-void usbif_connect(usbif_be_connect_t *connect)
-{
- domid_t domid = connect->domid;
- unsigned int evtchn = connect->evtchn;
- unsigned long shmem_frame = connect->shmem_frame;
- pgprot_t prot;
- int error;
- usbif_priv_t *up;
- usbif_sring_t *sring;
-
- up = usbif_find(domid);
- if ( unlikely(up == NULL) )
- {
- DPRINTK("usbif_connect attempted for non-existent usbif (%u)\n",
- connect->domid);
- connect->status = USBIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return;
- }
-
- if ( (up->usb_ring_area = alloc_vm_area(PAGE_SIZE)) == NULL )
- {
- connect->status = USBIF_BE_STATUS_OUT_OF_MEMORY;
- return;
- }
-
- prot = __pgprot(_KERNPG_TABLE);
- error = direct_remap_pfn_range(&init_mm, AREALLOC_AREADDR(area->addr),
- shmem_frame, PAGE_SIZE,
- prot, domid);
- if ( error != 0 )
- {
- if ( error == -ENOMEM )
- connect->status = USBIF_BE_STATUS_OUT_OF_MEMORY;
- else if ( error == -EFAULT )
- connect->status = USBIF_BE_STATUS_MAPPING_ERROR;
- else
- connect->status = USBIF_BE_STATUS_ERROR;
- free_vm_area(up->usb_ring_area);
- return;
- }
-
- if ( up->status != DISCONNECTED )
- {
- connect->status = USBIF_BE_STATUS_INTERFACE_CONNECTED;
- free_vm_area(up->usb_ring_area);
- return;
- }
-
- sring = (usbif_sring_t *)area->addr;
- SHARED_RING_INIT(sring);
- BACK_RING_INIT(&up->usb_ring, sring, PAGE_SIZE);
-
- up->evtchn = evtchn;
- up->shmem_frame = shmem_frame;
- up->status = CONNECTED;
- usbif_get(up);
-
- (void)bind_evtchn_to_irqhandler(
- evtchn, usbif_be_int, 0, "usbif-backend", up);
-
- connect->status = USBIF_BE_STATUS_OKAY;
-}
-
-/* Remove URBs for this interface before destroying it. */
-void usbif_deschedule(usbif_priv_t *up)
-{
- remove_from_usbif_list(up);
-}
-
-int usbif_disconnect(usbif_be_disconnect_t *disconnect, u8 rsp_id)
-{
- domid_t domid = disconnect->domid;
- usbif_priv_t *up;
-
- up = usbif_find(domid);
- if ( unlikely(up == NULL) )
- {
- DPRINTK("usbif_disconnect attempted for non-existent usbif"
- " (%u)\n", disconnect->domid);
- disconnect->status = USBIF_BE_STATUS_INTERFACE_NOT_FOUND;
- return 1; /* Caller will send response error message. */
- }
-
- if ( up->status == CONNECTED )
- {
- up->status = DISCONNECTING;
- up->disconnect_rspid = rsp_id;
- wmb(); /* Let other CPUs see the status change. */
- unbind_evtchn_from_irqhandler(up->evtchn, up);
- usbif_deschedule(up);
- usbif_put(up);
- return 0; /* Caller should not send response message. */
- }
-
- disconnect->status = USBIF_BE_STATUS_OKAY;
- return 1;
-}
-
-void __init usbif_interface_init(void)
-{
- usbif_priv_cachep = kmem_cache_create("usbif_priv_cache",
- sizeof(usbif_priv_t),
- 0, 0, NULL, NULL);
- memset(usbif_priv_hash, 0, sizeof(usbif_priv_hash));
-}
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c
--- a/linux-2.6-xen-sparse/drivers/xen/usbback/usbback.c Thu Sep 22
15:05:44 2005
+++ /dev/null Thu Sep 22 15:12:14 2005
@@ -1,1068 +0,0 @@
-/******************************************************************************
- * arch/xen/drivers/usbif/backend/main.c
- *
- * Backend for the Xen virtual USB driver - provides an abstraction of a
- * USB host controller to the corresponding frontend driver.
- *
- * by Mark Williamson
- * Copyright (c) 2004 Intel Research Cambridge
- * Copyright (c) 2004, 2005 Mark Williamson
- *
- * Based on arch/xen/drivers/blkif/backend/main.c
- * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
- */
-
-#include "common.h"
-
-
-#include <linux/list.h>
-#include <linux/usb.h>
-#include <linux/spinlock.h>
-#include <linux/module.h>
-#include <linux/tqueue.h>
-
-/*
- * This is rather arbitrary.
- */
-#define MAX_PENDING_REQS 4
-#define BATCH_PER_DOMAIN 1
-
-static unsigned long mmap_vstart;
-
-/* Needs to be sufficiently large that we can map the (large) buffers
- * the USB mass storage driver wants. */
-#define MMAP_PAGES_PER_REQUEST \
- (128)
-#define MMAP_PAGES \
- (MAX_PENDING_REQS * MMAP_PAGES_PER_REQUEST)
-
-#define MMAP_VADDR(_req,_seg) \
- (mmap_vstart + \
- ((_req) * MMAP_PAGES_PER_REQUEST * PAGE_SIZE) + \
- ((_seg) * PAGE_SIZE))
-
-
-static spinlock_t owned_ports_lock;
-LIST_HEAD(owned_ports);
-
-/* A list of these structures is used to track ownership of physical USB
- * ports. */
-typedef struct
-{
- usbif_priv_t *usbif_priv;
- char path[16];
- int guest_port;
- int enabled;
- struct list_head list;
- unsigned long guest_address; /* The USB device address that has been
- * assigned by the guest. */
- int dev_present; /* Is there a device present? */
- struct usb_device * dev;
- unsigned long ifaces; /* What interfaces are present on this device? */
-} owned_port_t;
-
-
-/*
- * Each outstanding request that we've passed to the lower device layers has a
- * 'pending_req' allocated to it. The request is complete, the specified
- * domain has a response queued for it, with the saved 'id' passed back.
- */
-typedef struct {
- usbif_priv_t *usbif_priv;
- unsigned long id;
- int nr_pages;
- unsigned short operation;
- int status;
-} pending_req_t;
-
-/*
- * We can't allocate pending_req's in order, since they may complete out of
- * order. We therefore maintain an allocation ring. This ring also indicates
- * when enough work has been passed down -- at that point the allocation ring
- * will be empty.
- */
-static pending_req_t pending_reqs[MAX_PENDING_REQS];
-static unsigned char pending_ring[MAX_PENDING_REQS];
-static spinlock_t pend_prod_lock;
-
-/* NB. We use a different index type to differentiate from shared usb rings. */
-typedef unsigned int PEND_RING_IDX;
-#define MASK_PEND_IDX(_i) ((_i)&(MAX_PENDING_REQS-1))
-static PEND_RING_IDX pending_prod, pending_cons;
-#define NR_PENDING_REQS (MAX_PENDING_REQS - pending_prod + pending_cons)
-
-static int do_usb_io_op(usbif_priv_t *usbif, int max_to_do);
-static void make_response(usbif_priv_t *usbif, unsigned long id,
- unsigned short op, int st, int inband,
- unsigned long actual_length);
-static void dispatch_usb_probe(usbif_priv_t *up, unsigned long id, unsigned
long port);
-static void dispatch_usb_io(usbif_priv_t *up, usbif_request_t *req);
-static void dispatch_usb_reset(usbif_priv_t *up, unsigned long portid);
-static owned_port_t *usbif_find_port(char *);
-
-/******************************************************************
- * PRIVATE DEBUG FUNCTIONS
- */
-
-#undef DEBUG
-#ifdef DEBUG
-
-static void dump_port(owned_port_t *p)
-{
- printk(KERN_DEBUG "owned_port_t @ %p\n"
- " usbif_priv @ %p\n"
- " path: %s\n"
- " guest_port: %d\n"
- " guest_address: %ld\n"
- " dev_present: %d\n"
- " dev @ %p\n"
- " ifaces: 0x%lx\n",
- p, p->usbif_priv, p->path, p->guest_port, p->guest_address,
- p->dev_present, p->dev, p->ifaces);
-}
-
-
-static void dump_request(usbif_request_t *req)
-{
- printk(KERN_DEBUG "id = 0x%lx\n"
- "devnum %d\n"
- "endpoint 0x%x\n"
- "direction %d\n"
- "speed %d\n"
- "pipe_type 0x%x\n"
- "transfer_buffer 0x%lx\n"
- "length 0x%lx\n"
- "transfer_flags 0x%lx\n"
- "setup = { 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x }\n"
- "iso_schedule = 0x%lx\n"
- "num_iso %ld\n",
- req->id, req->devnum, req->endpoint, req->direction, req->speed,
- req->pipe_type, req->transfer_buffer, req->length,
- req->transfer_flags, req->setup[0], req->setup[1], req->setup[2],
- req->setup[3], req->setup[4], req->setup[5], req->setup[6],
- req->setup[7], req->iso_schedule, req->num_iso);
-}
-
-static void dump_urb(struct urb *urb)
-{
- printk(KERN_DEBUG "dumping urb @ %p\n", urb);
-
-#define DUMP_URB_FIELD(name, format) \
- printk(KERN_DEBUG " " # name " " format "\n", urb-> name)
-
- DUMP_URB_FIELD(pipe, "0x%x");
- DUMP_URB_FIELD(status, "%d");
- DUMP_URB_FIELD(transfer_flags, "0x%x");
- DUMP_URB_FIELD(transfer_buffer, "%p");
- DUMP_URB_FIELD(transfer_buffer_length, "%d");
- DUMP_URB_FIELD(actual_length, "%d");
-}
-
-static void dump_response(usbif_response_t *resp)
-{
- printk(KERN_DEBUG "usbback: Sending response:\n"
- " id = 0x%x\n"
- " op = %d\n"
- " status = %d\n"
- " data = %d\n"
- " length = %d\n",
- resp->id, resp->op, resp->status, resp->data, resp->length);
-}
-
-#else /* DEBUG */
-
-#define dump_port(blah) ((void)0)
-#define dump_request(blah) ((void)0)
-#define dump_urb(blah) ((void)0)
-#define dump_response(blah) ((void)0)
-
-#endif /* DEBUG */
-
-/******************************************************************
- * MEMORY MANAGEMENT
- */
-
-static void fast_flush_area(int idx, int nr_pages)
-{
- multicall_entry_t mcl[MMAP_PAGES_PER_REQUEST];
- int i;
-
- for ( i = 0; i < nr_pages; i++ )
- {
- MULTI_update_va_mapping(mcl+i, MMAP_VADDR(idx, i),
- __pte(0), 0);
- }
-
- mcl[nr_pages-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
- if ( unlikely(HYPERVISOR_multicall(mcl, nr_pages) != 0) )
- BUG();
-}
-
-
-/******************************************************************
- * USB INTERFACE SCHEDULER LIST MAINTENANCE
- */
-
-static struct list_head usbio_schedule_list;
-static spinlock_t usbio_schedule_list_lock;
-
-static int __on_usbif_list(usbif_priv_t *up)
-{
- return up->usbif_list.next != NULL;
-}
-
-void remove_from_usbif_list(usbif_priv_t *up)
-{
- unsigned long flags;
- if ( !__on_usbif_list(up) ) return;
- spin_lock_irqsave(&usbio_schedule_list_lock, flags);
- if ( __on_usbif_list(up) )
- {
- list_del(&up->usbif_list);
- up->usbif_list.next = NULL;
- usbif_put(up);
- }
- spin_unlock_irqrestore(&usbio_schedule_list_lock, flags);
-}
-
-static void add_to_usbif_list_tail(usbif_priv_t *up)
-{
- unsigned long flags;
- if ( __on_usbif_list(up) ) return;
- spin_lock_irqsave(&usbio_schedule_list_lock, flags);
- if ( !__on_usbif_list(up) && (up->status == CONNECTED) )
- {
- list_add_tail(&up->usbif_list, &usbio_schedule_list);
- usbif_get(up);
- }
- spin_unlock_irqrestore(&usbio_schedule_list_lock, flags);
-}
-
-void free_pending(int pending_idx)
-{
- unsigned long flags;
-
- /* Free the pending request. */
- spin_lock_irqsave(&pend_prod_lock, flags);
- pending_ring[MASK_PEND_IDX(pending_prod++)] = pending_idx;
- spin_unlock_irqrestore(&pend_prod_lock, flags);
-}
-
-/******************************************************************
- * COMPLETION CALLBACK -- Called as urb->complete()
- */
-
-static void maybe_trigger_usbio_schedule(void);
-
-static void __end_usb_io_op(struct urb *purb)
-{
- pending_req_t *pending_req;
- int pending_idx;
-
- pending_req = purb->context;
-
- pending_idx = pending_req - pending_reqs;
-
- ASSERT(purb->actual_length <= purb->transfer_buffer_length);
- ASSERT(purb->actual_length <= pending_req->nr_pages * PAGE_SIZE);
-
- /* An error fails the entire request. */
- if ( purb->status )
- {
- printk(KERN_WARNING "URB @ %p failed. Status %d\n", purb,
purb->status);
- }
-
- if ( usb_pipetype(purb->pipe) == 0 )
- {
- int i;
- usbif_iso_t *sched = (usbif_iso_t *)MMAP_VADDR(pending_idx,
pending_req->nr_pages - 1);
-
- /* If we're dealing with an iso pipe, we need to copy back the
schedule. */
- for ( i = 0; i < purb->number_of_packets; i++ )
- {
- sched[i].length = purb->iso_frame_desc[i].actual_length;
- ASSERT(sched[i].buffer_offset ==
- purb->iso_frame_desc[i].offset);
- sched[i].status = purb->iso_frame_desc[i].status;
- }
- }
-
- fast_flush_area(pending_req - pending_reqs, pending_req->nr_pages);
-
- kfree(purb->setup_packet);
-
- make_response(pending_req->usbif_priv, pending_req->id,
- pending_req->operation, pending_req->status, 0,
purb->actual_length);
- usbif_put(pending_req->usbif_priv);
-
- usb_free_urb(purb);
-
- free_pending(pending_idx);
-
- rmb();
-
- /* Check for anything still waiting in the rings, having freed a
request... */
- maybe_trigger_usbio_schedule();
-}
-
-/******************************************************************
- * SCHEDULER FUNCTIONS
- */
-
-static DECLARE_WAIT_QUEUE_HEAD(usbio_schedule_wait);
-
-static int usbio_schedule(void *arg)
-{
- DECLARE_WAITQUEUE(wq, current);
-
- usbif_priv_t *up;
- struct list_head *ent;
-
- daemonize();
-
- for ( ; ; )
- {
- /* Wait for work to do. */
- add_wait_queue(&usbio_schedule_wait, &wq);
- set_current_state(TASK_INTERRUPTIBLE);
- if ( (NR_PENDING_REQS == MAX_PENDING_REQS) ||
- list_empty(&usbio_schedule_list) )
- schedule();
- __set_current_state(TASK_RUNNING);
- remove_wait_queue(&usbio_schedule_wait, &wq);
-
- /* Queue up a batch of requests. */
- while ( (NR_PENDING_REQS < MAX_PENDING_REQS) &&
- !list_empty(&usbio_schedule_list) )
- {
- ent = usbio_schedule_list.next;
- up = list_entry(ent, usbif_priv_t, usbif_list);
- usbif_get(up);
- remove_from_usbif_list(up);
- if ( do_usb_io_op(up, BATCH_PER_DOMAIN) )
- add_to_usbif_list_tail(up);
- usbif_put(up);
- }
- }
-}
-
-static void maybe_trigger_usbio_schedule(void)
-{
- /*
- * Needed so that two processes, who together make the following predicate
- * true, don't both read stale values and evaluate the predicate
- * incorrectly. Incredibly unlikely to stall the scheduler on x86, but...
- */
- smp_mb();
-
- if ( !list_empty(&usbio_schedule_list) )
- wake_up(&usbio_schedule_wait);
-}
-
-
-/******************************************************************************
- * NOTIFICATION FROM GUEST OS.
- */
-
-irqreturn_t usbif_be_int(int irq, void *dev_id, struct pt_regs *regs)
-{
- usbif_priv_t *up = dev_id;
-
- smp_mb();
-
- add_to_usbif_list_tail(up);
-
- /* Will in fact /always/ trigger an io schedule in this case. */
- maybe_trigger_usbio_schedule();
-
- return IRQ_HANDLED;
-}
-
-
-
-/******************************************************************
- * DOWNWARD CALLS -- These interface with the usb-device layer proper.
- */
-
-static int do_usb_io_op(usbif_priv_t *up, int max_to_do)
-{
- usbif_back_ring_t *usb_ring = &up->usb_ring;
- usbif_request_t *req;
- RING_IDX i, rp;
- int more_to_do = 0;
-
- rp = usb_ring->sring->req_prod;
- rmb(); /* Ensure we see queued requests up to 'rp'. */
-
- /* Take items off the comms ring, taking care not to overflow. */
- for ( i = usb_ring->req_cons;
- (i != rp) && !RING_REQUEST_CONS_OVERFLOW(usb_ring, i);
- i++ )
- {
- if ( (max_to_do-- == 0) || (NR_PENDING_REQS == MAX_PENDING_REQS) )
- {
- more_to_do = 1;
- break;
- }
-
- req = RING_GET_REQUEST(usb_ring, i);
-
- switch ( req->operation )
- {
- case USBIF_OP_PROBE:
- dispatch_usb_probe(up, req->id, req->port);
- break;
-
- case USBIF_OP_IO:
- /* Assemble an appropriate URB. */
- dispatch_usb_io(up, req);
- break;
-
- case USBIF_OP_RESET:
- dispatch_usb_reset(up, req->port);
- break;
-
- default:
- DPRINTK("error: unknown USB io operation [%d]\n",
- req->operation);
- make_response(up, req->id, req->operation, -EINVAL, 0, 0);
- break;
- }
- }
-
- usb_ring->req_cons = i;
-
- return more_to_do;
-}
-
-static owned_port_t *find_guest_port(usbif_priv_t *up, int port)
-{
- unsigned long flags;
- struct list_head *l;
-
- spin_lock_irqsave(&owned_ports_lock, flags);
- list_for_each(l, &owned_ports)
- {
- owned_port_t *p = list_entry(l, owned_port_t, list);
- if(p->usbif_priv == up && p->guest_port == port)
- {
- spin_unlock_irqrestore(&owned_ports_lock, flags);
- return p;
- }
- }
- spin_unlock_irqrestore(&owned_ports_lock, flags);
-
- return NULL;
-}
-
-static void dispatch_usb_reset(usbif_priv_t *up, unsigned long portid)
-{
- owned_port_t *port = find_guest_port(up, portid);
- int ret = 0;
-
-
- /* Allowing the guest to actually reset the device causes more problems
- * than it's worth. We just fake it out in software but we will do a real
- * reset when the interface is destroyed. */
-
- dump_port(port);
-
- port->guest_address = 0;
- /* If there's an attached device then the port is now enabled. */
- if ( port->dev_present )
- port->enabled = 1;
- else
- port->enabled = 0;
-
- make_response(up, 0, USBIF_OP_RESET, ret, 0, 0);
-}
-
-static void dispatch_usb_probe(usbif_priv_t *up, unsigned long id, unsigned
long portid)
-{
- owned_port_t *port = find_guest_port(up, portid);
- int ret;
-
- if ( port != NULL )
- ret = port->dev_present;
- else
- {
- ret = -EINVAL;
- printk(KERN_INFO "dispatch_usb_probe(): invalid port probe request "
- "(port %ld)\n", portid);
- }
-
- /* Probe result is sent back in-band. Probes don't have an associated id
- * right now... */
- make_response(up, id, USBIF_OP_PROBE, ret, portid, 0);
-}
-
-/**
- * check_iso_schedule - safety check the isochronous schedule for an URB
- * @purb : the URB in question
- */
-static int check_iso_schedule(struct urb *purb)
-{
- int i;
- unsigned long total_length = 0;
-
- for ( i = 0; i < purb->number_of_packets; i++ )
- {
- struct usb_iso_packet_descriptor *desc = &purb->iso_frame_desc[i];
-
- if ( desc->offset >= purb->transfer_buffer_length
- || ( desc->offset + desc->length) > purb->transfer_buffer_length )
- return -EINVAL;
-
- total_length += desc->length;
-
- if ( total_length > purb->transfer_buffer_length )
- return -EINVAL;
- }
-
- return 0;
-}
-
-owned_port_t *find_port_for_request(usbif_priv_t *up, usbif_request_t *req);
-
-static void dispatch_usb_io(usbif_priv_t *up, usbif_request_t *req)
-{
- unsigned long buffer_mach;
- int i = 0, offset = 0,
- pending_idx = pending_ring[MASK_PEND_IDX(pending_cons)];
- pending_req_t *pending_req;
- unsigned long remap_prot;
- multicall_entry_t mcl[MMAP_PAGES_PER_REQUEST];
- struct urb *purb = NULL;
- owned_port_t *port;
- unsigned char *setup;
-
- dump_request(req);
-
- if ( NR_PENDING_REQS == MAX_PENDING_REQS )
- {
- printk(KERN_WARNING "usbback: Max requests already queued. "
- "Giving up!\n");
-
- return;
- }
-
- port = find_port_for_request(up, req);
-
- if ( port == NULL )
- {
- printk(KERN_WARNING "No such device! (%d)\n", req->devnum);
- dump_request(req);
-
- make_response(up, req->id, req->operation, -ENODEV, 0, 0);
- return;
- }
- else if ( !port->dev_present )
- {
- /* In normal operation, we'll only get here if a device is unplugged
- * and the frontend hasn't noticed yet. */
- make_response(up, req->id, req->operation, -ENODEV, 0, 0);
- return;
- }
-
-
- setup = kmalloc(8, GFP_KERNEL);
-
- if ( setup == NULL )
- goto no_mem;
-
- /* Copy request out for safety. */
- memcpy(setup, req->setup, 8);
-
- if( setup[0] == 0x0 && setup[1] == 0x5)
- {
- /* To virtualise the USB address space, we need to intercept
- * set_address messages and emulate. From the USB specification:
- * bmRequestType = 0x0;
- * Brequest = SET_ADDRESS (i.e. 0x5)
- * wValue = device address
- * wIndex = 0
- * wLength = 0
- * data = None
- */
- /* Store into the guest transfer buffer using cpu_to_le16 */
- port->guest_address = le16_to_cpu(*(u16 *)(setup + 2));
- /* Make a successful response. That was easy! */
-
- make_response(up, req->id, req->operation, 0, 0, 0);
-
- kfree(setup);
- return;
- }
- else if ( setup[0] == 0x0 && setup[1] == 0x9 )
- {
- /* The host kernel needs to know what device configuration is in use
- * because various error checks get confused otherwise. We just do
- * configuration settings here, under controlled conditions.
- */
-
- /* Ignore configuration setting and hope that the host kernel
- did it right. */
- /* usb_set_configuration(port->dev, setup[2]); */
-
- make_response(up, req->id, req->operation, 0, 0, 0);
-
- kfree(setup);
- return;
- }
- else if ( setup[0] == 0x1 && setup[1] == 0xB )
- {
- /* The host kernel needs to know what device interface is in use
- * because various error checks get confused otherwise. We just do
- * configuration settings here, under controlled conditions.
- */
- usb_set_interface(port->dev, (setup[4] | setup[5] << 8),
- (setup[2] | setup[3] << 8) );
-
- make_response(up, req->id, req->operation, 0, 0, 0);
-
- kfree(setup);
- return;
- }
-
- if ( ( req->transfer_buffer - (req->transfer_buffer & PAGE_MASK)
- + req->length )
- > MMAP_PAGES_PER_REQUEST * PAGE_SIZE )
- {
- printk(KERN_WARNING "usbback: request of %lu bytes too large\n",
- req->length);
- make_response(up, req->id, req->operation, -EINVAL, 0, 0);
- kfree(setup);
- return;
- }
-
- buffer_mach = req->transfer_buffer;
-
- if( buffer_mach == 0 )
- goto no_remap;
-
- ASSERT((req->length >> PAGE_SHIFT) <= MMAP_PAGES_PER_REQUEST);
- ASSERT(buffer_mach);
-
- /* Always map writeable for now. */
- remap_prot = _KERNPG_TABLE;
-
- for ( i = 0, offset = 0; offset < req->length;
- i++, offset += PAGE_SIZE )
- {
- MULTI_update_va_mapping_otherdomain(
- mcl+i, MMAP_VADDR(pending_idx, i),
- pfn_pte_ma((buffer_mach + offset) >> PAGE_SHIFT, remap_prot),
- 0, up->domid);
-
- phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] =
- FOREIGN_FRAME((buffer_mach + offset) >> PAGE_SHIFT);
-
- ASSERT(virt_to_mfn(MMAP_VADDR(pending_idx, i))
- == ((buffer_mach >> PAGE_SHIFT) + i));
- }
-
- if ( req->pipe_type == 0 && req->num_iso > 0 ) /* Maybe schedule ISO... */
- {
- /* Map in ISO schedule, if necessary. */
- MULTI_update_va_mapping_otherdomain(
- mcl+i, MMAP_VADDR(pending_idx, i),
- pfn_pte_ma(req->iso_schedule >> PAGE_SHIFT, remap_prot),
- 0, up->domid);
-
- phys_to_machine_mapping[__pa(MMAP_VADDR(pending_idx, i))>>PAGE_SHIFT] =
- FOREIGN_FRAME(req->iso_schedule >> PAGE_SHIFT);
-
- i++;
- }
-
- if ( unlikely(HYPERVISOR_multicall(mcl, i) != 0) )
- BUG();
-
- {
- int j;
- for ( j = 0; j < i; j++ )
- {
- if ( unlikely(mcl[j].result != 0) )
- {
- printk(KERN_WARNING
- "invalid buffer %d -- could not remap it\n", j);
- fast_flush_area(pending_idx, i);
- goto bad_descriptor;
- }
- }
- }
-
- no_remap:
-
- ASSERT(i <= MMAP_PAGES_PER_REQUEST);
- ASSERT(i * PAGE_SIZE >= req->length);
-
- /* We have to do this because some things might complete out of order. */
- pending_req = &pending_reqs[pending_idx];
- pending_req->usbif_priv= up;
- pending_req->id = req->id;
- pending_req->operation = req->operation;
- pending_req->nr_pages = i;
-
- pending_cons++;
-
- usbif_get(up);
-
- /* Fill out an actual request for the USB layer. */
- purb = usb_alloc_urb(req->num_iso);
-
- if ( purb == NULL )
- {
- usbif_put(up);
- free_pending(pending_idx);
- goto no_mem;
- }
-
- purb->dev = port->dev;
- purb->context = pending_req;
- purb->transfer_buffer =
- (void *)(MMAP_VADDR(pending_idx, 0) + (buffer_mach & ~PAGE_MASK));
- if(buffer_mach == 0)
- purb->transfer_buffer = NULL;
- purb->complete = __end_usb_io_op;
- purb->transfer_buffer_length = req->length;
- purb->transfer_flags = req->transfer_flags;
-
- purb->pipe = 0;
- purb->pipe |= req->direction << 7;
- purb->pipe |= port->dev->devnum << 8;
- purb->pipe |= req->speed << 26;
- purb->pipe |= req->pipe_type << 30;
- purb->pipe |= req->endpoint << 15;
-
- purb->number_of_packets = req->num_iso;
-
- if ( purb->number_of_packets * sizeof(usbif_iso_t) > PAGE_SIZE )
- goto urb_error;
-
- /* Make sure there's always some kind of timeout. */
- purb->timeout = ( req->timeout > 0 ) ? (req->timeout * HZ) / 1000
- : 1000;
-
- purb->setup_packet = setup;
-
- if ( req->pipe_type == 0 ) /* ISO */
- {
- int j;
- usbif_iso_t *iso_sched = (usbif_iso_t *)MMAP_VADDR(pending_idx, i - 1);
-
- /* If we're dealing with an iso pipe, we need to copy in a schedule. */
- for ( j = 0; j < purb->number_of_packets; j++ )
- {
- purb->iso_frame_desc[j].length = iso_sched[j].length;
- purb->iso_frame_desc[j].offset = iso_sched[j].buffer_offset;
- iso_sched[j].status = 0;
- }
- }
-
- if ( check_iso_schedule(purb) != 0 )
- goto urb_error;
-
- if ( usb_submit_urb(purb) != 0 )
- goto urb_error;
-
- return;
-
- urb_error:
- dump_urb(purb);
- usbif_put(up);
- free_pending(pending_idx);
-
- bad_descriptor:
- kfree ( setup );
- if ( purb != NULL )
- usb_free_urb(purb);
- make_response(up, req->id, req->operation, -EINVAL, 0, 0);
- return;
-
- no_mem:
- if ( setup != NULL )
- kfree(setup);
- make_response(up, req->id, req->operation, -ENOMEM, 0, 0);
- return;
-}
-
-
-
-/******************************************************************
- * MISCELLANEOUS SETUP / TEARDOWN / DEBUGGING
- */
-
-
-static void make_response(usbif_priv_t *up, unsigned long id,
- unsigned short op, int st, int inband,
- unsigned long length)
-{
- usbif_response_t *resp;
- unsigned long flags;
- usbif_back_ring_t *usb_ring = &up->usb_ring;
-
- /* Place on the response ring for the relevant domain. */
- spin_lock_irqsave(&up->usb_ring_lock, flags);
- resp = RING_GET_RESPONSE(usb_ring, usb_ring->rsp_prod_pvt);
- resp->id = id;
- resp->operation = op;
- resp->status = st;
- resp->data = inband;
- resp->length = length;
- wmb(); /* Ensure other side can see the response fields. */
-
- dump_response(resp);
-
- usb_ring->rsp_prod_pvt++;
- RING_PUSH_RESPONSES(usb_ring);
- spin_unlock_irqrestore(&up->usb_ring_lock, flags);
-
- /* Kick the relevant domain. */
- notify_via_evtchn(up->evtchn);
-}
-
-/**
- * usbif_claim_port - claim devices on a port on behalf of guest
- *
- * Once completed, this will ensure that any device attached to that
- * port is claimed by this driver for use by the guest.
- */
-int usbif_claim_port(usbif_be_claim_port_t *msg)
-{
- owned_port_t *o_p;
-
- /* Sanity... */
- if ( usbif_find_port(msg->path) != NULL )
- {
- printk(KERN_WARNING "usbback: Attempted to claim USB port "
- "we already own!\n");
- return -EINVAL;
- }
-
- /* No need for a slab cache - this should be infrequent. */
- o_p = kmalloc(sizeof(owned_port_t), GFP_KERNEL);
-
- if ( o_p == NULL )
- return -ENOMEM;
-
- o_p->enabled = 0;
- o_p->usbif_priv = usbif_find(msg->domid);
- o_p->guest_port = msg->usbif_port;
- o_p->dev_present = 0;
- o_p->guest_address = 0; /* Default address. */
-
- strcpy(o_p->path, msg->path);
-
- spin_lock_irq(&owned_ports_lock);
-
- list_add(&o_p->list, &owned_ports);
-
- spin_unlock_irq(&owned_ports_lock);
-
- printk(KERN_INFO "usbback: Claimed USB port (%s) for %d.%d\n", o_p->path,
- msg->domid, msg->usbif_port);
-
- /* Force a reprobe for unclaimed devices. */
- usb_scan_devices();
-
- return 0;
-}
-
-owned_port_t *find_port_for_request(usbif_priv_t *up, usbif_request_t *req)
-{
- unsigned long flags;
- struct list_head *port;
-
- /* I'm assuming this is not called from IRQ context - correct? I think
- * it's probably only called in response to control messages or plug events
- * in the USB hub kernel thread, so should be OK. */
- spin_lock_irqsave(&owned_ports_lock, flags);
- list_for_each(port, &owned_ports)
- {
- owned_port_t *p = list_entry(port, owned_port_t, list);
- if(p->usbif_priv == up && p->guest_address == req->devnum &&
p->enabled )
- {
- dump_port(p);
-
- spin_unlock_irqrestore(&owned_ports_lock, flags);
- return p;
- }
- }
- spin_unlock_irqrestore(&owned_ports_lock, flags);
-
- return NULL;
-}
-
-owned_port_t *__usbif_find_port(char *path)
-{
- struct list_head *port;
-
- list_for_each(port, &owned_ports)
- {
- owned_port_t *p = list_entry(port, owned_port_t, list);
- if(!strcmp(path, p->path))
- {
- return p;
- }
- }
-
- return NULL;
-}
-
-owned_port_t *usbif_find_port(char *path)
-{
- owned_port_t *ret;
- unsigned long flags;
-
- spin_lock_irqsave(&owned_ports_lock, flags);
- ret = __usbif_find_port(path);
- spin_unlock_irqrestore(&owned_ports_lock, flags);
-
- return ret;
-}
-
-
-static void *probe(struct usb_device *dev, unsigned iface,
- const struct usb_device_id *id)
-{
- owned_port_t *p;
-
- /* We don't care what the device is - if we own the port, we want it. We
- * don't deal with device-specifics in this driver, so we don't care what
- * the device actually is ;-) */
- if ( ( p = usbif_find_port(dev->devpath) ) != NULL )
- {
- printk(KERN_INFO "usbback: claimed device attached to owned port\n");
-
- p->dev_present = 1;
- p->dev = dev;
- set_bit(iface, &p->ifaces);
-
- return p->usbif_priv;
- }
- else
- printk(KERN_INFO "usbback: hotplug for non-owned port (%s),
ignoring\n",
- dev->devpath);
-
-
- return NULL;
-}
-
-static void disconnect(struct usb_device *dev, void *usbif)
-{
- /* Note the device is removed so we can tell the guest when it probes. */
- owned_port_t *port = usbif_find_port(dev->devpath);
- port->dev_present = 0;
- port->dev = NULL;
- port->ifaces = 0;
-}
-
-
-struct usb_driver driver =
-{
- .owner = THIS_MODULE,
- .name = "Xen USB Backend",
- .probe = probe,
- .disconnect = disconnect,
- .id_table = NULL,
-};
-
-/* __usbif_release_port - internal mechanics for releasing a port */
-void __usbif_release_port(owned_port_t *p)
-{
- int i;
-
- for ( i = 0; p->ifaces != 0; i++)
- if ( p->ifaces & 1 << i )
- {
- usb_driver_release_interface(&driver, usb_ifnum_to_if(p->dev, i));
- clear_bit(i, &p->ifaces);
- }
- list_del(&p->list);
-
- /* Reset the real device. We don't simulate disconnect / probe for other
- * drivers in this kernel because we assume the device is completely under
- * the control of ourselves (i.e. the guest!). This should ensure that the
- * device is in a sane state for the next customer ;-) */
-
- /* MAW NB: we're not resetting the real device here. This looks perfectly
- * valid to me but it causes memory corruption. We seem to get away with
not
- * resetting for now, although it'd be nice to have this tracked down. */
-/* if ( p->dev != NULL) */
-/* usb_reset_device(p->dev); */
-
- kfree(p);
-}
-
-
-/**
- * usbif_release_port - stop claiming devices on a port on behalf of guest
- */
-void usbif_release_port(usbif_be_release_port_t *msg)
-{
- owned_port_t *p;
-
- spin_lock_irq(&owned_ports_lock);
- p = __usbif_find_port(msg->path);
- __usbif_release_port(p);
- spin_unlock_irq(&owned_ports_lock);
-}
-
-void usbif_release_ports(usbif_priv_t *up)
-{
- struct list_head *port, *tmp;
- unsigned long flags;
-
- spin_lock_irqsave(&owned_ports_lock, flags);
- list_for_each_safe(port, tmp, &owned_ports)
- {
- owned_port_t *p = list_entry(port, owned_port_t, list);
- if ( p->usbif_priv == up )
- __usbif_release_port(p);
- }
- spin_unlock_irqrestore(&owned_ports_lock, flags);
-}
-
-static int __init usbif_init(void)
-{
- int i;
- struct page *page;
-
- if ( !(xen_start_info->flags & SIF_INITDOMAIN) &&
- !(xen_start_info->flags & SIF_USB_BE_DOMAIN) )
- return 0;
-
- page = balloon_alloc_empty_page_range(MMAP_PAGES);
- BUG_ON(page == NULL);
- mmap_vstart = (unsigned long)pfn_to_kaddr(page_to_pfn(page));
-
- pending_cons = 0;
- pending_prod = MAX_PENDING_REQS;
- memset(pending_reqs, 0, sizeof(pending_reqs));
- for ( i = 0; i < MAX_PENDING_REQS; i++ )
- pending_ring[i] = i;
-
- spin_lock_init(&pend_prod_lock);
-
- spin_lock_init(&owned_ports_lock);
- INIT_LIST_HEAD(&owned_ports);
-
- spin_lock_init(&usbio_schedule_list_lock);
- INIT_LIST_HEAD(&usbio_schedule_list);
-
- if ( kernel_thread(usbio_schedule, 0, CLONE_FS | CLONE_FILES) < 0 )
- BUG();
-
- usbif_interface_init();
-
- usbif_ctrlif_init();
-
- usb_register(&driver);
-
- printk(KERN_INFO "Xen USB Backend Initialised");
-
- return 0;
-}
-
-__initcall(usbif_init);
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/usbfront/usbfront.c
--- a/linux-2.6-xen-sparse/drivers/xen/usbfront/usbfront.c Thu Sep 22
15:05:44 2005
+++ /dev/null Thu Sep 22 15:12:14 2005
@@ -1,1735 +0,0 @@
-/*
- * Xen Virtual USB Frontend Driver
- *
- * This file contains the first version of the Xen virtual USB hub
- * that I've managed not to delete by mistake (3rd time lucky!).
- *
- * Based on Linux's uhci.c, original copyright notices are displayed
- * below. Portions also (c) 2004 Intel Research Cambridge
- * and (c) 2004, 2005 Mark Williamson
- *
- * Contact <mark.williamson@xxxxxxxxxxxx> or
- * <xen-devel@xxxxxxxxxxxxxxxxxxxxx> regarding this code.
- *
- * Still to be (maybe) implemented:
- * - migration / backend restart support?
- * - support for building / using as a module
- */
-
-/*
- * Universal Host Controller Interface driver for USB.
- *
- * Maintainer: Johannes Erdfelt <johannes@xxxxxxxxxxx>
- *
- * (C) Copyright 1999 Linus Torvalds
- * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@xxxxxxxxxxx
- * (C) Copyright 1999 Randy Dunlap
- * (C) Copyright 1999 Georg Acher, acher@xxxxxxxxx
- * (C) Copyright 1999 Deti Fliegl, deti@xxxxxxxxx
- * (C) Copyright 1999 Thomas Sailer, sailer@xxxxxxxxxxxxxx
- * (C) Copyright 1999 Roman Weissgaerber, weissg@xxxxxxxxx
- * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
- * support from usb-ohci.c by Adam Richter, adam@xxxxxxxxxxxxx).
- * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
- *
- * Intel documents this fairly well, and as far as I know there
- * are no royalties or anything like that, but even so there are
- * people who decided that they want to do the same thing in a
- * completely different way.
- *
- * WARNING! The USB documentation is downright evil. Most of it
- * is just crap, written by a committee. You're better off ignoring
- * most of it, the important stuff is:
- * - the low-level protocol (fairly simple but lots of small details)
- * - working around the horridness of the rest
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/smp_lock.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
-#ifdef CONFIG_USB_DEBUG
-#define DEBUG
-#else
-#undef DEBUG
-#endif
-#include <linux/usb.h>
-
-#include <asm/irq.h>
-#include <asm/system.h>
-
-#include "xhci.h"
-
-#include "../../../../../drivers/usb/hcd.h"
-
-#include <asm-xen/xen-public/io/usbif.h>
-#include <asm/xen-public/io/domain_controller.h>
-
-/*
- * Version Information
- */
-#define DRIVER_VERSION "v1.0"
-#define DRIVER_AUTHOR "Linus 'Frodo Rabbit' Torvalds, Johannes Erdfelt, " \
- "Randy Dunlap, Georg Acher, Deti Fliegl, " \
- "Thomas Sailer, Roman Weissgaerber, Mark Williamson"
-#define DRIVER_DESC "Xen Virtual USB Host Controller Interface"
-
-/*
- * debug = 0, no debugging messages
- * debug = 1, dump failed URB's except for stalls
- * debug = 2, dump all failed URB's (including stalls)
- */
-#ifdef DEBUG
-static int debug = 1;
-#else
-static int debug = 0;
-#endif
-MODULE_PARM(debug, "i");
-MODULE_PARM_DESC(debug, "Debug level");
-static char *errbuf;
-#define ERRBUF_LEN (PAGE_SIZE * 8)
-
-static int rh_submit_urb(struct urb *urb);
-static int rh_unlink_urb(struct urb *urb);
-static int xhci_unlink_urb(struct urb *urb);
-static void xhci_call_completion(struct urb *urb);
-static void xhci_drain_ring(void);
-static void xhci_transfer_result(struct xhci *xhci, struct urb *urb);
-static void xhci_finish_completion(void);
-
-#define MAX_URB_LOOP 2048 /* Maximum number of linked URB's */
-
-static kmem_cache_t *xhci_up_cachep; /* urb_priv cache */
-static struct xhci *xhci; /* XHCI structure for the interface */
-
-/******************************************************************************
- * DEBUGGING
- */
-
-#ifdef DEBUG
-
-static void dump_urb(struct urb *urb)
-{
- printk(KERN_DEBUG "dumping urb @ %p\n"
- " hcpriv = %p\n"
- " next = %p\n"
- " dev = %p\n"
- " pipe = 0x%lx\n"
- " status = %d\n"
- " transfer_flags = 0x%lx\n"
- " transfer_buffer = %p\n"
- " transfer_buffer_length = %d\n"
- " actual_length = %d\n"
- " bandwidth = %d\n"
- " setup_packet = %p\n",
- urb, urb->hcpriv, urb->next, urb->dev, urb->pipe, urb->status,
- urb->transfer_flags, urb->transfer_buffer,
- urb->transfer_buffer_length, urb->actual_length, urb->bandwidth,
- urb->setup_packet);
- if ( urb->setup_packet != NULL )
- printk(KERN_DEBUG
- "setup = { 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x }\n",
- urb->setup_packet[0], urb->setup_packet[1],
- urb->setup_packet[2], urb->setup_packet[3],
- urb->setup_packet[4], urb->setup_packet[5],
- urb->setup_packet[6], urb->setup_packet[7]);
- printk(KERN_DEBUG "complete = %p\n"
- "interval = %d\n", urb->complete, urb->interval);
-
-}
-
-static void xhci_show_resp(usbif_response_t *r)
-{
- printk(KERN_DEBUG "dumping response @ %p\n"
- " id=0x%lx\n"
- " op=0x%x\n"
- " data=0x%x\n"
- " status=0x%x\n"
- " length=0x%lx\n",
- r->id, r->operation, r->data, r->status, r->length);
-}
-
-#define DPRINK(...) printk(KERN_DEBUG __VA_ARGS__)
-
-#else /* DEBUG */
-
-#define dump_urb(blah) ((void)0)
-#define xhci_show_resp(blah) ((void)0)
-#define DPRINTK(blah,...) ((void)0)
-
-#endif /* DEBUG */
-
-/******************************************************************************
- * RING REQUEST HANDLING
- */
-
-#define RING_PLUGGED(_hc) ( RING_FULL(&_hc->usb_ring) || _hc->recovery )
-
-/**
- * xhci_construct_isoc - add isochronous information to a request
- */
-static int xhci_construct_isoc(usbif_request_t *req, struct urb *urb)
-{
- usbif_iso_t *schedule;
- int i;
- struct urb_priv *urb_priv = urb->hcpriv;
-
- req->num_iso = urb->number_of_packets;
- schedule = (usbif_iso_t *)__get_free_page(GFP_KERNEL);
-
- if ( schedule == NULL )
- return -ENOMEM;
-
- for ( i = 0; i < req->num_iso; i++ )
- {
- schedule[i].buffer_offset = urb->iso_frame_desc[i].offset;
- schedule[i].length = urb->iso_frame_desc[i].length;
- }
-
- urb_priv->schedule = schedule;
- req->iso_schedule = virt_to_mfn(schedule) << PAGE_SHIFT;
-
- return 0;
-}
-
-/**
- * xhci_queue_req - construct and queue request for an URB
- */
-static int xhci_queue_req(struct urb *urb)
-{
- unsigned long flags;
- usbif_request_t *req;
- usbif_front_ring_t *usb_ring = &xhci->usb_ring;
-
-#if DEBUG
- printk(KERN_DEBUG
- "usbif = %p, req_prod = %d (@ 0x%lx), resp_prod = %d, resp_cons
= %d\n",
- usbif, usbif->req_prod, virt_to_mfn(&usbif->req_prod),
- usbif->resp_prod, xhci->usb_resp_cons);
-#endif
-
- spin_lock_irqsave(&xhci->ring_lock, flags);
-
- if ( RING_PLUGGED(xhci) )
- {
- printk(KERN_WARNING
- "xhci_queue_req(): USB ring plugged, not queuing
request\n");
- spin_unlock_irqrestore(&xhci->ring_lock, flags);
- return -ENOBUFS;
- }
-
- /* Stick something in the shared communications ring. */
- req = RING_GET_REQUEST(usb_ring, usb_ring->req_prod_pvt);
-
- req->operation = USBIF_OP_IO;
- req->port = 0; /* We don't care what the port is. */
- req->id = (unsigned long) urb->hcpriv;
- req->transfer_buffer = virt_to_mfn(urb->transfer_buffer) << PAGE_SHIFT;
- req->devnum = usb_pipedevice(urb->pipe);
- req->direction = usb_pipein(urb->pipe);
- req->speed = usb_pipeslow(urb->pipe);
- req->pipe_type = usb_pipetype(urb->pipe);
- req->length = urb->transfer_buffer_length;
- req->transfer_flags = urb->transfer_flags;
- req->endpoint = usb_pipeendpoint(urb->pipe);
- req->speed = usb_pipeslow(urb->pipe);
- req->timeout = urb->timeout * (1000 / HZ);
-
- if ( usb_pipetype(urb->pipe) == 0 ) /* ISO */
- {
- int ret = xhci_construct_isoc(req, urb);
- if ( ret != 0 )
- return ret;
- }
-
- if(urb->setup_packet != NULL)
- memcpy(req->setup, urb->setup_packet, 8);
- else
- memset(req->setup, 0, 8);
-
- usb_ring->req_prod_pvt++;
- RING_PUSH_REQUESTS(usb_ring);
-
- spin_unlock_irqrestore(&xhci->ring_lock, flags);
-
- notify_via_evtchn(xhci->evtchn);
-
- DPRINTK("Queued request for an URB.\n");
- dump_urb(urb);
-
- return -EINPROGRESS;
-}
-
-/**
- * xhci_queue_probe - queue a probe request for a particular port
- */
-static inline usbif_request_t *xhci_queue_probe(usbif_vdev_t port)
-{
- usbif_request_t *req;
- usbif_front_ring_t *usb_ring = &xhci->usb_ring;
-
-#if DEBUG
- printk(KERN_DEBUG
- "queuing probe: req_prod = %d (@ 0x%lx), resp_prod = %d, "
- "resp_cons = %d\n", usbif->req_prod,
- virt_to_mfn(&usbif->req_prod),
- usbif->resp_prod, xhci->usb_resp_cons);
-#endif
-
- /* This is always called from the timer interrupt. */
- spin_lock(&xhci->ring_lock);
-
- if ( RING_PLUGGED(xhci) )
- {
- printk(KERN_WARNING
- "xhci_queue_probe(): ring full, not queuing request\n");
- spin_unlock(&xhci->ring_lock);
- return NULL;
- }
-
- /* Stick something in the shared communications ring. */
- req = RING_GET_REQUEST(usb_ring, usb_ring->req_prod_pvt);
-
- memset(req, 0, sizeof(*req));
-
- req->operation = USBIF_OP_PROBE;
- req->port = port;
-
- usb_ring->req_prod_pvt++;
- RING_PUSH_REQUESTS(usb_ring);
-
- spin_unlock(&xhci->ring_lock);
-
- notify_via_evtchn(xhci->evtchn);
-
- return req;
-}
-
-/**
- * xhci_port_reset - queue a reset request for a particular port
- */
-static int xhci_port_reset(usbif_vdev_t port)
-{
- usbif_request_t *req;
- usbif_front_ring_t *usb_ring = &xhci->usb_ring;
-
- /* Only ever happens from process context (hub thread). */
- spin_lock_irq(&xhci->ring_lock);
-
- if ( RING_PLUGGED(xhci) )
- {
- printk(KERN_WARNING
- "xhci_port_reset(): ring plugged, not queuing
request\n");
- spin_unlock_irq(&xhci->ring_lock);
- return -ENOBUFS;
- }
-
- /* We only reset one port at a time, so we only need one variable per
- * hub. */
- xhci->awaiting_reset = 1;
-
- /* Stick something in the shared communications ring. */
- req = RING_GET_REQUEST(usb_ring, usb_ring->req_prod_pvt);
-
- memset(req, 0, sizeof(*req));
-
- req->operation = USBIF_OP_RESET;
- req->port = port;
-
- usb_ring->req_prod_pvt++;
- RING_PUSH_REQUESTS(usb_ring);
-
- spin_unlock_irq(&xhci->ring_lock);
-
- notify_via_evtchn(xhci->evtchn);
-
- while ( xhci->awaiting_reset > 0 )
- {
- mdelay(1);
- xhci_drain_ring();
- }
-
- xhci->rh.ports[port].pe = 1;
- xhci->rh.ports[port].pe_chg = 1;
-
- return xhci->awaiting_reset;
-}
-
-
-/******************************************************************************
- * RING RESPONSE HANDLING
- */
-
-static void receive_usb_reset(usbif_response_t *resp)
-{
- xhci->awaiting_reset = resp->status;
- rmb();
-
-}
-
-static void receive_usb_probe(usbif_response_t *resp)
-{
- spin_lock(&xhci->rh.port_state_lock);
-
- if ( resp->status >= 0 )
- {
- if ( resp->status == 1 )
- {
- /* If theres a device there and there wasn't one before there must
- * have been a connection status change. */
- if( xhci->rh.ports[resp->data].cs == 0 )
- {
- xhci->rh.ports[resp->data].cs = 1;
- xhci->rh.ports[resp->data].cs_chg = 1;
- }
- }
- else if ( resp->status == 0 )
- {
- if(xhci->rh.ports[resp->data].cs == 1 )
- {
- xhci->rh.ports[resp->data].cs = 0;
- xhci->rh.ports[resp->data].cs_chg = 1;
- xhci->rh.ports[resp->data].pe = 0;
- /* According to USB Spec v2.0, 11.24.2.7.2.2, we don't need
- * to set pe_chg since an error has not occurred. */
- }
- }
- else
- printk(KERN_WARNING "receive_usb_probe(): unexpected status %d "
- "for port %d\n", resp->status, resp->data);
- }
- else if ( resp->status < 0)
- printk(KERN_WARNING "receive_usb_probe(): got error status %d\n",
- resp->status);
-
- spin_unlock(&xhci->rh.port_state_lock);
-}
-
-static void receive_usb_io(usbif_response_t *resp)
-{
- struct urb_priv *urbp = (struct urb_priv *)resp->id;
- struct urb *urb = urbp->urb;
-
- urb->actual_length = resp->length;
- urbp->in_progress = 0;
-
- if( usb_pipetype(urb->pipe) == 0 ) /* ISO */
- {
- int i;
-
- /* Copy ISO schedule results back in. */
- for ( i = 0; i < urb->number_of_packets; i++ )
- {
- urb->iso_frame_desc[i].status
- = urbp->schedule[i].status;
- urb->iso_frame_desc[i].actual_length
- = urbp->schedule[i].length;
- }
- free_page((unsigned long)urbp->schedule);
- }
-
- /* Only set status if it's not been changed since submission. It might
- * have been changed if the URB has been unlinked asynchronously, for
- * instance. */
- if ( urb->status == -EINPROGRESS )
- urbp->status = urb->status = resp->status;
-}
-
-/**
- * xhci_drain_ring - drain responses from the ring, calling handlers
- *
- * This may be called from interrupt context when an event is received from the
- * backend domain, or sometimes in process context whilst waiting for a port
- * reset or URB completion.
- */
-static void xhci_drain_ring(void)
-{
- struct list_head *tmp, *head;
- usbif_front_ring_t *usb_ring = &xhci->usb_ring;
- usbif_response_t *resp;
- RING_IDX i, rp;
-
- /* Walk the ring here to get responses, updating URBs to show what
- * completed. */
-
- rp = usb_ring->sring->rsp_prod;
- rmb(); /* Ensure we see queued requests up to 'rp'. */
-
- /* Take items off the comms ring, taking care not to overflow. */
- for ( i = usb_ring->rsp_cons; i != rp; i++ )
- {
- resp = RING_GET_RESPONSE(usb_ring, i);
-
- /* May need to deal with batching and with putting a ceiling on
- the number dispatched for performance and anti-dos reasons */
-
- xhci_show_resp(resp);
-
- switch ( resp->operation )
- {
- case USBIF_OP_PROBE:
- receive_usb_probe(resp);
- break;
-
- case USBIF_OP_IO:
- receive_usb_io(resp);
- break;
-
- case USBIF_OP_RESET:
- receive_usb_reset(resp);
- break;
-
- default:
- printk(KERN_WARNING
- "error: unknown USB io operation response [%d]\n",
- resp->operation);
- break;
- }
- }
-
- usb_ring->rsp_cons = i;
-
- /* Walk the list of pending URB's to see which ones completed and do
- * callbacks, etc. */
- spin_lock(&xhci->urb_list_lock);
- head = &xhci->urb_list;
- tmp = head->next;
- while (tmp != head) {
- struct urb *urb = list_entry(tmp, struct urb, urb_list);
-
- tmp = tmp->next;
-
- /* Checks the status and does all of the magic necessary */
- xhci_transfer_result(xhci, urb);
- }
- spin_unlock(&xhci->urb_list_lock);
-
- xhci_finish_completion();
-}
-
-
-static void xhci_interrupt(int irq, void *__xhci, struct pt_regs *regs)
-{
- xhci_drain_ring();
-}
-
-/******************************************************************************
- * HOST CONTROLLER FUNCTIONALITY
- */
-
-/**
- * no-op implementation of private device alloc / free routines
- */
-static int xhci_do_nothing_dev(struct usb_device *dev)
-{
- return 0;
-}
-
-static inline void xhci_add_complete(struct urb *urb)
-{
- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
- unsigned long flags;
-
- spin_lock_irqsave(&xhci->complete_list_lock, flags);
- list_add_tail(&urbp->complete_list, &xhci->complete_list);
- spin_unlock_irqrestore(&xhci->complete_list_lock, flags);
-}
-
-/* When this returns, the owner of the URB may free its
- * storage.
- *
- * We spin and wait for the URB to complete before returning.
- *
- * Call with urb->lock acquired.
- */
-static void xhci_delete_urb(struct urb *urb)
-{
- struct urb_priv *urbp;
-
- urbp = urb->hcpriv;
-
- /* If there's no urb_priv structure for this URB then it can't have
- * been submitted at all. */
- if ( urbp == NULL )
- return;
-
- /* For now we just spin until the URB completes. It shouldn't take too
- * long and we don't expect to have to do this very often. */
- while ( urb->status == -EINPROGRESS )
- {
- xhci_drain_ring();
- mdelay(1);
- }
-
- /* Now we know that further transfers to the buffer won't
- * occur, so we can safely return. */
-}
-
-static struct urb_priv *xhci_alloc_urb_priv(struct urb *urb)
-{
- struct urb_priv *urbp;
-
- urbp = kmem_cache_alloc(xhci_up_cachep, SLAB_ATOMIC);
- if (!urbp) {
- err("xhci_alloc_urb_priv: couldn't allocate memory for
urb_priv\n");
- return NULL;
- }
-
- memset((void *)urbp, 0, sizeof(*urbp));
-
- urbp->inserttime = jiffies;
- urbp->urb = urb;
- urbp->dev = urb->dev;
-
- INIT_LIST_HEAD(&urbp->complete_list);
-
- urb->hcpriv = urbp;
-
- return urbp;
-}
-
-/*
- * MUST be called with urb->lock acquired
- */
-/* When is this called? Do we need to stop the transfer (as we
- * currently do)? */
-static void xhci_destroy_urb_priv(struct urb *urb)
-{
- struct urb_priv *urbp;
-
- urbp = (struct urb_priv *)urb->hcpriv;
- if (!urbp)
- return;
-
- if (!list_empty(&urb->urb_list))
- warn("xhci_destroy_urb_priv: urb %p still on xhci->urb_list", urb);
-
- if (!list_empty(&urbp->complete_list))
- warn("xhci_destroy_urb_priv: urb %p still on xhci->complete_list",
urb);
-
- kmem_cache_free(xhci_up_cachep, urb->hcpriv);
-
- urb->hcpriv = NULL;
-}
-
-/**
- * Try to find URBs in progress on the same pipe to the same device.
- *
- * MUST be called with xhci->urb_list_lock acquired
- */
-static struct urb *xhci_find_urb_ep(struct xhci *xhci, struct urb *urb)
-{
- struct list_head *tmp, *head;
-
- /* We don't match Isoc transfers since they are special */
- if (usb_pipeisoc(urb->pipe))
- return NULL;
-
- head = &xhci->urb_list;
- tmp = head->next;
- while (tmp != head) {
- struct urb *u = list_entry(tmp, struct urb, urb_list);
-
- tmp = tmp->next;
-
- if (u->dev == urb->dev && u->pipe == urb->pipe &&
- u->status == -EINPROGRESS)
- return u;
- }
-
- return NULL;
-}
-
-static int xhci_submit_urb(struct urb *urb)
-{
- int ret = -EINVAL;
- unsigned long flags;
- struct urb *eurb;
- int bustime;
-
- DPRINTK("URB submitted to XHCI driver.\n");
- dump_urb(urb);
-
- if (!urb)
- return -EINVAL;
-
- if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv) {
- warn("xhci_submit_urb: urb %p belongs to disconnected device or
bus?", urb);
- return -ENODEV;
- }
-
- if ( urb->dev->devpath == NULL )
- BUG();
-
- usb_inc_dev_use(urb->dev);
-
- spin_lock_irqsave(&xhci->urb_list_lock, flags);
- spin_lock(&urb->lock);
-
- if (urb->status == -EINPROGRESS || urb->status == -ECONNRESET ||
- urb->status == -ECONNABORTED) {
- dbg("xhci_submit_urb: urb not available to submit (status =
%d)", urb->status);
- /* Since we can have problems on the out path */
- spin_unlock(&urb->lock);
- spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
- usb_dec_dev_use(urb->dev);
-
- return ret;
- }
-
- INIT_LIST_HEAD(&urb->urb_list);
- if (!xhci_alloc_urb_priv(urb)) {
- ret = -ENOMEM;
-
- goto out;
- }
-
- ( (struct urb_priv *)urb->hcpriv )->in_progress = 1;
-
- eurb = xhci_find_urb_ep(xhci, urb);
- if (eurb && !(urb->transfer_flags & USB_QUEUE_BULK)) {
- ret = -ENXIO;
-
- goto out;
- }
-
- /* Short circuit the virtual root hub */
- if (urb->dev == xhci->rh.dev) {
- ret = rh_submit_urb(urb);
-
- goto out;
- }
-
- switch (usb_pipetype(urb->pipe)) {
- case PIPE_CONTROL:
- case PIPE_BULK:
- ret = xhci_queue_req(urb);
- break;
-
- case PIPE_INTERRUPT:
- if (urb->bandwidth == 0) { /* not yet checked/allocated */
- bustime = usb_check_bandwidth(urb->dev, urb);
- if (bustime < 0)
- ret = bustime;
- else {
- ret = xhci_queue_req(urb);
- if (ret == -EINPROGRESS)
- usb_claim_bandwidth(urb->dev, urb,
- bustime, 0);
- }
- } else /* bandwidth is already set */
- ret = xhci_queue_req(urb);
- break;
-
- case PIPE_ISOCHRONOUS:
- if (urb->bandwidth == 0) { /* not yet checked/allocated */
- if (urb->number_of_packets <= 0) {
- ret = -EINVAL;
- break;
- }
- bustime = usb_check_bandwidth(urb->dev, urb);
- if (bustime < 0) {
- ret = bustime;
- break;
- }
-
- ret = xhci_queue_req(urb);
- if (ret == -EINPROGRESS)
- usb_claim_bandwidth(urb->dev, urb, bustime, 1);
- } else /* bandwidth is already set */
- ret = xhci_queue_req(urb);
- break;
- }
-out:
- urb->status = ret;
-
- if (ret == -EINPROGRESS) {
- /* We use _tail to make find_urb_ep more efficient */
- list_add_tail(&urb->urb_list, &xhci->urb_list);
-
- spin_unlock(&urb->lock);
- spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
-
- return 0;
- }
-
- xhci_delete_urb(urb);
-
- spin_unlock(&urb->lock);
- spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
-
- /* Only call completion if it was successful */
- if (!ret)
- xhci_call_completion(urb);
-
- return ret;
-}
-
-/*
- * Return the result of a transfer
- *
- * MUST be called with urb_list_lock acquired
- */
-static void xhci_transfer_result(struct xhci *xhci, struct urb *urb)
-{
- int ret = 0;
- unsigned long flags;
- struct urb_priv *urbp;
-
- /* The root hub is special */
- if (urb->dev == xhci->rh.dev)
- return;
-
- spin_lock_irqsave(&urb->lock, flags);
-
- urbp = (struct urb_priv *)urb->hcpriv;
-
- if ( ( (struct urb_priv *)urb->hcpriv )->in_progress )
- ret = -EINPROGRESS;
-
- if (urb->actual_length < urb->transfer_buffer_length) {
- if (urb->transfer_flags & USB_DISABLE_SPD) {
- ret = -EREMOTEIO;
- }
- }
-
- if (urb->status == -EPIPE)
- {
- ret = urb->status;
- /* endpoint has stalled - mark it halted */
- usb_endpoint_halt(urb->dev, usb_pipeendpoint(urb->pipe),
- usb_pipeout(urb->pipe));
- }
-
- if ((debug == 1 && ret != 0 && ret != -EPIPE) ||
- (ret != 0 && debug > 1)) {
- /* Some debugging code */
- dbg("xhci_result_interrupt/bulk() failed with status %x",
- status);
- }
-
- if (ret == -EINPROGRESS)
- goto out;
-
- switch (usb_pipetype(urb->pipe)) {
- case PIPE_CONTROL:
- case PIPE_BULK:
- case PIPE_ISOCHRONOUS:
- /* Release bandwidth for Interrupt or Isoc. transfers */
- /* Spinlock needed ? */
- if (urb->bandwidth)
- usb_release_bandwidth(urb->dev, urb, 1);
- xhci_delete_urb(urb);
- break;
- case PIPE_INTERRUPT:
- /* Interrupts are an exception */
- if (urb->interval)
- goto out_complete;
-
- /* Release bandwidth for Interrupt or Isoc. transfers */
- /* Spinlock needed ? */
- if (urb->bandwidth)
- usb_release_bandwidth(urb->dev, urb, 0);
- xhci_delete_urb(urb);
- break;
- default:
- info("xhci_transfer_result: unknown pipe type %d for urb %p\n",
- usb_pipetype(urb->pipe), urb);
- }
-
- /* Remove it from xhci->urb_list */
- list_del_init(&urb->urb_list);
-
-out_complete:
- xhci_add_complete(urb);
-
-out:
- spin_unlock_irqrestore(&urb->lock, flags);
-}
-
-static int xhci_unlink_urb(struct urb *urb)
-{
- unsigned long flags;
- struct urb_priv *urbp = urb->hcpriv;
-
- if (!urb)
- return -EINVAL;
-
- if (!urb->dev || !urb->dev->bus || !urb->dev->bus->hcpriv)
- return -ENODEV;
-
- spin_lock_irqsave(&xhci->urb_list_lock, flags);
- spin_lock(&urb->lock);
-
- /* Release bandwidth for Interrupt or Isoc. transfers */
- /* Spinlock needed ? */
- if (urb->bandwidth) {
- switch (usb_pipetype(urb->pipe)) {
- case PIPE_INTERRUPT:
- usb_release_bandwidth(urb->dev, urb, 0);
- break;
- case PIPE_ISOCHRONOUS:
- usb_release_bandwidth(urb->dev, urb, 1);
- break;
- default:
- break;
- }
- }
-
- if (urb->status != -EINPROGRESS) {
- spin_unlock(&urb->lock);
- spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
- return 0;
- }
-
- list_del_init(&urb->urb_list);
-
- /* Short circuit the virtual root hub */
- if (urb->dev == xhci->rh.dev) {
- rh_unlink_urb(urb);
-
- spin_unlock(&urb->lock);
- spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
-
- xhci_call_completion(urb);
- } else {
- if (urb->transfer_flags & USB_ASYNC_UNLINK) {
- /* We currently don't currently attempt to cancel URBs
- * that have been queued in the ring. We handle async
- * unlinked URBs when they complete. */
- urbp->status = urb->status = -ECONNABORTED;
- spin_unlock(&urb->lock);
- spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
- } else {
- urb->status = -ENOENT;
-
- spin_unlock(&urb->lock);
- spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
-
- if (in_interrupt()) { /* wait at least 1 frame */
- static int errorcount = 10;
-
- if (errorcount--)
- dbg("xhci_unlink_urb called from
interrupt for urb %p", urb);
- udelay(1000);
- } else
- schedule_timeout(1+1*HZ/1000);
-
- xhci_delete_urb(urb);
-
- xhci_call_completion(urb);
- }
- }
-
- return 0;
-}
-
-static void xhci_call_completion(struct urb *urb)
-{
- struct urb_priv *urbp;
- struct usb_device *dev = urb->dev;
- int is_ring = 0, killed, resubmit_interrupt, status;
- struct urb *nurb;
- unsigned long flags;
-
- spin_lock_irqsave(&urb->lock, flags);
-
- urbp = (struct urb_priv *)urb->hcpriv;
- if (!urbp || !urb->dev) {
- spin_unlock_irqrestore(&urb->lock, flags);
- return;
- }
-
- killed = (urb->status == -ENOENT || urb->status == -ECONNABORTED ||
- urb->status == -ECONNRESET);
- resubmit_interrupt = (usb_pipetype(urb->pipe) == PIPE_INTERRUPT &&
- urb->interval);
-
- nurb = urb->next;
- if (nurb && !killed) {
- int count = 0;
-
- while (nurb && nurb != urb && count < MAX_URB_LOOP) {
- if (nurb->status == -ENOENT ||
- nurb->status == -ECONNABORTED ||
- nurb->status == -ECONNRESET) {
- killed = 1;
- break;
- }
-
- nurb = nurb->next;
- count++;
- }
-
- if (count == MAX_URB_LOOP)
- err("xhci_call_completion: too many linked URB's, loop?
(first loop)");
-
- /* Check to see if chain is a ring */
- is_ring = (nurb == urb);
- }
-
- status = urbp->status;
- if (!resubmit_interrupt || killed)
- /* We don't need urb_priv anymore */
- xhci_destroy_urb_priv(urb);
-
- if (!killed)
- urb->status = status;
-
- spin_unlock_irqrestore(&urb->lock, flags);
-
- if (urb->complete)
- urb->complete(urb);
-
- if (resubmit_interrupt)
- /* Recheck the status. The completion handler may have */
- /* unlinked the resubmitting interrupt URB */
- killed = (urb->status == -ENOENT ||
- urb->status == -ECONNABORTED ||
- urb->status == -ECONNRESET);
-
- if (resubmit_interrupt && !killed) {
- if ( urb->dev != xhci->rh.dev )
- xhci_queue_req(urb); /* XXX What if this fails? */
- /* Don't need to resubmit URBs for the virtual root dev. */
- } else {
- if (is_ring && !killed) {
- urb->dev = dev;
- xhci_submit_urb(urb);
- } else {
- /* We decrement the usage count after we're done */
- /* with everything */
- usb_dec_dev_use(dev);
- }
- }
-}
-
-static void xhci_finish_completion(void)
-{
- struct list_head *tmp, *head;
- unsigned long flags;
-
- spin_lock_irqsave(&xhci->complete_list_lock, flags);
- head = &xhci->complete_list;
- tmp = head->next;
- while (tmp != head) {
- struct urb_priv *urbp = list_entry(tmp, struct urb_priv,
- complete_list);
- struct urb *urb = urbp->urb;
-
- list_del_init(&urbp->complete_list);
- spin_unlock_irqrestore(&xhci->complete_list_lock, flags);
-
- xhci_call_completion(urb);
-
- spin_lock_irqsave(&xhci->complete_list_lock, flags);
- head = &xhci->complete_list;
- tmp = head->next;
- }
- spin_unlock_irqrestore(&xhci->complete_list_lock, flags);
-}
-
-static struct usb_operations xhci_device_operations = {
- .allocate = xhci_do_nothing_dev,
- .deallocate = xhci_do_nothing_dev,
- /* It doesn't look like any drivers actually care what the frame number
- * is at the moment! If necessary, we could approximate the current
- * frame nubmer by passing it from the backend in response messages. */
- .get_frame_number = NULL,
- .submit_urb = xhci_submit_urb,
- .unlink_urb = xhci_unlink_urb
-};
-
-/******************************************************************************
- * VIRTUAL ROOT HUB EMULATION
- */
-
-static __u8 root_hub_dev_des[] =
-{
- 0x12, /* __u8 bLength; */
- 0x01, /* __u8 bDescriptorType; Device */
- 0x00, /* __u16 bcdUSB; v1.0 */
- 0x01,
- 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
- 0x00, /* __u8 bDeviceSubClass; */
- 0x00, /* __u8 bDeviceProtocol; */
- 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
- 0x00, /* __u16 idVendor; */
- 0x00,
- 0x00, /* __u16 idProduct; */
- 0x00,
- 0x00, /* __u16 bcdDevice; */
- 0x00,
- 0x00, /* __u8 iManufacturer; */
- 0x02, /* __u8 iProduct; */
- 0x01, /* __u8 iSerialNumber; */
- 0x01 /* __u8 bNumConfigurations; */
-};
-
-
-/* Configuration descriptor */
-static __u8 root_hub_config_des[] =
-{
- 0x09, /* __u8 bLength; */
- 0x02, /* __u8 bDescriptorType; Configuration */
- 0x19, /* __u16 wTotalLength; */
- 0x00,
- 0x01, /* __u8 bNumInterfaces; */
- 0x01, /* __u8 bConfigurationValue; */
- 0x00, /* __u8 iConfiguration; */
- 0x40, /* __u8 bmAttributes;
- Bit 7: Bus-powered, 6: Self-powered,
- Bit 5 Remote-wakeup, 4..0: resvd */
- 0x00, /* __u8 MaxPower; */
-
- /* interface */
- 0x09, /* __u8 if_bLength; */
- 0x04, /* __u8 if_bDescriptorType; Interface */
- 0x00, /* __u8 if_bInterfaceNumber; */
- 0x00, /* __u8 if_bAlternateSetting; */
- 0x01, /* __u8 if_bNumEndpoints; */
- 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
- 0x00, /* __u8 if_bInterfaceSubClass; */
- 0x00, /* __u8 if_bInterfaceProtocol; */
- 0x00, /* __u8 if_iInterface; */
-
- /* endpoint */
- 0x07, /* __u8 ep_bLength; */
- 0x05, /* __u8 ep_bDescriptorType; Endpoint */
- 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
- 0x03, /* __u8 ep_bmAttributes; Interrupt */
- 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */
- 0x00,
- 0xff /* __u8 ep_bInterval; 255 ms */
-};
-
-static __u8 root_hub_hub_des[] =
-{
- 0x09, /* __u8 bLength; */
- 0x29, /* __u8 bDescriptorType; Hub-descriptor */
- 0x02, /* __u8 bNbrPorts; */
- 0x00, /* __u16 wHubCharacteristics; */
- 0x00,
- 0x01, /* __u8 bPwrOn2pwrGood; 2ms */
- 0x00, /* __u8 bHubContrCurrent; 0 mA */
- 0x00, /* __u8 DeviceRemovable; *** 7 Ports max ***
*/
- 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max ***
*/
-};
-
-/* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */
-static int rh_send_irq(struct urb *urb)
-{
- struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
- xhci_port_t *ports = xhci->rh.ports;
- unsigned long flags;
- int i, len = 1;
- __u16 data = 0;
-
- spin_lock_irqsave(&urb->lock, flags);
- for (i = 0; i < xhci->rh.numports; i++) {
- /* Set a bit if anything at all has changed on the port, as per
- * USB spec 11.12 */
- data |= (ports[i].cs_chg || ports[i].pe_chg )
- ? (1 << (i + 1))
- : 0;
-
- len = (i + 1) / 8 + 1;
- }
-
- *(__u16 *) urb->transfer_buffer = cpu_to_le16(data);
- urb->actual_length = len;
- urbp->status = 0;
-
- spin_unlock_irqrestore(&urb->lock, flags);
-
- if ((data > 0) && (xhci->rh.send != 0)) {
- dbg("root-hub INT complete: data: %x", data);
- xhci_call_completion(urb);
- }
-
- return 0;
-}
-
-/* Virtual Root Hub INTs are polled by this timer every "interval" ms */
-static int rh_init_int_timer(struct urb *urb);
-
-static void rh_int_timer_do(unsigned long ptr)
-{
- struct urb *urb = (struct urb *)ptr;
- struct list_head list, *tmp, *head;
- unsigned long flags;
- int i;
-
- for ( i = 0; i < xhci->rh.numports; i++)
- xhci_queue_probe(i);
-
- if (xhci->rh.send)
- rh_send_irq(urb);
-
- INIT_LIST_HEAD(&list);
-
- spin_lock_irqsave(&xhci->urb_list_lock, flags);
- head = &xhci->urb_list;
- tmp = head->next;
- while (tmp != head) {
- struct urb *u = list_entry(tmp, struct urb, urb_list);
- struct urb_priv *up = (struct urb_priv *)u->hcpriv;
-
- tmp = tmp->next;
-
- spin_lock(&u->lock);
-
- /* Check if the URB timed out */
- if (u->timeout && time_after_eq(jiffies,
- up->inserttime + u->timeout)) {
- list_del(&u->urb_list);
- list_add_tail(&u->urb_list, &list);
- }
-
- spin_unlock(&u->lock);
- }
- spin_unlock_irqrestore(&xhci->urb_list_lock, flags);
-
- head = &list;
- tmp = head->next;
- while (tmp != head) {
- struct urb *u = list_entry(tmp, struct urb, urb_list);
-
- tmp = tmp->next;
-
- u->transfer_flags |= USB_ASYNC_UNLINK | USB_TIMEOUT_KILLED;
- xhci_unlink_urb(u);
- }
-
- rh_init_int_timer(urb);
-}
-
-/* Root Hub INTs are polled by this timer */
-static int rh_init_int_timer(struct urb *urb)
-{
- xhci->rh.interval = urb->interval;
- init_timer(&xhci->rh.rh_int_timer);
- xhci->rh.rh_int_timer.function = rh_int_timer_do;
- xhci->rh.rh_int_timer.data = (unsigned long)urb;
- xhci->rh.rh_int_timer.expires = jiffies
- + (HZ * (urb->interval < 30 ? 30 : urb->interval)) / 1000;
- add_timer(&xhci->rh.rh_int_timer);
-
- return 0;
-}
-
-#define OK(x) len = (x); break
-
-/* Root Hub Control Pipe */
-static int rh_submit_urb(struct urb *urb)
-{
- unsigned int pipe = urb->pipe;
- struct usb_ctrlrequest *cmd =
- (struct usb_ctrlrequest *)urb->setup_packet;
- void *data = urb->transfer_buffer;
- int leni = urb->transfer_buffer_length;
- int len = 0;
- xhci_port_t *status;
- int stat = 0;
- int i;
- int retstatus;
- unsigned long flags;
-
- __u16 cstatus;
- __u16 bmRType_bReq;
- __u16 wValue;
- __u16 wIndex;
- __u16 wLength;
-
- if (usb_pipetype(pipe) == PIPE_INTERRUPT) {
- xhci->rh.urb = urb;
- xhci->rh.send = 1;
- xhci->rh.interval = urb->interval;
- rh_init_int_timer(urb);
-
- return -EINPROGRESS;
- }
-
- bmRType_bReq = cmd->bRequestType | cmd->bRequest << 8;
- wValue = le16_to_cpu(cmd->wValue);
- wIndex = le16_to_cpu(cmd->wIndex);
- wLength = le16_to_cpu(cmd->wLength);
-
- for (i = 0; i < 8; i++)
- xhci->rh.c_p_r[i] = 0;
-
- status = &xhci->rh.ports[wIndex - 1];
-
- spin_lock_irqsave(&xhci->rh.port_state_lock, flags);
-
- switch (bmRType_bReq) {
- /* Request Destination:
- without flags: Device,
- RH_INTERFACE: interface,
- RH_ENDPOINT: endpoint,
- RH_CLASS means HUB here,
- RH_OTHER | RH_CLASS almost ever means HUB_PORT here
- */
-
- case RH_GET_STATUS:
- *(__u16 *)data = cpu_to_le16(1);
- OK(2);
- case RH_GET_STATUS | RH_INTERFACE:
- *(__u16 *)data = cpu_to_le16(0);
- OK(2);
- case RH_GET_STATUS | RH_ENDPOINT:
- *(__u16 *)data = cpu_to_le16(0);
- OK(2);
- case RH_GET_STATUS | RH_CLASS:
- *(__u32 *)data = cpu_to_le32(0);
- OK(4); /* hub power */
- case RH_GET_STATUS | RH_OTHER | RH_CLASS:
- cstatus = (status->cs_chg) |
- (status->pe_chg << 1) |
- (xhci->rh.c_p_r[wIndex - 1] << 4);
- retstatus = (status->cs) |
- (status->pe << 1) |
- (status->susp << 2) |
- (1 << 8) | /* power on */
- (status->lsda << 9);
- *(__u16 *)data = cpu_to_le16(retstatus);
- *(__u16 *)(data + 2) = cpu_to_le16(cstatus);
- OK(4);
- case RH_CLEAR_FEATURE | RH_ENDPOINT:
- switch (wValue) {
- case RH_ENDPOINT_STALL:
- OK(0);
- }
- break;
- case RH_CLEAR_FEATURE | RH_CLASS:
- switch (wValue) {
- case RH_C_HUB_OVER_CURRENT:
- OK(0); /* hub power over current */
- }
- break;
- case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
- switch (wValue) {
- case RH_PORT_ENABLE:
- status->pe = 0;
- OK(0);
- case RH_PORT_SUSPEND:
- status->susp = 0;
- OK(0);
- case RH_PORT_POWER:
- OK(0); /* port power */
- case RH_C_PORT_CONNECTION:
- status->cs_chg = 0;
- OK(0);
- case RH_C_PORT_ENABLE:
- status->pe_chg = 0;
- OK(0);
- case RH_C_PORT_SUSPEND:
- /*** WR_RH_PORTSTAT(RH_PS_PSSC); */
- OK(0);
- case RH_C_PORT_OVER_CURRENT:
- OK(0); /* port power over current */
- case RH_C_PORT_RESET:
- xhci->rh.c_p_r[wIndex - 1] = 0;
- OK(0);
- }
- break;
- case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
- switch (wValue) {
- case RH_PORT_SUSPEND:
- status->susp = 1;
- OK(0);
- case RH_PORT_RESET:
- {
- int ret;
- xhci->rh.c_p_r[wIndex - 1] = 1;
- status->pr = 0;
- status->pe = 1;
- ret = xhci_port_reset(wIndex - 1);
- /* XXX MAW: should probably cancel queued transfers
during reset... *\/ */
- if ( ret == 0 ) { OK(0); }
- else { return ret; }
- }
- break;
- case RH_PORT_POWER:
- OK(0); /* port power ** */
- case RH_PORT_ENABLE:
- status->pe = 1;
- OK(0);
- }
- break;
- case RH_SET_ADDRESS:
- xhci->rh.devnum = wValue;
- OK(0);
- case RH_GET_DESCRIPTOR:
- switch ((wValue & 0xff00) >> 8) {
- case 0x01: /* device descriptor */
- len = min_t(unsigned int, leni,
- min_t(unsigned int,
- sizeof(root_hub_dev_des), wLength));
- memcpy(data, root_hub_dev_des, len);
- OK(len);
- case 0x02: /* configuration descriptor */
- len = min_t(unsigned int, leni,
- min_t(unsigned int,
- sizeof(root_hub_config_des), wLength));
- memcpy (data, root_hub_config_des, len);
- OK(len);
- case 0x03: /* string descriptors */
- len = usb_root_hub_string (wValue & 0xff,
- 0, "XHCI-alt",
- data, wLength);
- if (len > 0) {
- OK(min_t(int, leni, len));
- } else
- stat = -EPIPE;
- }
- break;
- case RH_GET_DESCRIPTOR | RH_CLASS:
- root_hub_hub_des[2] = xhci->rh.numports;
- len = min_t(unsigned int, leni,
- min_t(unsigned int, sizeof(root_hub_hub_des),
wLength));
- memcpy(data, root_hub_hub_des, len);
- OK(len);
- case RH_GET_CONFIGURATION:
- *(__u8 *)data = 0x01;
- OK(1);
- case RH_SET_CONFIGURATION:
- OK(0);
- case RH_GET_INTERFACE | RH_INTERFACE:
- *(__u8 *)data = 0x00;
- OK(1);
- case RH_SET_INTERFACE | RH_INTERFACE:
- OK(0);
- default:
- stat = -EPIPE;
- }
-
- spin_unlock_irqrestore(&xhci->rh.port_state_lock, flags);
-
- urb->actual_length = len;
-
- return stat;
-}
-
-/*
- * MUST be called with urb->lock acquired
- */
-static int rh_unlink_urb(struct urb *urb)
-{
- if (xhci->rh.urb == urb) {
- urb->status = -ENOENT;
- xhci->rh.send = 0;
- xhci->rh.urb = NULL;
- del_timer(&xhci->rh.rh_int_timer);
- }
- return 0;
-}
-
-/******************************************************************************
- * CONTROL PLANE FUNCTIONALITY
- */
-
-/**
- * alloc_xhci - initialise a new virtual root hub for a new USB device channel
- */
-static int alloc_xhci(void)
-{
- int retval;
- struct usb_bus *bus;
-
- retval = -EBUSY;
-
- xhci = kmalloc(sizeof(*xhci), GFP_KERNEL);
- if (!xhci) {
- err("couldn't allocate xhci structure");
- retval = -ENOMEM;
- goto err_alloc_xhci;
- }
-
- xhci->state = USBIF_STATE_CLOSED;
-
- spin_lock_init(&xhci->urb_list_lock);
- INIT_LIST_HEAD(&xhci->urb_list);
-
- spin_lock_init(&xhci->complete_list_lock);
- INIT_LIST_HEAD(&xhci->complete_list);
-
- spin_lock_init(&xhci->frame_list_lock);
-
- bus = usb_alloc_bus(&xhci_device_operations);
-
- if (!bus) {
- err("unable to allocate bus");
- goto err_alloc_bus;
- }
-
- xhci->bus = bus;
- bus->bus_name = "XHCI";
- bus->hcpriv = xhci;
-
- usb_register_bus(xhci->bus);
-
- /* Initialize the root hub */
-
- xhci->rh.numports = 0;
-
- xhci->bus->root_hub = xhci->rh.dev = usb_alloc_dev(NULL, xhci->bus);
- if (!xhci->rh.dev) {
- err("unable to allocate root hub");
- goto err_alloc_root_hub;
- }
-
- xhci->state = 0;
-
- return 0;
-
-/*
- * error exits:
- */
-err_alloc_root_hub:
- usb_deregister_bus(xhci->bus);
- usb_free_bus(xhci->bus);
- xhci->bus = NULL;
-
-err_alloc_bus:
- kfree(xhci);
-
-err_alloc_xhci:
- return retval;
-}
-
-/**
- * usbif_status_change - deal with an incoming USB_INTERFACE_STATUS_ message
- */
-static void usbif_status_change(usbif_fe_interface_status_changed_t *status)
-{
- ctrl_msg_t cmsg;
- usbif_fe_interface_connect_t up;
- long rc;
- usbif_sring_t *sring;
-
- switch ( status->status )
- {
- case USBIF_INTERFACE_STATUS_DESTROYED:
- printk(KERN_WARNING "Unexpected usbif-DESTROYED message in state %d\n",
- xhci->state);
- break;
-
- case USBIF_INTERFACE_STATUS_DISCONNECTED:
- if ( xhci->state != USBIF_STATE_CLOSED )
- {
- printk(KERN_WARNING "Unexpected usbif-DISCONNECTED message"
- " in state %d\n", xhci->state);
- break;
- /* Not bothering to do recovery here for now. Keep things
- * simple. */
-
- spin_lock_irq(&xhci->ring_lock);
-
- /* Clean up resources. */
- free_page((unsigned long)xhci->usb_ring.sring);
- unbind_evtchn_from_irqhandler(xhci->evtchn, xhci);
-
- /* Plug the ring. */
- xhci->recovery = 1;
- wmb();
-
- spin_unlock_irq(&xhci->ring_lock);
- }
-
- /* Move from CLOSED to DISCONNECTED state. */
- sring = (usbif_sring_t *)__get_free_page(GFP_KERNEL);
- SHARED_RING_INIT(sring);
- FRONT_RING_INIT(&xhci->usb_ring, sring, PAGE_SIZE);
- xhci->state = USBIF_STATE_DISCONNECTED;
-
- /* Construct an interface-CONNECT message for the domain controller. */
- cmsg.type = CMSG_USBIF_FE;
- cmsg.subtype = CMSG_USBIF_FE_INTERFACE_CONNECT;
- cmsg.length = sizeof(usbif_fe_interface_connect_t);
- up.shmem_frame = virt_to_mfn(sring);
- memcpy(cmsg.msg, &up, sizeof(up));
-
- /* Tell the controller to bring up the interface. */
- ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
- break;
-
- case USBIF_INTERFACE_STATUS_CONNECTED:
- if ( xhci->state == USBIF_STATE_CLOSED )
- {
- printk(KERN_WARNING "Unexpected usbif-CONNECTED message"
- " in state %d\n", xhci->state);
- break;
- }
-
- xhci->evtchn = status->evtchn;
- xhci->bandwidth = status->bandwidth;
- xhci->rh.numports = status->num_ports;
-
- xhci->rh.ports = kmalloc (sizeof(xhci_port_t) * xhci->rh.numports,
GFP_KERNEL);
-
- if ( xhci->rh.ports == NULL )
- goto alloc_ports_nomem;
-
- memset(xhci->rh.ports, 0, sizeof(xhci_port_t) * xhci->rh.numports);
-
- usb_connect(xhci->rh.dev);
-
- if (usb_new_device(xhci->rh.dev) != 0) {
- err("unable to start root hub");
- }
-
- /* Allocate the appropriate USB bandwidth here... Need to
- * somehow know what the total available is thought to be so we
- * can calculate the reservation correctly. */
- usb_claim_bandwidth(xhci->rh.dev, xhci->rh.urb,
- 1000 - xhci->bandwidth, 0);
-
- if ( (rc = bind_evtchn_to_irqhandler(xhci->evtchn, xhci_interrupt,
- SA_SAMPLE_RANDOM, "usbif", xhci)) )
- printk(KERN_ALERT"usbfront request_irq failed (%ld)\n",rc);
-
- DPRINTK(KERN_INFO __FILE__
- ": USB XHCI: SHM at %p (0x%lx), EVTCHN %d\n",
- xhci->usb_ring.sring, virt_to_mfn(xhci->usbif),
- xhci->evtchn);
-
- xhci->state = USBIF_STATE_CONNECTED;
-
- break;
-
- default:
- printk(KERN_WARNING "Status change to unknown value %d\n",
- status->status);
- break;
- }
-
- return;
-
- alloc_ports_nomem:
- printk(KERN_WARNING "Failed to allocate port memory, XHCI failed to
connect.\n");
- return;
-}
-
-/**
- * usbif_ctrlif_rx - demux control messages by subtype
- */
-static void usbif_ctrlif_rx(ctrl_msg_t *msg, unsigned long id)
-{
- switch ( msg->subtype )
- {
- case CMSG_USBIF_FE_INTERFACE_STATUS_CHANGED:
- usbif_status_change((usbif_fe_interface_status_changed_t *)
- &msg->msg[0]);
- break;
-
- /* New interface...? */
- default:
- msg->length = 0;
- break;
- }
-
- ctrl_if_send_response(msg);
-}
-
-static void send_driver_up(void)
-{
- control_msg_t cmsg;
- usbif_fe_interface_status_changed_t st;
-
- /* Send a driver-UP notification to the domain controller. */
- cmsg.type = CMSG_USBIF_FE;
- cmsg.subtype = CMSG_USBIF_FE_DRIVER_STATUS_CHANGED;
- cmsg.length = sizeof(usbif_fe_driver_status_changed_t);
- st.status = USBIF_DRIVER_STATUS_UP;
- memcpy(cmsg.msg, &st, sizeof(st));
- ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
-}
-
-void usbif_resume(void)
-{
- int i;
-
- /* Fake disconnection on all virtual USB ports (suspending / migrating
- * will destroy hard state associated will the USB devices anyhow). */
- /* No need to lock here. */
- for ( i = 0; i < xhci->rh.numports; i++ )
- {
- xhci->rh.ports[i].cs = 0;
- xhci->rh.ports[i].cs_chg = 1;
- xhci->rh.ports[i].pe = 0;
- }
-
- send_driver_up();
-}
-
-static int __init xhci_hcd_init(void)
-{
- int retval = -ENOMEM, i;
-
- if ( (xen_start_info->flags & SIF_INITDOMAIN) ||
- (xen_start_info->flags & SIF_USB_BE_DOMAIN) )
- return 0;
-
- info(DRIVER_DESC " " DRIVER_VERSION);
-
- if (debug) {
- errbuf = kmalloc(ERRBUF_LEN, GFP_KERNEL);
- if (!errbuf)
- goto errbuf_failed;
- }
-
- xhci_up_cachep = kmem_cache_create("xhci_urb_priv",
- sizeof(struct urb_priv), 0, 0, NULL, NULL);
- if (!xhci_up_cachep)
- goto up_failed;
-
- /* Let the domain controller know we're here. For now we wait until
- * connection, as for the block and net drivers. This is only strictly
- * necessary if we're going to boot off a USB device. */
- printk(KERN_INFO "Initialising Xen virtual USB hub\n");
-
- (void)ctrl_if_register_receiver(CMSG_USBIF_FE, usbif_ctrlif_rx,
- CALLBACK_IN_BLOCKING_CONTEXT);
-
- alloc_xhci();
-
- send_driver_up();
-
- /*
- * We should read 'nr_interfaces' from response message and wait
- * for notifications before proceeding. For now we assume that we
- * will be notified of exactly one interface.
- */
- for ( i=0; (xhci->state != USBIF_STATE_CONNECTED) && (i < 10*HZ); i++ )
- {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(1);
- }
-
- if (xhci->state != USBIF_STATE_CONNECTED)
- printk(KERN_WARNING "Timeout connecting USB frontend driver!\n");
-
- return 0;
-
-up_failed:
- if (errbuf)
- kfree(errbuf);
-
-errbuf_failed:
- return retval;
-}
-
-module_init(xhci_hcd_init);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL");
-
diff -r eba5afe9aa37 -r 10759a44ce3b
linux-2.6-xen-sparse/drivers/xen/usbfront/xhci.h
--- a/linux-2.6-xen-sparse/drivers/xen/usbfront/xhci.h Thu Sep 22 15:05:44 2005
+++ /dev/null Thu Sep 22 15:12:14 2005
@@ -1,182 +0,0 @@
-/******************************************************************************
- * xhci.h
- *
- * Private definitions for the Xen Virtual USB Controller. Based on
- * drivers/usb/host/uhci.h from Linux. Copyright for the imported content is
- * retained by the original authors.
- *
- * Modifications are:
- * Copyright (C) 2004 Intel Research Cambridge
- * Copyright (C) 2004, 2005 Mark Williamson
- */
-
-#ifndef __LINUX_XHCI_H
-#define __LINUX_XHCI_H
-
-#include <linux/list.h>
-#include <linux/usb.h>
-#include <asm-xen/xen-public/io/usbif.h>
-#include <linux/spinlock.h>
-
-/* xhci_port_t - current known state of a virtual hub ports */
-typedef struct {
- unsigned int cs :1; /* Connection status. */
- unsigned int cs_chg :1; /* Connection status change. */
- unsigned int pe :1; /* Port enable. */
- unsigned int pe_chg :1; /* Port enable change. */
- unsigned int susp :1; /* Suspended. */
- unsigned int lsda :1; /* Low speed device attached. */
- unsigned int pr :1; /* Port reset. */
-} xhci_port_t;
-
-/* struct virt_root_hub - state related to the virtual root hub */
-struct virt_root_hub {
- struct usb_device *dev;
- int devnum; /* Address of Root Hub endpoint */
- struct urb *urb;
- void *int_addr;
- int send;
- int interval;
- int numports;
- int c_p_r[8];
- struct timer_list rh_int_timer;
- spinlock_t port_state_lock;
- xhci_port_t *ports;
-};
-
-/* struct xhci - contains the state associated with a single USB interface */
-struct xhci {
-
-#ifdef CONFIG_PROC_FS
- /* procfs */
- int num;
- struct proc_dir_entry *proc_entry;
-#endif
-
- int evtchn; /* Interdom channel to backend */
- enum {
- USBIF_STATE_CONNECTED = 2,
- USBIF_STATE_DISCONNECTED = 1,
- USBIF_STATE_CLOSED = 0
- } state; /* State of this USB interface */
- unsigned long recovery; /* boolean recovery in progress flag */
-
- unsigned long bandwidth;
-
- struct usb_bus *bus;
-
- /* Main list of URB's currently controlled by this HC */
- spinlock_t urb_list_lock;
- struct list_head urb_list; /* P: xhci->urb_list_lock */
-
- /* List of URB's awaiting completion callback */
- spinlock_t complete_list_lock;
- struct list_head complete_list; /* P: xhci->complete_list_lock
*/
-
- struct virt_root_hub rh; /* private data of the virtual root hub
*/
-
- spinlock_t ring_lock;
- usbif_front_ring_t usb_ring;
-
- int awaiting_reset;
-};
-
-/* per-URB private data structure for the host controller */
-struct urb_priv {
- struct urb *urb;
- usbif_iso_t *schedule;
- struct usb_device *dev;
-
- int in_progress : 1; /* QH was queued (not linked in) */
- int short_control_packet : 1; /* If we get a short packet during */
- /* a control transfer, retrigger */
- /* the status phase */
-
- int status; /* Final status */
-
- unsigned long inserttime; /* In jiffies */
-
- struct list_head complete_list; /* P: xhci->complete_list_lock */
-};
-
-/*
- * Locking in xhci.c
- *
- * spinlocks are used extensively to protect the many lists and data
- * structures we have. It's not that pretty, but it's necessary. We
- * need to be done with all of the locks (except complete_list_lock) when
- * we call urb->complete. I've tried to make it simple enough so I don't
- * have to spend hours racking my brain trying to figure out if the
- * locking is safe.
- *
- * Here's the safe locking order to prevent deadlocks:
- *
- * #1 xhci->urb_list_lock
- * #2 urb->lock
- * #3 xhci->urb_remove_list_lock
- * #4 xhci->complete_list_lock
- *
- * If you're going to grab 2 or more locks at once, ALWAYS grab the lock
- * at the lowest level FIRST and NEVER grab locks at the same level at the
- * same time.
- *
- * So, if you need xhci->urb_list_lock, grab it before you grab urb->lock
- */
-
-/* -------------------------------------------------------------------------
- Virtual Root HUB
- ------------------------------------------------------------------------- */
-/* destination of request */
-#define RH_DEVICE 0x00
-#define RH_INTERFACE 0x01
-#define RH_ENDPOINT 0x02
-#define RH_OTHER 0x03
-
-#define RH_CLASS 0x20
-#define RH_VENDOR 0x40
-
-/* Requests: bRequest << 8 | bmRequestType */
-#define RH_GET_STATUS 0x0080
-#define RH_CLEAR_FEATURE 0x0100
-#define RH_SET_FEATURE 0x0300
-#define RH_SET_ADDRESS 0x0500
-#define RH_GET_DESCRIPTOR 0x0680
-#define RH_SET_DESCRIPTOR 0x0700
-#define RH_GET_CONFIGURATION 0x0880
-#define RH_SET_CONFIGURATION 0x0900
-#define RH_GET_STATE 0x0280
-#define RH_GET_INTERFACE 0x0A80
-#define RH_SET_INTERFACE 0x0B00
-#define RH_SYNC_FRAME 0x0C80
-/* Our Vendor Specific Request */
-#define RH_SET_EP 0x2000
-
-/* Hub port features */
-#define RH_PORT_CONNECTION 0x00
-#define RH_PORT_ENABLE 0x01
-#define RH_PORT_SUSPEND 0x02
-#define RH_PORT_OVER_CURRENT 0x03
-#define RH_PORT_RESET 0x04
-#define RH_PORT_POWER 0x08
-#define RH_PORT_LOW_SPEED 0x09
-#define RH_C_PORT_CONNECTION 0x10
-#define RH_C_PORT_ENABLE 0x11
-#define RH_C_PORT_SUSPEND 0x12
-#define RH_C_PORT_OVER_CURRENT 0x13
-#define RH_C_PORT_RESET 0x14
-
-/* Hub features */
-#define RH_C_HUB_LOCAL_POWER 0x00
-#define RH_C_HUB_OVER_CURRENT 0x01
-#define RH_DEVICE_REMOTE_WAKEUP 0x00
-#define RH_ENDPOINT_STALL 0x01
-
-/* Our Vendor Specific feature */
-#define RH_REMOVE_EP 0x00
-
-#define RH_ACK 0x01
-#define RH_REQ_ERR -1
-#define RH_NACK 0x00
-
-#endif
-
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|