ia64/linux-2.6.18-xen.hg

annotate drivers/xen/usbback/interface.c @ 829:f799db0570f2

PVUSB: backend driver

Signed-off-by: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Mar 18 11:43:24 2009 +0000 (2009-03-18)
parents
children 4c7eb2e71e9d
rev   line source
keir@829 1 /*
keir@829 2 * interface.c
keir@829 3 *
keir@829 4 * Xen USB backend interface management.
keir@829 5 *
keir@829 6 * Copyright (C) 2009, FUJITSU LABORATORIES LTD.
keir@829 7 * Author: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
keir@829 8 *
keir@829 9 * This program is free software; you can redistribute it and/or modify
keir@829 10 * it under the terms of the GNU General Public License as published by
keir@829 11 * the Free Software Foundation; either version 2 of the License, or
keir@829 12 * (at your option) any later version.
keir@829 13 *
keir@829 14 * This program is distributed in the hope that it will be useful,
keir@829 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
keir@829 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
keir@829 17 * GNU General Public License for more details.
keir@829 18 *
keir@829 19 * You should have received a copy of the GNU General Public License
keir@829 20 * along with this program; if not, see <http://www.gnu.org/licenses/>.
keir@829 21 *
keir@829 22 * or,
keir@829 23 *
keir@829 24 * When distributed separately from the Linux kernel or incorporated into
keir@829 25 * other software packages, subject to the following license:
keir@829 26 *
keir@829 27 * Permission is hereby granted, free of charge, to any person obtaining a copy
keir@829 28 * of this software and associated documentation files (the "Software"), to
keir@829 29 * deal in the Software without restriction, including without limitation the
keir@829 30 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
keir@829 31 * sell copies of the Software, and to permit persons to whom the Software is
keir@829 32 * furnished to do so, subject to the following conditions:
keir@829 33 *
keir@829 34 * The above copyright notice and this permission notice shall be included in
keir@829 35 * all copies or substantial portions of the Software.
keir@829 36 *
keir@829 37 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
keir@829 38 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
keir@829 39 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
keir@829 40 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
keir@829 41 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
keir@829 42 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
keir@829 43 * DEALINGS IN THE SOFTWARE.
keir@829 44 */
keir@829 45
keir@829 46 #include "usbback.h"
keir@829 47
keir@829 48 static LIST_HEAD(usbif_list);
keir@829 49 static DEFINE_SPINLOCK(usbif_list_lock);
keir@829 50
keir@829 51 usbif_t *find_usbif(int dom_id, int dev_id)
keir@829 52 {
keir@829 53 usbif_t *usbif;
keir@829 54 int found = 0;
keir@829 55 unsigned long flags;
keir@829 56
keir@829 57 spin_lock_irqsave(&usbif_list_lock, flags);
keir@829 58 list_for_each_entry(usbif, &usbif_list, usbif_list) {
keir@829 59 if (usbif->domid == dom_id
keir@829 60 && usbif->handle == dev_id) {
keir@829 61 found = 1;
keir@829 62 break;
keir@829 63 }
keir@829 64 }
keir@829 65 spin_unlock_irqrestore(&usbif_list_lock, flags);
keir@829 66
keir@829 67 if (found)
keir@829 68 return usbif;
keir@829 69
keir@829 70 return NULL;
keir@829 71 }
keir@829 72
keir@829 73 usbif_t *usbif_alloc(domid_t domid, unsigned int handle)
keir@829 74 {
keir@829 75 usbif_t *usbif;
keir@829 76 unsigned long flags;
keir@829 77 int i;
keir@829 78
keir@829 79 usbif = kzalloc(sizeof(usbif_t), GFP_KERNEL);
keir@829 80 if (!usbif)
keir@829 81 return NULL;
keir@829 82
keir@829 83 usbif->domid = domid;
keir@829 84 usbif->handle = handle;
keir@829 85 spin_lock_init(&usbif->ring_lock);
keir@829 86 atomic_set(&usbif->refcnt, 0);
keir@829 87 init_waitqueue_head(&usbif->wq);
keir@829 88 init_waitqueue_head(&usbif->waiting_to_free);
keir@829 89 spin_lock_init(&usbif->plug_lock);
keir@829 90 INIT_LIST_HEAD(&usbif->plugged_devices);
keir@829 91 spin_lock_init(&usbif->addr_lock);
keir@829 92 for (i = 0; i < USB_DEV_ADDR_SIZE; i++) {
keir@829 93 usbif->addr_table[i] = NULL;
keir@829 94 }
keir@829 95
keir@829 96 spin_lock_irqsave(&usbif_list_lock, flags);
keir@829 97 list_add(&usbif->usbif_list, &usbif_list);
keir@829 98 spin_unlock_irqrestore(&usbif_list_lock, flags);
keir@829 99
keir@829 100 return usbif;
keir@829 101 }
keir@829 102
keir@829 103 static int map_frontend_page(usbif_t *usbif, unsigned long shared_page)
keir@829 104 {
keir@829 105 struct gnttab_map_grant_ref op;
keir@829 106
keir@829 107 gnttab_set_map_op(&op, (unsigned long)usbif->ring_area->addr,
keir@829 108 GNTMAP_host_map, shared_page, usbif->domid);
keir@829 109
keir@829 110 if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
keir@829 111 BUG();
keir@829 112
keir@829 113 if (op.status) {
keir@829 114 printk(KERN_ERR "grant table operation failure\n");
keir@829 115 return op.status;
keir@829 116 }
keir@829 117
keir@829 118 usbif->shmem_ref = shared_page;
keir@829 119 usbif->shmem_handle = op.handle;
keir@829 120
keir@829 121 return 0;
keir@829 122 }
keir@829 123
keir@829 124 static void unmap_frontend_page(usbif_t *usbif)
keir@829 125 {
keir@829 126 struct gnttab_unmap_grant_ref op;
keir@829 127
keir@829 128 gnttab_set_unmap_op(&op, (unsigned long)usbif->ring_area->addr,
keir@829 129 GNTMAP_host_map, usbif->shmem_handle);
keir@829 130
keir@829 131 if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
keir@829 132 BUG();
keir@829 133 }
keir@829 134
keir@829 135 int usbif_map(usbif_t *usbif, unsigned long shared_page, unsigned int evtchn)
keir@829 136 {
keir@829 137 int err;
keir@829 138 usbif_sring_t *sring;
keir@829 139
keir@829 140 if (usbif->irq)
keir@829 141 return 0;
keir@829 142
keir@829 143 if ((usbif->ring_area = alloc_vm_area(PAGE_SIZE)) == NULL)
keir@829 144 return -ENOMEM;
keir@829 145
keir@829 146 err = map_frontend_page(usbif, shared_page);
keir@829 147 if (err) {
keir@829 148 free_vm_area(usbif->ring_area);
keir@829 149 return err;
keir@829 150 }
keir@829 151
keir@829 152 sring = (usbif_sring_t *) usbif->ring_area->addr;
keir@829 153 BACK_RING_INIT(&usbif->ring, sring, PAGE_SIZE);
keir@829 154
keir@829 155 err = bind_interdomain_evtchn_to_irqhandler(
keir@829 156 usbif->domid, evtchn, usbbk_be_int, 0, "usbif-backend", usbif);
keir@829 157 if (err < 0)
keir@829 158 {
keir@829 159 unmap_frontend_page(usbif);
keir@829 160 free_vm_area(usbif->ring_area);
keir@829 161 usbif->ring.sring = NULL;
keir@829 162 return err;
keir@829 163 }
keir@829 164 usbif->irq = err;
keir@829 165
keir@829 166 return 0;
keir@829 167 }
keir@829 168
keir@829 169 void usbif_disconnect(usbif_t *usbif)
keir@829 170 {
keir@829 171 struct usbstub *stub, *tmp;
keir@829 172 unsigned long flags;
keir@829 173
keir@829 174 if (usbif->xenusbd) {
keir@829 175 kthread_stop(usbif->xenusbd);
keir@829 176 usbif->xenusbd = NULL;
keir@829 177 }
keir@829 178
keir@829 179 spin_lock_irqsave(&usbif->plug_lock, flags);
keir@829 180 list_for_each_entry_safe(stub, tmp, &usbif->plugged_devices, plugged_list) {
keir@829 181 usbbk_unlink_urbs(stub);
keir@829 182 detach_device_without_lock(usbif, stub);
keir@829 183 }
keir@829 184 spin_unlock_irqrestore(&usbif->plug_lock, flags);
keir@829 185
keir@829 186 wait_event(usbif->waiting_to_free, atomic_read(&usbif->refcnt) == 0);
keir@829 187
keir@829 188 if (usbif->irq) {
keir@829 189 unbind_from_irqhandler(usbif->irq, usbif);
keir@829 190 usbif->irq = 0;
keir@829 191 }
keir@829 192
keir@829 193 if (usbif->ring.sring) {
keir@829 194 unmap_frontend_page(usbif);
keir@829 195 free_vm_area(usbif->ring_area);
keir@829 196 usbif->ring.sring = NULL;
keir@829 197 }
keir@829 198 }
keir@829 199
keir@829 200 void usbif_free(usbif_t *usbif)
keir@829 201 {
keir@829 202 unsigned long flags;
keir@829 203
keir@829 204 spin_lock_irqsave(&usbif_list_lock, flags);
keir@829 205 list_del(&usbif->usbif_list);
keir@829 206 spin_unlock_irqrestore(&usbif_list_lock, flags);
keir@829 207 kfree(usbif);
keir@829 208 }