diff options
author | Yunhong Jiang <yunhong.jiang@intel.com> | 2015-08-04 12:17:53 -0700 |
---|---|---|
committer | Yunhong Jiang <yunhong.jiang@intel.com> | 2015-08-04 15:44:42 -0700 |
commit | 9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (patch) | |
tree | 1c9cafbcd35f783a87880a10f85d1a060db1a563 /kernel/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c | |
parent | 98260f3884f4a202f9ca5eabed40b1354c489b29 (diff) |
Add the rt linux 4.1.3-rt3 as base
Import the rt linux 4.1.3-rt3 as OPNFV kvm base.
It's from git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git linux-4.1.y-rt and
the base is:
commit 0917f823c59692d751951bf5ea699a2d1e2f26a2
Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: Sat Jul 25 12:13:34 2015 +0200
Prepare v4.1.3-rt3
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
We lose all the git history this way and it's not good. We
should apply another opnfv project repo in future.
Change-Id: I87543d81c9df70d99c5001fbdf646b202c19f423
Signed-off-by: Yunhong Jiang <yunhong.jiang@intel.com>
Diffstat (limited to 'kernel/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c')
-rw-r--r-- | kernel/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/kernel/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c b/kernel/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c new file mode 100644 index 000000000..3b303b6b1 --- /dev/null +++ b/kernel/drivers/staging/ft1000/ft1000-usb/ft1000_usb.c @@ -0,0 +1,254 @@ +/*===================================================== + * CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved. + * + * + * This file is part of Express Card USB Driver + * + * $Id: + *==================================================== + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/usb.h> +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/firmware.h> +#include "ft1000_usb.h" + +#include <linux/kthread.h> + +MODULE_DESCRIPTION("FT1000 EXPRESS CARD DRIVER"); +MODULE_LICENSE("Dual MPL/GPL"); +MODULE_SUPPORTED_DEVICE("QFT FT1000 Express Cards"); + +void *pFileStart; +size_t FileLength; + +#define VENDOR_ID 0x1291 /* Qualcomm vendor id */ +#define PRODUCT_ID 0x11 /* fake product id */ + +/* table of devices that work with this driver */ +static struct usb_device_id id_table[] = { + {USB_DEVICE(VENDOR_ID, PRODUCT_ID)}, + {}, +}; + +MODULE_DEVICE_TABLE(usb, id_table); + +static bool gPollingfailed; +static int ft1000_poll_thread(void *arg) +{ + int ret; + + while (!kthread_should_stop()) { + usleep_range(10000, 11000); + if (!gPollingfailed) { + ret = ft1000_poll(arg); + if (ret != 0) { + pr_debug("polling failed\n"); + gPollingfailed = true; + } + } + } + return 0; +} + +static int ft1000_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + struct usb_device *dev; + unsigned numaltsetting; + int i, ret = 0, size; + + struct ft1000_usb *ft1000dev; + struct ft1000_info *pft1000info = NULL; + const struct firmware *dsp_fw; + + ft1000dev = kzalloc(sizeof(struct ft1000_usb), GFP_KERNEL); + if (!ft1000dev) + return -ENOMEM; + + dev = interface_to_usbdev(interface); + pr_debug("usb device descriptor info - number of configuration is %d\n", + dev->descriptor.bNumConfigurations); + + ft1000dev->dev = dev; + ft1000dev->status = 0; + ft1000dev->net = NULL; + ft1000dev->tx_urb = usb_alloc_urb(0, GFP_KERNEL); + ft1000dev->rx_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!ft1000dev->tx_urb || !ft1000dev->rx_urb) { + ret = -ENOMEM; + goto err_fw; + } + + numaltsetting = interface->num_altsetting; + pr_debug("number of alt settings is: %d\n", numaltsetting); + iface_desc = interface->cur_altsetting; + pr_debug("number of endpoints is: %d\n", + iface_desc->desc.bNumEndpoints); + pr_debug("descriptor type is: %d\n", iface_desc->desc.bDescriptorType); + pr_debug("interface number is: %d\n", + iface_desc->desc.bInterfaceNumber); + pr_debug("alternatesetting is: %d\n", + iface_desc->desc.bAlternateSetting); + pr_debug("interface class is: %d\n", iface_desc->desc.bInterfaceClass); + pr_debug("control endpoint info:\n"); + pr_debug("descriptor0 type -- %d\n", + iface_desc->endpoint[0].desc.bmAttributes); + pr_debug("descriptor1 type -- %d\n", + iface_desc->endpoint[1].desc.bmAttributes); + pr_debug("descriptor2 type -- %d\n", + iface_desc->endpoint[2].desc.bmAttributes); + + for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { + endpoint = + (struct usb_endpoint_descriptor *)&iface_desc-> + endpoint[i].desc; + pr_debug("endpoint %d\n", i); + pr_debug("bEndpointAddress=%x, bmAttributes=%x\n", + endpoint->bEndpointAddress, endpoint->bmAttributes); + if ((endpoint->bEndpointAddress & USB_DIR_IN) + && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_BULK)) { + ft1000dev->bulk_in_endpointAddr = + endpoint->bEndpointAddress; + pr_debug("in: %d\n", endpoint->bEndpointAddress); + } + + if (!(endpoint->bEndpointAddress & USB_DIR_IN) + && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_BULK)) { + ft1000dev->bulk_out_endpointAddr = + endpoint->bEndpointAddress; + pr_debug("out: %d\n", endpoint->bEndpointAddress); + } + } + + pr_debug("bulk_in=%d, bulk_out=%d\n", + ft1000dev->bulk_in_endpointAddr, + ft1000dev->bulk_out_endpointAddr); + + ret = request_firmware(&dsp_fw, "ft3000.img", &dev->dev); + if (ret < 0) { + dev_err(interface->usb_dev, "Error request_firmware()\n"); + goto err_fw; + } + + size = max_t(uint, dsp_fw->size, 4096); + pFileStart = kmalloc(size, GFP_KERNEL); + + if (!pFileStart) { + release_firmware(dsp_fw); + ret = -ENOMEM; + goto err_fw; + } + + memcpy(pFileStart, dsp_fw->data, dsp_fw->size); + FileLength = dsp_fw->size; + release_firmware(dsp_fw); + + pr_debug("start downloading dsp image...\n"); + + ret = init_ft1000_netdev(ft1000dev); + if (ret) + goto err_load; + + pft1000info = netdev_priv(ft1000dev->net); + + pr_debug("pft1000info=%p\n", pft1000info); + ret = dsp_reload(ft1000dev); + if (ret) { + dev_err(interface->usb_dev, + "Problem with DSP image loading\n"); + goto err_load; + } + + gPollingfailed = false; + ft1000dev->pPollThread = + kthread_run(ft1000_poll_thread, ft1000dev, "ft1000_poll"); + + if (IS_ERR(ft1000dev->pPollThread)) { + ret = PTR_ERR(ft1000dev->pPollThread); + goto err_load; + } + + msleep(500); + + while (!pft1000info->CardReady) { + if (gPollingfailed) { + ret = -EIO; + goto err_thread; + } + msleep(100); + pr_debug("Waiting for Card Ready\n"); + } + + pr_debug("Card Ready!!!! Registering network device\n"); + + ret = reg_ft1000_netdev(ft1000dev, interface); + if (ret) + goto err_thread; + + ft1000dev->NetDevRegDone = 1; + + return 0; + +err_thread: + kthread_stop(ft1000dev->pPollThread); +err_load: + kfree(pFileStart); +err_fw: + usb_free_urb(ft1000dev->rx_urb); + usb_free_urb(ft1000dev->tx_urb); + kfree(ft1000dev); + return ret; +} + +static void ft1000_disconnect(struct usb_interface *interface) +{ + struct ft1000_info *pft1000info; + struct ft1000_usb *ft1000dev; + + pft1000info = (struct ft1000_info *)usb_get_intfdata(interface); + pr_debug("In disconnect pft1000info=%p\n", pft1000info); + + if (pft1000info) { + ft1000dev = pft1000info->priv; + if (ft1000dev->pPollThread) + kthread_stop(ft1000dev->pPollThread); + + pr_debug("threads are terminated\n"); + + if (ft1000dev->net) { + pr_debug("destroy char driver\n"); + ft1000_destroy_dev(ft1000dev->net); + unregister_netdev(ft1000dev->net); + pr_debug("network device unregistered\n"); + free_netdev(ft1000dev->net); + + } + + usb_free_urb(ft1000dev->rx_urb); + usb_free_urb(ft1000dev->tx_urb); + + pr_debug("urb freed\n"); + + kfree(ft1000dev); + } + kfree(pFileStart); +} + +static struct usb_driver ft1000_usb_driver = { + .name = "ft1000usb", + .probe = ft1000_probe, + .disconnect = ft1000_disconnect, + .id_table = id_table, +}; + +module_usb_driver(ft1000_usb_driver); |