static void usb_log_enable(struct es1_ap_dev *es1) { if (!IS_ERR_OR_NULL(apb1_log_task)) return; /* get log from APB1 */ apb1_log_task = kthread_run(apb1_log_poll, es1, "apb1_log"); if (IS_ERR(apb1_log_task)) return; apb1_log_dentry = debugfs_create_file("apb1_log", S_IRUGO, gb_debugfs_get(), NULL, &apb1_log_fops); }
static void usb_log_enable(struct es2_ap_dev *es2) { if (!IS_ERR_OR_NULL(es2->apb_log_task)) return; /* get log from APB1 */ es2->apb_log_task = kthread_run(apb_log_poll, es2, "apb_log"); if (IS_ERR(es2->apb_log_task)) return; /* XXX We will need to rename this per APB */ es2->apb_log_dentry = debugfs_create_file("apb_log", S_IRUGO, gb_debugfs_get(), es2, &apb_log_fops); }
/* * The ES2 USB Bridge device has 15 endpoints * 1 Control - usual USB stuff + AP -> APBridgeA messages * 7 Bulk IN - CPort data in * 7 Bulk OUT - CPort data out */ static int ap_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct es2_ap_dev *es2; struct gb_host_device *hd; struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; int bulk_in = 0; int bulk_out = 0; int retval = -ENOMEM; int i; int num_cports; int cport_id; udev = usb_get_dev(interface_to_usbdev(interface)); num_cports = apb_get_cport_count(udev); if (num_cports < 0) { usb_put_dev(udev); dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n", num_cports); return num_cports; } hd = gb_hd_create(&es2_driver, &udev->dev, ES2_GBUF_MSG_SIZE_MAX, num_cports); if (IS_ERR(hd)) { usb_put_dev(udev); return PTR_ERR(hd); } /* * CPorts 16 and 17 are reserved for CDSI0 and CDSI1, make sure they * won't be allocated dynamically. */ do { cport_id = ida_simple_get(&hd->cport_id_map, 16, 18, GFP_KERNEL); } while (cport_id > 0); es2 = hd_to_es2(hd); es2->hd = hd; es2->usb_intf = interface; es2->usb_dev = udev; spin_lock_init(&es2->cport_out_urb_lock); INIT_KFIFO(es2->apb_log_fifo); usb_set_intfdata(interface, es2); es2->cport_to_ep = kcalloc(hd->num_cports, sizeof(*es2->cport_to_ep), GFP_KERNEL); if (!es2->cport_to_ep) { retval = -ENOMEM; goto error; } /* find all bulk endpoints */ iface_desc = interface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; if (usb_endpoint_is_bulk_in(endpoint)) { es2->cport_in[bulk_in++].endpoint = endpoint->bEndpointAddress; } else if (usb_endpoint_is_bulk_out(endpoint)) { es2->cport_out[bulk_out++].endpoint = endpoint->bEndpointAddress; } else { dev_err(&udev->dev, "Unknown endpoint type found, address 0x%02x\n", endpoint->bEndpointAddress); } } if (bulk_in != NUM_BULKS || bulk_out != NUM_BULKS) { dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); goto error; } /* Allocate buffers for our cport in messages */ for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) { struct es2_cport_in *cport_in = &es2->cport_in[bulk_in]; for (i = 0; i < NUM_CPORT_IN_URB; ++i) { struct urb *urb; u8 *buffer; urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) goto error; buffer = kmalloc(ES2_GBUF_MSG_SIZE_MAX, GFP_KERNEL); if (!buffer) goto error; usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, cport_in->endpoint), buffer, ES2_GBUF_MSG_SIZE_MAX, cport_in_callback, hd); cport_in->urb[i] = urb; cport_in->buffer[i] = buffer; } } /* Allocate urbs for our CPort OUT messages */ for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { struct urb *urb; urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) goto error; es2->cport_out_urb[i] = urb; es2->cport_out_urb_busy[i] = false; /* just to be anal */ } /* XXX We will need to rename this per APB */ es2->apb_log_enable_dentry = debugfs_create_file("apb_log_enable", (S_IWUSR | S_IRUGO), gb_debugfs_get(), es2, &apb_log_enable_fops); retval = gb_hd_add(hd); if (retval) goto error; for (i = 0; i < NUM_BULKS; ++i) { retval = es2_cport_in_enable(es2, &es2->cport_in[i]); if (retval) goto err_disable_cport_in; } return 0; err_disable_cport_in: for (--i; i >= 0; --i) es2_cport_in_disable(es2, &es2->cport_in[i]); gb_hd_del(hd); error: es2_destroy(es2); return retval; }
/* * The ES1 USB Bridge device contains 4 endpoints * 1 Control - usual USB stuff + AP -> SVC messages * 1 Interrupt IN - SVC -> AP messages * 1 Bulk IN - CPort data in * 1 Bulk OUT - CPort data out */ static int ap_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct es1_ap_dev *es1; struct greybus_host_device *hd; struct usb_device *udev; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; int bulk_in = 0; int bulk_out = 0; int retval = -ENOMEM; int i; int num_cports; udev = usb_get_dev(interface_to_usbdev(interface)); num_cports = apb1_get_cport_count(udev); if (num_cports < 0) { usb_put_dev(udev); dev_err(&udev->dev, "Cannot retrieve CPort count: %d\n", num_cports); return num_cports; } hd = greybus_create_hd(&es1_driver, &udev->dev, ES1_GBUF_MSG_SIZE_MAX, num_cports); if (IS_ERR(hd)) { usb_put_dev(udev); return PTR_ERR(hd); } es1 = hd_to_es1(hd); es1->hd = hd; es1->usb_intf = interface; es1->usb_dev = udev; spin_lock_init(&es1->cport_out_urb_lock); usb_set_intfdata(interface, es1); es1->cport_to_ep = kcalloc(hd->num_cports, sizeof(*es1->cport_to_ep), GFP_KERNEL); if (!es1->cport_to_ep) { retval = -ENOMEM; goto error; } /* find all 3 of our endpoints */ iface_desc = interface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; if (usb_endpoint_is_bulk_in(endpoint)) { es1->cport_in[bulk_in++].endpoint = endpoint->bEndpointAddress; } else if (usb_endpoint_is_bulk_out(endpoint)) { es1->cport_out[bulk_out++].endpoint = endpoint->bEndpointAddress; } else { dev_err(&udev->dev, "Unknown endpoint type found, address %x\n", endpoint->bEndpointAddress); } } if ((bulk_in == 0) || (bulk_out == 0)) { dev_err(&udev->dev, "Not enough endpoints found in device, aborting!\n"); goto error; } /* Allocate buffers for our cport in messages and start them up */ for (bulk_in = 0; bulk_in < NUM_BULKS; bulk_in++) { struct es1_cport_in *cport_in = &es1->cport_in[bulk_in]; for (i = 0; i < NUM_CPORT_IN_URB; ++i) { struct urb *urb; u8 *buffer; urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) goto error; buffer = kmalloc(ES1_GBUF_MSG_SIZE_MAX, GFP_KERNEL); if (!buffer) goto error; usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, cport_in->endpoint), buffer, ES1_GBUF_MSG_SIZE_MAX, cport_in_callback, hd); cport_in->urb[i] = urb; cport_in->buffer[i] = buffer; retval = usb_submit_urb(urb, GFP_KERNEL); if (retval) goto error; } } /* Allocate urbs for our CPort OUT messages */ for (i = 0; i < NUM_CPORT_OUT_URB; ++i) { struct urb *urb; urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) goto error; es1->cport_out_urb[i] = urb; es1->cport_out_urb_busy[i] = false; /* just to be anal */ } apb1_log_enable_dentry = debugfs_create_file("apb1_log_enable", (S_IWUSR | S_IRUGO), gb_debugfs_get(), es1, &apb1_log_enable_fops); return 0; error: ap_disconnect(interface); return retval; }