Date: Fri, 27 Sep 2013 11:30:51 GMT From: bguan@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r257756 - soc2013/bguan/head/sys/dev/xen/usbfront Message-ID: <201309271130.r8RBUph5016468@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: bguan Date: Fri Sep 27 11:30:51 2013 New Revision: 257756 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=257756 Log: create a thread to deal with USB request queue; get entry from the share ring; other little stuff work Modified: soc2013/bguan/head/sys/dev/xen/usbfront/usbfront.c Modified: soc2013/bguan/head/sys/dev/xen/usbfront/usbfront.c ============================================================================== --- soc2013/bguan/head/sys/dev/xen/usbfront/usbfront.c Fri Sep 27 10:47:22 2013 (r257755) +++ soc2013/bguan/head/sys/dev/xen/usbfront/usbfront.c Fri Sep 27 11:30:51 2013 (r257756) @@ -32,6 +32,7 @@ #include <sys/systm.h> #include <sys/malloc.h> #include <sys/kernel.h> +#include <sys/kthread.h> #include <vm/vm.h> #include <vm/pmap.h> @@ -81,18 +82,21 @@ #include "xenbus_if.h" +#define XENHCI_VENDORID_XEN 0x0001 -static int usbfront_probe(device_t dev); -static int usbfront_attach(device_t dev); -static int usbfront_detach(device_t dev); -static int usbfront_suspend(device_t dev); -static int usbfront_resume(device_t dev); -static int talk_to_backend(device_t dev, struct xenhci_softc *sc); -static int setup_rings(device_t dev, struct xenhci_softc *sc); -static void destroy_rings(struct xenhci_softc *sc); -static void xenhci_notify_work(struct xenhci_softc *sc); -static void xu_intr(void *xsc); -static int usbfront_connect(device_t dev); +static int usbfront_probe(device_t dev); +static int usbfront_attach(device_t dev); +static int usbfront_detach(device_t dev); +static int usbfront_suspend(device_t dev); +static int usbfront_resume(device_t dev); +static int talk_to_backend(device_t dev, struct xenhci_softc *sc); +static int setup_rings(device_t dev, struct xenhci_softc *sc); +static void destroy_rings(struct xenhci_softc *sc); +static void xenhci_thread(void *arg); +static void xenhci_notify_work(struct xenhci_softc *sc); +static void xu_int(void *xsc); +static int usbfront_connect(device_t dev); +static void usbfront_free(struct xenhci_softc *sc); #define virt_to_mfn(x) (vtomach(x) >> PAGE_SHIFT) @@ -116,7 +120,7 @@ return (ENXIO); } -/* +/** * Setup supplies the backend dir, virtual device. We place an event * channel and shared frame entries. We watch backend to wait if it's * ok. @@ -192,11 +196,20 @@ sc->xb_dev = dev; sc->rh_numports = num_ports; sc->sc_noport = num_ports; - sprintf(sc->sc_vendor, "0x%04x", pci_get_vendor(dev)); + + switch (pci_get_vendor(dev)) { + case XENHCI_VENDORID_XEN: + sprintf(sc->sc_vendor, "Xen Device"); + break; + default: + DPRINTK("host controller vendor: 0x%x\n", pci_get_vendor(dev)); + sprintf(sc->sc_vendor, "0x%04x", pci_get_vendor(dev)); + } for (i = 0; i < USB_URB_RING_SIZE; i++) { sc->shadow[i].req.id = i + 1; - sc->shadow[i].urb = NULL; + //sc->shadow[i].urb = NULL; + sc->shadow[i].xfer = NULL; } sc->shadow[USB_URB_RING_SIZE-1].req.id = 0x0fff; @@ -250,12 +263,21 @@ DPRINTK("usbfront_detach: %s removed\n", xenbus_get_node(dev)); //TODO - //usbfront_free(sc); + usbfront_free(sc); + //mtx_destroy(&sc->xb_io_lock); + + xenhci_uninit(sc); return 0; } +static void +usbfront_free(struct xenhci_softc *sc) +{ + destroy_rings(sc); +} + static int usbfront_connect(device_t dev) @@ -271,18 +293,14 @@ //hcd = info_to_hcd(info); //snprintf(name, TASK_COMM_LEN, "xenhcd.%d", sc->sc_bus.busnum); - err = talk_to_backend(dev, sc); if (err) return err; - //sc->kthread = kthread_run(xenhcd_schedule, sc, name); - //if (IS_ERR(sc->kthread)) { - // err = PTR_ERR(sc->kthread); - // sc->kthread = NULL; - // xenbus_dev_fatal(dev, err, "Error creating thread"); - // return err; - //} + //err = kproc_create(xenhci_thread, sc, NULL, 0, 0, name); + err = kproc_create(xenhci_thread, sc, NULL, 0, 0, "xenhcd"); + if (err) + return err; /* prepare ring for hotplug notification */ for (idx = 0, i = 0; i < USB_CONN_RING_SIZE; i++) { @@ -372,7 +390,9 @@ } } -/* Common code used when first setting up, and when resuming. */ +/** + * Common code used when first setting up, and when resuming. + */ static int talk_to_backend(device_t dev, struct xenhci_softc *sc) { @@ -459,7 +479,9 @@ sc->conn_ring.sring = NULL; } -/* Create shared ring, alloc event channel. */ +/** + * Create shared ring, alloc event channel. + */ static int setup_rings(device_t dev, struct xenhci_softc *sc) { @@ -484,7 +506,6 @@ //sc->urb_ring.sring = NULL; goto fail; } - sc->urb_ring_ref = err; conn_sring = (usbif_conn_sring_t *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT|M_ZERO); if (!conn_sring) { @@ -500,17 +521,15 @@ //sc->conn_ring.sring = NULL; goto fail; } - sc->conn_ring_ref = err; err = bind_listening_port_to_irqhandler(xenbus_get_otherend_id(dev), - "xu", xu_intr, sc, INTR_TYPE_BIO | INTR_MPSAFE, &sc->irq); + "xu", xu_int, sc, INTR_TYPE_BIO | INTR_MPSAFE, &sc->irq); if (err) { xenbus_dev_fatal(dev, err, "bind_listening_port_to_irqhandler"); goto fail; } - sc->irq = err; return 0; fail: @@ -518,24 +537,228 @@ return err; } +//////////////////////////////////////////////// +static inline int get_id_from_freelist(struct xenhci_softc *sc) +{ + unsigned long free; + free = sc->shadow_free; + //BUG_ON(free >= USB_URB_RING_SIZE); //???? + sc->shadow_free = sc->shadow[free].req.id; + sc->shadow[free].req.id = (unsigned int)0x0fff; /* debug */ + return free; +} + +static inline void add_id_to_freelist(struct xenhci_softc *sc, + unsigned long id) +{ + sc->shadow[id].req.id = sc->shadow_free; + //sc->shadow[id].urb = NULL; + sc->shadow[id].xfer = NULL; + sc->shadow_free = id; +} + +static void xenhci_gnttab_done(struct usb_shadow *shadow) +{ + int nr_segs = 0; + int i; + + nr_segs = shadow->req.nr_buffer_segs; + + //??? + //if (usb_pipeisoc(shadow->req.pipe)) + nr_segs += shadow->req.u.isoc.nr_frame_desc_segs; + + for (i = 0; i < nr_segs; i++) + gnttab_end_foreign_access(shadow->req.seg[i].gref, 0UL); + + shadow->req.nr_buffer_segs = 0; + shadow->req.u.isoc.nr_frame_desc_segs = 0; +} + +/* +static void xenhci_giveback_urb(struct usbfront_info *info, struct urb *urb, int status) +} +*/ + + +/** + * Get response data from the backend + */ +static int +xenhci_xfer_request_done(struct xenhci_softc *sc) +{ + usbif_urb_response_t *resp; + //struct urb *urb; + struct usb_xfer *xfer; + + RING_IDX i, rp; + uint16_t id; + int more_req = 0; + + mtx_lock(&sc->lock); + rp = sc->urb_ring.sring->rsp_prod; + //rmb();??? /* ensure we see queued responses up to "rp" */ + + for (i = sc->urb_ring.rsp_cons; i != rp; i++) { + resp = RING_GET_RESPONSE(&sc->urb_ring, i); + id = resp->id; + + if (likely(usbif_pipesubmit(sc->shadow[id].req.pipe))) { + xenhci_gnttab_done(&sc->shadow[id]); + //urb = sc->shadow[id].urb; + xfer = sc->shadow[id].xfer; + //barrier(); + //if (likely(urb)) { + + //if (urb) { + if (xfer) { + //TODO + //xfer-> + + //urb->actual_length = resp->actual_length; + //urb->error_count = resp->error_count; + //urb->start_frame = resp->start_frame; + + //barrier(); + //xenhci_giveback_urb(sc, urb, resp->status); //??? + } + } + + add_id_to_freelist(sc, id); + } + sc->urb_ring.rsp_cons = i; + + if (i != sc->urb_ring.req_prod_pvt) + RING_FINAL_CHECK_FOR_RESPONSES(&sc->urb_ring, more_req); + else + sc->urb_ring.sring->rsp_event = i + 1; + + mtx_unlock(&sc->lock); + + //cond_resched(); + + return more_req; +} + +static int +xenhci_conn_notify(struct xenhci_softc *sc) +{ + usbif_conn_response_t *res; + usbif_conn_request_t *req; + RING_IDX rc, rp; + uint16_t id; + uint8_t portnum, speed; + int more_req = 0; + int notify; + int port_changed = 0; + //unsigned long flags; + + //spin_lock_irqsave(&sc->lock, flags); + mtx_lock(&sc->lock); + + rc = sc->conn_ring.rsp_cons; + rp = sc->conn_ring.sring->rsp_prod; + rmb(); /* ensure we see queued responses up to "rp" */ + + while (rc != rp) { + res = RING_GET_RESPONSE(&sc->conn_ring, rc); + id = res->id; + portnum = res->portnum; + speed = res->speed; + sc->conn_ring.rsp_cons = ++rc; + + //rhport_connect(sc, portnum, speed); + sc->ports[portnum-1].c_connection = 1; + if (sc->ports[portnum-1].c_connection) + port_changed = 1; + + //barrier(); + + req = RING_GET_REQUEST(&sc->conn_ring, sc->conn_ring.req_prod_pvt); + req->id = id; + sc->conn_ring.req_prod_pvt++; + } + + if (rc != sc->conn_ring.req_prod_pvt) + RING_FINAL_CHECK_FOR_RESPONSES(&sc->conn_ring, more_req); + else + sc->conn_ring.sring->rsp_event = rc + 1; + + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&sc->conn_ring, notify); + if (notify) + notify_remote_via_irq(sc->irq); + + //spin_unlock_irqrestore(&sc->lock, flags); + mtx_unlock(&sc->lock); + + if (port_changed) { + //usb_hcd_poll_rh_status(sc_to_hcd(sc)); + printf("[gbtest]usb_hcd_poll_rh_status(sc_to_hcd(sc))???????????\n"); + } + //cond_resched(); + + return more_req; +} + +/** + * A thread to deal with the USB req queue. + * Get the reply data from share ring. + */ +static void +xenhci_thread(void *arg) +{ + struct xenhci_softc *sc = (struct xenhci_softc *) arg; + + for (;;) { + while(sc->waiting_resp == 0) {}; + sc->waiting_resp = 0; + + if (xenhci_xfer_request_done(sc)) + sc->waiting_resp = 1; + + if (xenhci_conn_notify(sc)) + sc->waiting_resp = 1; + +/* //mtx_lock(&xs.watch_events_lock); + //mtx_unlock(&xs.watch_events_lock); + + //??? + wait_event_interruptible( + info->wq, + info->waiting_resp || kthread_should_stop()); + info->waiting_resp = 0; + smp_mb(); + + if (xenhci_urb_request_done(sc)) + info->waiting_resp = 1; + + if (xenhci_conn_notify(sc)) + info->waiting_resp = 1; + +*/ //??? + } +} + static void xenhci_notify_work(struct xenhci_softc *sc) { printf("[gbdebug-pvusb]xenhci_notify_work()\n"); sc->waiting_resp = 1; - wakeup(&sc->wait_taskqueue); + wakeup(&sc->wait_taskqueue);//???? } static void -xu_intr(void *xsc) +xu_int(void *xsc) { - printf("[gbdebug-pvusb]xu_intr()\n"); + printf("[gbdebug-pvusb]xu_int()\n"); struct xenhci_softc *sc = xsc; xenhci_notify_work(sc); } -/* ** Driver registration ** */ +/** + * ** Driver registration ** + */ static device_method_t usbfront_methods[] = { /* Device interface */ DEVMETHOD(device_probe, usbfront_probe),
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201309271130.r8RBUph5016468>