summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorRichard Braun <rbraun@sceen.net>2016-09-21 00:35:26 +0200
committerRichard Braun <rbraun@sceen.net>2016-09-21 00:35:26 +0200
commit6923672268ae8e51e3cf303314fca196dc369e19 (patch)
tree1401fbb4ee3c6be84745dec814487d6d85920f02 /linux
parent39fb13e762817b814aa0fc6e49305b5c0fd0c083 (diff)
Update device drivers for highmem support
Unconditionally use bounce buffers for now. * linux/dev/glue/net.c (device_write): Unconditionally use a bounce buffer. * xen/block.c (device_write): Likewise. * xen/net.c: Include <device/ds_routines.h>. (device_write): Unconditionally use a bounce buffer.
Diffstat (limited to 'linux')
-rw-r--r--linux/dev/glue/net.c63
1 files changed, 22 insertions, 41 deletions
diff --git a/linux/dev/glue/net.c b/linux/dev/glue/net.c
index 15732737..6b9cadd5 100644
--- a/linux/dev/glue/net.c
+++ b/linux/dev/glue/net.c
@@ -428,62 +428,43 @@ device_write (void *d, ipc_port_t reply_port,
int *bytes_written)
{
unsigned char *p;
- int i, amt, skblen, s;
+ int i, s;
vm_map_copy_t copy = (vm_map_copy_t) data;
+ char *map_data;
+ vm_offset_t map_addr;
+ vm_size_t map_size;
struct net_data *nd = d;
struct linux_device *dev = nd->dev;
struct sk_buff *skb;
+ kern_return_t kr;
if (count == 0 || count > dev->mtu + dev->hard_header_len)
return D_INVALID_SIZE;
/* Allocate a sk_buff. */
- amt = PAGE_SIZE - (copy->offset & PAGE_MASK);
- skblen = (amt >= count) ? 0 : count;
- skb = dev_alloc_skb (skblen);
+ skb = dev_alloc_skb (count);
if (!skb)
return D_NO_MEMORY;
- /* Copy user data. This is only required if it spans multiple pages. */
- if (skblen == 0)
- {
- assert (copy->cpy_npages == 1);
-
- skb->copy = copy;
- skb->data = ((void *) phystokv(copy->cpy_page_list[0]->phys_addr)
- + (copy->offset & PAGE_MASK));
- skb->len = count;
- skb->head = skb->data;
- skb->tail = skb->data + skb->len;
- skb->end = skb->tail;
- }
- else
- {
- skb->len = skblen;
- skb->tail = skb->data + skblen;
- skb->end = skb->tail;
-
- memcpy (skb->data,
- ((void *) phystokv(copy->cpy_page_list[0]->phys_addr)
- + (copy->offset & PAGE_MASK)),
- amt);
- count -= amt;
- p = skb->data + amt;
- for (i = 1; count > 0 && i < copy->cpy_npages; i++)
- {
- amt = PAGE_SIZE;
- if (amt > count)
- amt = count;
- memcpy (p, (void *) phystokv(copy->cpy_page_list[i]->phys_addr), amt);
- count -= amt;
- p += amt;
- }
+ /* Map user data. */
+ kr = kmem_io_map_copyout(device_io_map, (vm_offset_t *)&map_data,
+ &map_addr, &map_size, copy, count);
- assert (count == 0);
+ if (kr) {
+ dev_kfree_skb (skb, FREE_WRITE);
+ return D_NO_MEMORY;
+ }
- vm_map_copy_discard (copy);
- }
+ /* XXX The underlying physical pages of the mapping could be highmem,
+ for which drivers require the use of a bounce buffer. */
+ memcpy (skb->data, map_data, count);
+ kmem_io_map_deallocate (device_io_map, map_addr, map_size);
+ vm_map_copy_discard (copy);
+ skb->len = count;
+ skb->head = skb->data;
+ skb->tail = skb->data + skb->len;
+ skb->end = skb->tail;
skb->dev = dev;
skb->reply = reply_port;
skb->reply_type = reply_port_type;