diff options
author | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-01-20 14:01:31 -0300 |
---|---|---|
committer | André Fabian Silva Delgado <emulatorman@parabola.nu> | 2016-01-20 14:01:31 -0300 |
commit | b4b7ff4b08e691656c9d77c758fc355833128ac0 (patch) | |
tree | 82fcb00e6b918026dc9f2d1f05ed8eee83874cc0 /drivers/staging/most/hdm-usb | |
parent | 35acfa0fc609f2a2cd95cef4a6a9c3a5c38f1778 (diff) |
Linux-libre 4.4-gnupck-4.4-gnu
Diffstat (limited to 'drivers/staging/most/hdm-usb')
-rw-r--r-- | drivers/staging/most/hdm-usb/hdm_usb.c | 162 |
1 files changed, 73 insertions, 89 deletions
diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c index 305303f2f..41690f801 100644 --- a/drivers/staging/most/hdm-usb/hdm_usb.c +++ b/drivers/staging/most/hdm-usb/hdm_usb.c @@ -59,6 +59,8 @@ #define DRCI_REG_HW_ADDR_HI 0x0145 #define DRCI_REG_HW_ADDR_MI 0x0146 #define DRCI_REG_HW_ADDR_LO 0x0147 +#define DRCI_REG_BASE 0x1100 +#define DRCI_COMMAND 0x02 #define DRCI_READ_REQ 0xA0 #define DRCI_WRITE_REQ 0xA1 @@ -75,6 +77,7 @@ struct buf_anchor { struct list_head list; struct completion urb_compl; }; + #define to_buf_anchor(w) container_of(w, struct buf_anchor, clear_work_obj) /** @@ -86,6 +89,7 @@ struct most_dci_obj { struct kobject kobj; struct usb_device *usb_device; }; + #define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj) /** @@ -129,6 +133,7 @@ struct most_dev { struct timer_list link_stat_timer; struct work_struct poll_work_obj; }; + #define to_mdev(d) container_of(d, struct most_dev, iface) #define to_mdev_from_work(w) container_of(w, struct most_dev, poll_work_obj) @@ -137,36 +142,6 @@ static void wq_clear_halt(struct work_struct *wq_obj); static void wq_netinfo(struct work_struct *wq_obj); /** - * trigger_resync_vr - Vendor request to trigger HW re-sync mechanism - * @dev: usb device - * - */ -static void trigger_resync_vr(struct usb_device *dev) -{ - int retval; - u8 request_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT; - int *data = kzalloc(sizeof(*data), GFP_KERNEL); - - if (!data) - goto error; - *data = HW_RESYNC; - retval = usb_control_msg(dev, - usb_sndctrlpipe(dev, 0), - 0, - request_type, - 0, - 0, - data, - 0, - 5 * HZ); - kfree(data); - if (retval >= 0) - return; -error: - dev_err(&dev->dev, "Vendor request \"stall\" failed\n"); -} - -/** * drci_rd_reg - read a DCI register * @dev: usb device * @reg: register address @@ -174,17 +149,23 @@ error: * * This is reads data from INIC's direct register communication interface */ -static inline int drci_rd_reg(struct usb_device *dev, u16 reg, void *buf) +static inline int drci_rd_reg(struct usb_device *dev, u16 reg, u16 *buf) { - return usb_control_msg(dev, - usb_rcvctrlpipe(dev, 0), - DRCI_READ_REQ, - USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - 0x0000, - reg, - buf, - 2, - 5 * HZ); + int retval; + u16 *dma_buf = kzalloc(sizeof(u16), GFP_KERNEL); + u8 req_type = USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE; + + if (!dma_buf) + return -ENOMEM; + + retval = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), + DRCI_READ_REQ, req_type, + 0x0000, + reg, dma_buf, sizeof(u16), 5 * HZ); + *buf = le16_to_cpu(*dma_buf); + kfree(dma_buf); + + return retval; } /** @@ -220,7 +201,8 @@ static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel) unsigned long flags; spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags); - list_for_each_entry_safe(anchor, tmp, &mdev->anchor_list[channel], list) { + list_for_each_entry_safe(anchor, tmp, &mdev->anchor_list[channel], + list) { struct urb *urb = anchor->urb; spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); @@ -267,10 +249,11 @@ static unsigned int get_stream_frame_size(struct most_channel_config *cfg) if (cfg->packets_per_xact == 0) { pr_warn("Misconfig: Packets per XACT zero\n"); frame_size = 0; - } else if (cfg->packets_per_xact == 0xFF) + } else if (cfg->packets_per_xact == 0xFF) { frame_size = (USB_MTU / sub_size) * sub_size; - else + } else { frame_size = cfg->packets_per_xact * sub_size; + } break; default: pr_warn("Query frame size of non-streaming channel\n"); @@ -308,7 +291,7 @@ static int hdm_poison_channel(struct most_interface *iface, int channel) mutex_lock(&mdev->io_mutex); free_anchored_buffers(mdev, channel); - if (mdev->padding_active[channel] == true) + if (mdev->padding_active[channel]) mdev->padding_active[channel] = false; if (mdev->conf[channel].data_type == MOST_CH_ASYNC) { @@ -365,7 +348,8 @@ static int hdm_add_padding(struct most_dev *mdev, int channel, struct mbo *mbo) * This takes the INIC hardware specific padding bytes off a streaming * channel's buffer. */ -static int hdm_remove_padding(struct most_dev *mdev, int channel, struct mbo *mbo) +static int hdm_remove_padding(struct most_dev *mdev, int channel, + struct mbo *mbo) { unsigned int j, num_frames, frame_size; struct most_channel_config *const conf = &mdev->conf[channel]; @@ -411,7 +395,7 @@ static void hdm_write_completion(struct urb *urb) dev = &mdev->usb_device->dev; if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) || - (mdev->is_channel_healthy[channel] == false)) { + (!mdev->is_channel_healthy[channel])) { complete(&anchor->urb_compl); return; } @@ -453,7 +437,7 @@ static void hdm_write_completion(struct urb *urb) } /** - * hdm_read_completion - completion funciton for submitted Rx URBs + * hdm_read_completion - completion function for submitted Rx URBs * @urb: the URB that has been completed * * This checks the status of the completed URB. In case the URB has been @@ -568,7 +552,6 @@ static void hdm_read_completion(struct urb *urb) struct device *dev; unsigned long flags; unsigned int channel; - struct most_channel_config *conf; mbo = urb->context; anchor = mbo->priv; @@ -577,13 +560,11 @@ static void hdm_read_completion(struct urb *urb) dev = &mdev->usb_device->dev; if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) || - (mdev->is_channel_healthy[channel] == false)) { + (!mdev->is_channel_healthy[channel])) { complete(&anchor->urb_compl); return; } - conf = &mdev->conf[channel]; - if (unlikely(urb->status && !(urb->status == -ENOENT || urb->status == -ECONNRESET || urb->status == -ESHUTDOWN))) { @@ -608,7 +589,7 @@ static void hdm_read_completion(struct urb *urb) } } else { mbo->processed_length = urb->actual_length; - if (mdev->padding_active[channel] == false) { + if (!mdev->padding_active[channel]) { mbo->status = MBO_SUCCESS; } else { if (hdm_remove_padding(mdev, channel, mbo)) { @@ -644,7 +625,8 @@ static void hdm_read_completion(struct urb *urb) * * Context: Could in _some_ cases be interrupt! */ -static int hdm_enqueue(struct most_interface *iface, int channel, struct mbo *mbo) +static int hdm_enqueue(struct most_interface *iface, int channel, + struct mbo *mbo) { struct most_dev *mdev; struct buf_anchor *anchor; @@ -688,7 +670,7 @@ static int hdm_enqueue(struct most_interface *iface, int channel, struct mbo *mb list_add_tail(&anchor->list, &mdev->anchor_list[channel]); spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags); - if ((mdev->padding_active[channel] == true) && + if ((mdev->padding_active[channel]) && (conf->direction & MOST_CH_TX)) if (hdm_add_padding(mdev, channel, mbo)) { retval = -EIO; @@ -714,7 +696,7 @@ static int hdm_enqueue(struct most_interface *iface, int channel, struct mbo *mb usb_rcvbulkpipe(mdev->usb_device, mdev->ep_address[channel]), virt_address, - length, + length + conf->extra_len, hdm_read_completion, mbo); } @@ -780,12 +762,6 @@ static int hdm_configure_channel(struct most_interface *iface, int channel, mdev->padding_active[channel] = true; temp_size = conf->buffer_size; - if ((conf->data_type != MOST_CH_SYNC) && - (conf->data_type != MOST_CH_ISOC_AVP)) { - dev_warn(dev, "Unsupported data type\n"); - return -EINVAL; - } - frame_size = get_stream_frame_size(conf); if ((frame_size == 0) || (frame_size > USB_MTU)) { dev_warn(dev, "Misconfig: frame size wrong\n"); @@ -798,8 +774,7 @@ static int hdm_configure_channel(struct most_interface *iface, int channel, tmp_val = conf->buffer_size / frame_size; conf->buffer_size = tmp_val * frame_size; dev_notice(dev, - "Channel %d - rouding buffer size to %d bytes, " - "channel config says %d bytes\n", + "Channel %d - rounding buffer size to %d bytes, channel config says %d bytes\n", channel, conf->buffer_size, temp_size); @@ -826,38 +801,41 @@ exit: */ static int hdm_update_netinfo(struct most_dev *mdev) { - struct device *dev = &mdev->usb_device->dev; - int i; - u16 link; - u8 addr[6]; + struct usb_device *usb_device = mdev->usb_device; + struct device *dev = &usb_device->dev; + u16 hi, mi, lo, link; if (!is_valid_ether_addr(mdev->hw_addr)) { - if (0 > drci_rd_reg(mdev->usb_device, - DRCI_REG_HW_ADDR_HI, addr)) { + if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_HI, &hi) < 0) { dev_err(dev, "Vendor request \"hw_addr_hi\" failed\n"); return -1; } - if (0 > drci_rd_reg(mdev->usb_device, - DRCI_REG_HW_ADDR_MI, addr + 2)) { + + if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_MI, &mi) < 0) { dev_err(dev, "Vendor request \"hw_addr_mid\" failed\n"); return -1; } - if (0 > drci_rd_reg(mdev->usb_device, - DRCI_REG_HW_ADDR_LO, addr + 4)) { + + if (drci_rd_reg(usb_device, DRCI_REG_HW_ADDR_LO, &lo) < 0) { dev_err(dev, "Vendor request \"hw_addr_low\" failed\n"); return -1; } + mutex_lock(&mdev->io_mutex); - for (i = 0; i < 6; i++) - mdev->hw_addr[i] = addr[i]; + mdev->hw_addr[0] = hi >> 8; + mdev->hw_addr[1] = hi; + mdev->hw_addr[2] = mi >> 8; + mdev->hw_addr[3] = mi; + mdev->hw_addr[4] = lo >> 8; + mdev->hw_addr[5] = lo; mutex_unlock(&mdev->io_mutex); - } - if (0 > drci_rd_reg(mdev->usb_device, DRCI_REG_NI_STATE, &link)) { + + if (drci_rd_reg(usb_device, DRCI_REG_NI_STATE, &link) < 0) { dev_err(dev, "Vendor request \"link status\" failed\n"); return -1; } - le16_to_cpus(&link); + mutex_lock(&mdev->io_mutex); mdev->link_stat = link; mutex_unlock(&mdev->io_mutex); @@ -919,7 +897,7 @@ static void wq_netinfo(struct work_struct *wq_obj) for (i = 0; i < 6; i++) prev_hw_addr[i] = mdev->hw_addr[i]; - if (0 > hdm_update_netinfo(mdev)) + if (hdm_update_netinfo(mdev) < 0) return; if ((prev_link_stat != mdev->link_stat) || (prev_hw_addr[0] != mdev->hw_addr[0]) || @@ -1009,8 +987,8 @@ struct most_dci_attribute { const char *buf, size_t count); }; -#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr) +#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr) /** * dci_attr_show - show function for dci object @@ -1107,14 +1085,14 @@ static ssize_t show_value(struct most_dci_obj *dci_obj, if (err < 0) return err; - return snprintf(buf, PAGE_SIZE, "%04x\n", le16_to_cpu(tmp_val)); + return snprintf(buf, PAGE_SIZE, "%04x\n", tmp_val); } static ssize_t store_value(struct most_dci_obj *dci_obj, struct most_dci_attribute *attr, const char *buf, size_t count) { - u16 v16; + u16 val; u16 reg_addr; int err; @@ -1137,11 +1115,11 @@ static ssize_t store_value(struct most_dci_obj *dci_obj, else return -EIO; - err = kstrtou16(buf, 16, &v16); + err = kstrtou16(buf, 16, &val); if (err) return err; - err = drci_wr_reg(dci_obj->usb_device, reg_addr, cpu_to_le16(v16)); + err = drci_wr_reg(dci_obj->usb_device, reg_addr, val); if (err < 0) return err; @@ -1248,6 +1226,7 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) struct usb_host_interface *usb_iface_desc; struct usb_endpoint_descriptor *ep_desc; int ret = 0; + int err; usb_iface_desc = interface->cur_altsetting; usb_dev = interface_to_usbdev(interface); @@ -1260,11 +1239,10 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) num_endpoints = usb_iface_desc->desc.bNumEndpoints; mutex_init(&mdev->io_mutex); INIT_WORK(&mdev->poll_work_obj, wq_netinfo); - init_timer(&mdev->link_stat_timer); + setup_timer(&mdev->link_stat_timer, link_stat_timer_handler, + (unsigned long)mdev); mdev->usb_device = usb_dev; - mdev->link_stat_timer.function = link_stat_timer_handler; - mdev->link_stat_timer.data = (unsigned long)mdev; mdev->link_stat_timer.expires = jiffies + (2 * HZ); mdev->iface.mod = hdm_usb_fops.owner; @@ -1328,6 +1306,13 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) tmp_cap++; INIT_LIST_HEAD(&mdev->anchor_list[i]); spin_lock_init(&mdev->anchor_list_lock[i]); + err = drci_wr_reg(usb_dev, + DRCI_REG_BASE + DRCI_COMMAND + + ep_desc->bEndpointAddress * 16, + 1); + if (err < 0) + pr_warn("DCI Sync for EP %02x failed", + ep_desc->bEndpointAddress); } dev_notice(dev, "claimed gadget: Vendor=%4.4x ProdID=%4.4x Bus=%02x Device=%02x\n", le16_to_cpu(usb_dev->descriptor.idVendor), @@ -1362,7 +1347,6 @@ hdm_probe(struct usb_interface *interface, const struct usb_device_id *id) kobject_uevent(&mdev->dci->kobj, KOBJ_ADD); mdev->dci->usb_device = mdev->usb_device; - trigger_resync_vr(usb_dev); } mutex_unlock(&mdev->io_mutex); return 0; @@ -1432,7 +1416,7 @@ static int __init hdm_usb_init(void) return -EIO; } schedule_usb_work = create_workqueue("hdmu_work"); - if (schedule_usb_work == NULL) { + if (!schedule_usb_work) { pr_err("could not create workqueue\n"); usb_deregister(&hdm_usb); return -ENOMEM; |