socsvn commit: r255269 - soc2013/bguan/head/sys/dev/xen/usbfront

bguan at FreeBSD.org bguan at FreeBSD.org
Sun Jul 28 17:24:12 UTC 2013


Author: bguan
Date: Sun Jul 28 17:24:11 2013
New Revision: 255269
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=255269

Log:
  debug method usbfront_connect() in usbfront

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	Sun Jul 28 16:56:31 2013	(r255268)
+++ soc2013/bguan/head/sys/dev/xen/usbfront/usbfront.c	Sun Jul 28 17:24:11 2013	(r255269)
@@ -88,7 +88,14 @@
 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);
 
+#define virt_to_mfn(x) (vtomach(x) >> PAGE_SHIFT)
 
 /**
  * Entry point to this code when a new device is created. Allocate the basic
@@ -168,6 +175,9 @@
 	printf("[gbdebug-pvusb]device_add_child() done!\n");
 	device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
 
+	/* usbfront IO lock TODO?? */
+	mtx_init(&sc->lock, "usbfront i/o lock", NULL, MTX_DEF);
+
 	/* xen shared ring related stuff*/
 	err = xs_scanf(XST_NIL, backend_path, "num-ports", NULL, "%d", &num_ports);
 	if (err) {
@@ -234,8 +244,9 @@
 {
 	printf("[gbdebug-pvusb]usbfront_detach\n");
 
-	//struct xenhci_softc *sc = device_get_softc(dev);
+	struct xenhci_softc *sc = device_get_softc(dev);
 
+	mtx_destroy(&sc->lock);
 	DPRINTK("usbfront_remove: %s removed\n", xenbus_get_node(dev));
 
 	//TODO
@@ -245,6 +256,59 @@
 	return 0;
 }
 
+
+static int 
+usbfront_connect(device_t dev)
+{
+	struct xenhci_softc *sc = device_get_softc(dev);
+	//struct usbfront_info *info = dev->dev.driver_data;
+
+	usbif_conn_request_t *req;
+	int i, idx, err;
+	int notify;
+	//char name[TASK_COMM_LEN];
+	//struct usb_hcd *hcd;
+
+	//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;
+	//}
+
+	/* prepare ring for hotplug notification */
+	for (idx = 0, i = 0; i < USB_CONN_RING_SIZE; i++) {
+		req = RING_GET_REQUEST(&sc->conn_ring, idx);
+		req->id = idx;
+		idx++;
+	}
+	sc->conn_ring.req_prod_pvt = idx;
+
+	RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&sc->conn_ring, notify);
+	if (notify)
+		notify_remote_via_irq(sc->irq);
+
+	return 0;
+}
+
+static void 
+usbfront_disconnect(device_t dev)
+{
+        xenbus_set_state(dev, XenbusStateClosing);
+
+        DPRINTK("xusb_closing: %s removed\n", xenbus_get_node(dev));
+	
+        xenbus_set_state(dev, XenbusStateClosed);
+}
+
 /**
  * Callback received when the backend's state changes.
  */
@@ -258,39 +322,204 @@
 	//DPRINTK("backend_state=%d\n", backend_state);
 
 	switch (backend_state) {
-		case XenbusStateUnknown:
+		case XenbusStateInitialised:
 		case XenbusStateInitialising:
+		case XenbusStateConnected:
 		case XenbusStateReconfigured:
 		case XenbusStateReconfiguring:
+		case XenbusStateUnknown:
 		case XenbusStateClosed:
 			break;
 
 		case XenbusStateInitWait:
-		case XenbusStateInitialised:
-			//TODO
-			//usbfront_initialize(sc);
-			printf("[gbdebug-pvusb]usbfront_backend_changed: initialize(sc)\n");
+			printf("[gbdebug-pvusb]usbfront_backend_changed: XenbusStateInitWait\n");
+			if (xenbus_get_state(dev) != XenbusStateInitialising)
+				break;
+			//if (usbfront_connect(sc) != 0)
+			if (usbfront_connect(dev) != 0) {
+				printf("[gbdebug-pvusb]usbfront_connect(dev) error.\n");
+				break;
+			}
+			xenbus_set_state(dev, XenbusStateConnected); //???
+			printf("[gbdebug-pvusb]xenbus_set_state finished!\n");
 			break;
 
-		case XenbusStateConnected:
-			//TODO
-			//usbfront_initialize(sc);
-			//usbfront_connect(sc);
-			printf("[gbdebug-pvusb]usbfront_backend_changed: initialize(sc);connect(sc)\n");
+		case XenbusStateClosing:
+			usbfront_disconnect(dev);
 			break;
 
-		case XenbusStateClosing:
-			//if (sc->users > 0) {
-			//	xenbus_dev_error(dev, -EBUSY, "Device in use; refusing to close");
-			//} else {
-				//TODO
-				//usbfront_closing(dev);
-				printf("[gbdebug-pvusb]usbfront_backend_changed: closing(dev)\n");
-			//}
-			break;	
+		default:
+                	xenbus_dev_fatal(dev, EINVAL, "get state %d at usb frontend",
+					 backend_state);
+			break;
 	}
+	printf("[gbdebug-pvusb]usbfront_backend_changed finished!\n");
 }
 
+/* Common code used when first setting up, and when resuming. */
+static int 
+talk_to_backend(device_t dev, struct xenhci_softc *sc)
+{
+	const char *message;
+	struct xs_transaction xst;
+	const char *node = xenbus_get_node(dev);
+	int err;
+
+	printf("[gbdebug-pvusb]takl_to_backend()\n");
+	/* Create shared ring, alloc event channel. */
+	err = setup_rings(dev, sc);
+	if (err)
+		goto out;
+
+again:	
+	err = xs_transaction_start(&xst);
+	if (err) {
+		xenbus_dev_fatal(dev, err, "starting transaction");
+		goto destroy_ring;
+	}
+
+	err = xs_printf(xst, node, "urb-ring-ref", "%u",
+			    sc->urb_ring_ref);
+	if (err) {
+		message = "writing urb-ring-ref";
+		goto abort_transaction;
+	}
+
+	err = xs_printf(xst, node, "conn-ring-ref", "%u",
+			    sc->conn_ring_ref);
+	if (err) {
+		message = "writing conn-ring-ref";
+		goto abort_transaction;
+	}
+
+	err = xs_printf(xst, node, "event-channel", "%u",
+			    irq_to_evtchn_port(sc->irq));
+	if (err) {
+		message = "writing event-channel";
+		goto abort_transaction;
+	}
+
+	err = xs_transaction_end(xst, 0);
+	if (err) {
+		if (err == EAGAIN)
+			goto again;
+		xenbus_dev_fatal(dev, err, "completing transaction");
+		goto destroy_ring;
+	}
+
+	return 0;
+
+abort_transaction:
+	xs_transaction_end(xst, 1);
+	xenbus_dev_fatal(dev, err, "%s", message);
+
+destroy_ring:
+	destroy_rings(sc);
+
+out:
+	return err;
+}
+
+static void
+destroy_rings(struct xenhci_softc *sc)
+{
+	if (sc->irq)
+		unbind_from_irqhandler(sc->irq);
+	sc->irq = 0;
+
+	if (sc->urb_ring_ref != GRANT_INVALID_REF) {
+		/* This API frees the associated ??TODO. */
+		gnttab_end_foreign_access(sc->urb_ring_ref,
+					  (void *)sc->urb_ring.sring);
+		sc->urb_ring_ref = GRANT_INVALID_REF;
+	}
+	sc->urb_ring.sring = NULL;
+
+	if (sc->conn_ring_ref != GRANT_INVALID_REF) {
+		gnttab_end_foreign_access(sc->conn_ring_ref,
+					  (void *)sc->conn_ring.sring);
+		sc->conn_ring_ref = GRANT_INVALID_REF;
+	}
+	sc->conn_ring.sring = NULL;
+}
+
+/* Create shared ring, alloc event channel. */
+static int 
+setup_rings(device_t dev, struct xenhci_softc *sc)
+{
+	usbif_urb_sring_t *urb_sring;
+	usbif_conn_sring_t *conn_sring;
+	int otherend_id = 0;
+	int err;
+
+	printf("[gbdebug-pvusb]setup_rings()\n");
+	sc->urb_ring_ref = GRANT_INVALID_REF;
+	sc->conn_ring_ref = GRANT_INVALID_REF;
+
+	//urb_sring = (usbif_urb_sring_t *)get_zeroed_page(GFP_NOIO|__GFP_HIGH);
+	urb_sring = (usbif_urb_sring_t *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT|M_ZERO);
+	if (!urb_sring) {
+		xenbus_dev_fatal(dev, ENOMEM, "allocating urb ring");
+		return ENOMEM;
+	}
+	SHARED_RING_INIT(urb_sring);
+	FRONT_RING_INIT(&sc->urb_ring, urb_sring, PAGE_SIZE);
+
+	err = xenbus_grant_ring(dev, virt_to_mfn(urb_sring), &sc->urb_ring_ref);
+	if (err < 0) {
+		//free_page((unsigned long)urb_sring);//TODO
+		//sc->urb_ring.sring = NULL;
+		goto fail;
+	}
+	sc->urb_ring_ref = err;
+
+	//conn_sring = (usbif_conn_sring_t *)get_zeroed_page(GFP_NOIO|__GFP_HIGH);
+	conn_sring = (usbif_conn_sring_t *)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT|M_ZERO);
+	if (!conn_sring) {
+		xenbus_dev_fatal(dev, ENOMEM, "allocating conn ring");
+		return ENOMEM;
+	}
+	SHARED_RING_INIT(conn_sring);
+	FRONT_RING_INIT(&sc->conn_ring, conn_sring, PAGE_SIZE);
+
+	err = xenbus_grant_ring(dev, virt_to_mfn(conn_sring), &sc->conn_ring_ref);
+	if (err < 0) {
+		//free_page((unsigned long)conn_sring);//TODO
+		//sc->conn_ring.sring = NULL;
+		goto fail;
+	}
+	sc->conn_ring_ref = err;
+
+	otherend_id = xenbus_get_otherend_id(dev);
+	err = bind_listening_port_to_irqhandler(otherend_id, "xu", xu_intr, 
+					sc, INTR_TYPE_BIO | INTR_MPSAFE, &sc->irq);
+	if (err <= 0) {
+		xenbus_dev_fatal(dev, err,
+				 "bind_listening_port_to_irqhandler");
+		goto fail;
+	}
+	sc->irq = err;
+
+	return 0;
+fail:
+	destroy_rings(sc);
+	return err;
+}
+
+static void 
+xenhci_notify_work(struct xenhci_softc *sc)
+{       
+        sc->waiting_resp = 1;
+        wakeup(&sc->wait_taskqueue);
+}                          
+
+static void
+xu_intr(void *xsc)
+{
+	struct xenhci_softc *sc = xsc;
+        xenhci_notify_work(sc);
+}       
+
 
 /* ** Driver registration ** */
 static device_method_t usbfront_methods[] = { 


More information about the svn-soc-all mailing list