2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-11-27 12:04:22 +08:00

Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media fixes from Mauro Carvalho Chehab:
 "A series of small fixes.  Mostly driver ones.  There is one core
  regression fix on a patch that was meant to fix some race issues on
  vb2, but that actually caused more harm than good.  So, we're just
  reverting it for now"

* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media:
  [media] adv7842: Composite free-run platfrom-data fix
  [media] v4l2-dv-timings: fix GTF calculation
  [media] hdpvr: Fix memory leak in debug
  [media] af9035: add ID [2040:f900] Hauppauge WinTV-MiniStick 2
  [media] mxl111sf: Fix compile when CONFIG_DVB_USB_MXL111SF is unset
  [media] mxl111sf: Fix unintentional garbage stack read
  [media] cx24117: use a valid dev pointer for dev_err printout
  [media] cx24117: remove dead code in always 'false' if statement
  [media] update Michael Krufky's email address
  [media] vb2: Check if there are buffers before streamon
  [media] Revert "[media] videobuf_vm_{open,close} race fixes"
  [media] go7007-loader: fix usb_dev leak
  [media] media: bt8xx: add missing put_device call
  [media] exynos4-is: Compile in fimc-lite runtime PM callbacks conditionally
  [media] exynos4-is: Compile in fimc runtime PM callbacks conditionally
  [media] exynos4-is: Fix error paths in probe() for !pm_runtime_enabled()
  [media] s5p-jpeg: Fix wrong NV12 format parameters
  [media] s5k5baf: allow to handle arbitrary long i2c sequences
This commit is contained in:
Linus Torvalds 2014-02-07 12:16:36 -08:00
commit 3e382dd9d0
32 changed files with 85 additions and 73 deletions

View File

@ -78,7 +78,7 @@ Peter Beutner <p.beutner@gmx.net>
Wilson Michaels <wilsonmichaels@earthlink.net>
for the lgdt330x frontend driver, and various bugfixes
Michael Krufky <mkrufky@m1k.net>
Michael Krufky <mkrufky@linuxtv.org>
for maintaining v4l/dvb inter-tree dependencies
Taylor Jacob <rtjacob@earthlink.net>

View File

@ -1176,7 +1176,7 @@ struct dvb_frontend *cx24117_attach(const struct cx24117_config *config,
switch (demod) {
case 0:
dev_err(&state->priv->i2c->dev,
dev_err(&i2c->dev,
"%s: Error attaching frontend %d\n",
KBUILD_MODNAME, demod);
goto error1;
@ -1200,12 +1200,6 @@ struct dvb_frontend *cx24117_attach(const struct cx24117_config *config,
state->demod = demod - 1;
state->priv = priv;
/* test i2c bus for ack */
if (demod == 0) {
if (cx24117_readreg(state, 0x00) < 0)
goto error3;
}
dev_info(&state->priv->i2c->dev,
"%s: Attaching frontend %d\n",
KBUILD_MODNAME, state->demod);
@ -1216,8 +1210,6 @@ struct dvb_frontend *cx24117_attach(const struct cx24117_config *config,
state->frontend.demodulator_priv = state;
return &state->frontend;
error3:
kfree(state);
error2:
cx24117_release_priv(priv);
error1:

View File

@ -2,7 +2,7 @@
* Support for NXT2002 and NXT2004 - VSB/QAM
*
* Copyright (C) 2005 Kirk Lapray <kirk.lapray@gmail.com>
* Copyright (C) 2006 Michael Krufky <mkrufky@m1k.net>
* Copyright (C) 2006-2014 Michael Krufky <mkrufky@linuxtv.org>
* based on nxt2002 by Taylor Jacob <rtjacob@earthlink.net>
* and nxt2004 by Jean-Francois Thibert <jeanfrancois@sagetv.com>
*

View File

@ -2554,7 +2554,7 @@ static int adv7842_core_init(struct v4l2_subdev *sd)
sdp_write_and_or(sd, 0xdd, 0xf0, pdata->sdp_free_run_force |
(pdata->sdp_free_run_cbar_en << 1) |
(pdata->sdp_free_run_man_col_en << 2) |
(pdata->sdp_free_run_force << 3));
(pdata->sdp_free_run_auto << 3));
/* TODO from platform data */
cp_write(sd, 0x69, 0x14); /* Enable CP CSC */

View File

@ -478,25 +478,33 @@ static void s5k5baf_write_arr_seq(struct s5k5baf *state, u16 addr,
u16 count, const u16 *seq)
{
struct i2c_client *c = v4l2_get_subdevdata(&state->sd);
__be16 buf[count + 1];
int ret, n;
__be16 buf[65];
s5k5baf_i2c_write(state, REG_CMDWR_ADDR, addr);
if (state->error)
return;
buf[0] = __constant_cpu_to_be16(REG_CMD_BUF);
for (n = 1; n <= count; ++n)
buf[n] = cpu_to_be16(*seq++);
n *= 2;
ret = i2c_master_send(c, (char *)buf, n);
v4l2_dbg(3, debug, c, "i2c_write_seq(count=%d): %*ph\n", count,
min(2 * count, 64), seq - count);
min(2 * count, 64), seq);
if (ret != n) {
v4l2_err(c, "i2c_write_seq: error during transfer (%d)\n", ret);
state->error = ret;
buf[0] = __constant_cpu_to_be16(REG_CMD_BUF);
while (count > 0) {
int n = min_t(int, count, ARRAY_SIZE(buf) - 1);
int ret, i;
for (i = 1; i <= n; ++i)
buf[i] = cpu_to_be16(*seq++);
i *= 2;
ret = i2c_master_send(c, (char *)buf, i);
if (ret != i) {
v4l2_err(c, "i2c_write_seq: error during transfer (%d)\n", ret);
state->error = ret;
break;
}
count -= n;
}
}

View File

@ -2426,7 +2426,7 @@ struct tvcard bttv_tvcards[] = {
},
/* ---- card 0x87---------------------------------- */
[BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE] = {
/* Michael Krufky <mkrufky@m1k.net> */
/* Michael Krufky <mkrufky@linuxtv.org> */
.name = "DViCO FusionHDTV 5 Lite",
.tuner_type = TUNER_LG_TDVS_H06XF, /* TDVS-H064F */
.tuner_addr = ADDR_UNSET,

View File

@ -98,7 +98,7 @@ int bttv_sub_add_device(struct bttv_core *core, char *name)
err = device_register(&sub->dev);
if (0 != err) {
kfree(sub);
put_device(&sub->dev);
return err;
}
pr_info("%d: add subdevice \"%s\"\n", core->nr, dev_name(&sub->dev));

View File

@ -2590,7 +2590,7 @@ struct saa7134_board saa7134_boards[] = {
}},
},
[SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180] = {
/* Michael Krufky <mkrufky@m1k.net>
/* Michael Krufky <mkrufky@linuxtv.org>
* Uses Alps Electric TDHU2, containing NXT2004 ATSC Decoder
* AFAIK, there is no analog demod, thus,
* no support for analog television.

View File

@ -1027,7 +1027,8 @@ static int fimc_probe(struct platform_device *pdev)
return 0;
err_gclk:
clk_disable(fimc->clock[CLK_GATE]);
if (!pm_runtime_enabled(dev))
clk_disable(fimc->clock[CLK_GATE]);
err_sd:
fimc_unregister_capture_subdev(fimc);
err_sclk:
@ -1036,6 +1037,7 @@ err_sclk:
return ret;
}
#ifdef CONFIG_PM_RUNTIME
static int fimc_runtime_resume(struct device *dev)
{
struct fimc_dev *fimc = dev_get_drvdata(dev);
@ -1068,6 +1070,7 @@ static int fimc_runtime_suspend(struct device *dev)
dbg("fimc%d: state: 0x%lx", fimc->id, fimc->state);
return ret;
}
#endif
#ifdef CONFIG_PM_SLEEP
static int fimc_resume(struct device *dev)

View File

@ -1563,7 +1563,7 @@ static int fimc_lite_probe(struct platform_device *pdev)
if (!pm_runtime_enabled(dev)) {
ret = clk_enable(fimc->clock);
if (ret < 0)
goto err_clk_put;
goto err_sd;
}
fimc->alloc_ctx = vb2_dma_contig_init_ctx(dev);
@ -1579,7 +1579,8 @@ static int fimc_lite_probe(struct platform_device *pdev)
return 0;
err_clk_dis:
clk_disable(fimc->clock);
if (!pm_runtime_enabled(dev))
clk_disable(fimc->clock);
err_sd:
fimc_lite_unregister_capture_subdev(fimc);
err_clk_put:
@ -1587,6 +1588,7 @@ err_clk_put:
return ret;
}
#ifdef CONFIG_PM_RUNTIME
static int fimc_lite_runtime_resume(struct device *dev)
{
struct fimc_lite *fimc = dev_get_drvdata(dev);
@ -1602,6 +1604,7 @@ static int fimc_lite_runtime_suspend(struct device *dev)
clk_disable(fimc->clock);
return 0;
}
#endif
#ifdef CONFIG_PM_SLEEP
static int fimc_lite_resume(struct device *dev)

View File

@ -175,7 +175,7 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = {
{
.name = "YUV 4:2:0 planar, Y/CbCr",
.fourcc = V4L2_PIX_FMT_NV12,
.depth = 16,
.depth = 12,
.colplanes = 2,
.h_align = 1,
.v_align = 1,
@ -188,10 +188,10 @@ static struct s5p_jpeg_fmt sjpeg_formats[] = {
{
.name = "YUV 4:2:0 planar, Y/CbCr",
.fourcc = V4L2_PIX_FMT_NV12,
.depth = 16,
.colplanes = 4,
.depth = 12,
.colplanes = 2,
.h_align = 4,
.v_align = 1,
.v_align = 4,
.flags = SJPEG_FMT_FLAG_ENC_OUTPUT |
SJPEG_FMT_FLAG_DEC_CAPTURE |
SJPEG_FMT_FLAG_S5P |

View File

@ -1539,6 +1539,8 @@ static const struct usb_device_id af9035_id_table[] = {
&af9035_props, "TerraTec Cinergy T Stick Dual RC (rev. 2)", NULL) },
{ DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6a05,
&af9035_props, "Leadtek WinFast DTV Dongle Dual", NULL) },
{ DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xf900,
&af9035_props, "Hauppauge WinTV-MiniStick 2", NULL) },
{ }
};
MODULE_DEVICE_TABLE(usb, af9035_id_table);

View File

@ -1,7 +1,7 @@
/*
* mxl111sf-demod.c - driver for the MaxLinear MXL111SF DVB-T demodulator
*
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
* Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -601,7 +601,7 @@ struct dvb_frontend *mxl111sf_demod_attach(struct mxl111sf_state *mxl_state,
EXPORT_SYMBOL_GPL(mxl111sf_demod_attach);
MODULE_DESCRIPTION("MaxLinear MxL111SF DVB-T demodulator driver");
MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1");

View File

@ -1,7 +1,7 @@
/*
* mxl111sf-demod.h - driver for the MaxLinear MXL111SF DVB-T demodulator
*
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
* Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
/*
* mxl111sf-gpio.c - driver for the MaxLinear MXL111SF
*
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
* Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
/*
* mxl111sf-gpio.h - driver for the MaxLinear MXL111SF
*
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
* Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
/*
* mxl111sf-i2c.c - driver for the MaxLinear MXL111SF
*
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
* Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
/*
* mxl111sf-i2c.h - driver for the MaxLinear MXL111SF
*
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
* Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
/*
* mxl111sf-phy.c - driver for the MaxLinear MXL111SF
*
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
* Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
/*
* mxl111sf-phy.h - driver for the MaxLinear MXL111SF
*
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
* Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
/*
* mxl111sf-reg.h - driver for the MaxLinear MXL111SF
*
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
* Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,7 +1,7 @@
/*
* mxl111sf-tuner.c - driver for the MaxLinear MXL111SF CMOS tuner
*
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
* Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -512,7 +512,7 @@ struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
EXPORT_SYMBOL_GPL(mxl111sf_tuner_attach);
MODULE_DESCRIPTION("MaxLinear MxL111SF CMOS tuner driver");
MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1");

View File

@ -1,7 +1,7 @@
/*
* mxl111sf-tuner.h - driver for the MaxLinear MXL111SF CMOS tuner
*
* Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com>
* Copyright (C) 2010-2014 Michael Krufky <mkrufky@linuxtv.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -68,7 +68,7 @@ struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
#else
static inline
struct dvb_frontend *mxl111sf_tuner_attach(struct dvb_frontend *fe,
struct mxl111sf_state *mxl_state
struct mxl111sf_state *mxl_state,
struct mxl111sf_tuner_config *cfg)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.com)
* Copyright (C) 2010-2014 Michael Krufky (mkrufky@linuxtv.org)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
@ -105,7 +105,7 @@ int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data)
ret = -EINVAL;
}
pr_debug("R: (0x%02x, 0x%02x)\n", addr, *data);
pr_debug("R: (0x%02x, 0x%02x)\n", addr, buf[1]);
fail:
return ret;
}
@ -1421,7 +1421,7 @@ static struct usb_driver mxl111sf_usb_driver = {
module_usb_driver(mxl111sf_usb_driver);
MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
MODULE_AUTHOR("Michael Krufky <mkrufky@linuxtv.org>");
MODULE_DESCRIPTION("Driver for MaxLinear MxL111SF");
MODULE_VERSION("1.0");
MODULE_LICENSE("GPL");

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.com)
* Copyright (C) 2010-2014 Michael Krufky (mkrufky@linuxtv.org)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free

View File

@ -198,7 +198,6 @@ static int device_authorization(struct hdpvr_device *dev)
hex_dump_to_buffer(response, 8, 16, 1, print_buf, 5*buf_size+1, 0);
v4l2_dbg(MSG_INFO, hdpvr_debug, &dev->v4l2_dev, " response: %s\n",
print_buf);
kfree(print_buf);
#endif
msleep(100);
@ -214,6 +213,9 @@ static int device_authorization(struct hdpvr_device *dev)
retval = ret != 8;
unlock:
mutex_unlock(&dev->usbc_mutex);
#ifdef HDPVR_DEBUG
kfree(print_buf);
#endif
return retval;
}

View File

@ -515,6 +515,7 @@ bool v4l2_detect_gtf(unsigned frame_height,
aspect.denominator = 9;
}
image_width = ((image_height * aspect.numerator) / aspect.denominator);
image_width = (image_width + GTF_CELL_GRAN/2) & ~(GTF_CELL_GRAN - 1);
/* Horizontal */
if (default_gtf)

View File

@ -66,14 +66,11 @@ static void __videobuf_dc_free(struct device *dev,
static void videobuf_vm_open(struct vm_area_struct *vma)
{
struct videobuf_mapping *map = vma->vm_private_data;
struct videobuf_queue *q = map->q;
dev_dbg(q->dev, "vm_open %p [count=%u,vma=%08lx-%08lx]\n",
dev_dbg(map->q->dev, "vm_open %p [count=%u,vma=%08lx-%08lx]\n",
map, map->count, vma->vm_start, vma->vm_end);
videobuf_queue_lock(q);
map->count++;
videobuf_queue_unlock(q);
}
static void videobuf_vm_close(struct vm_area_struct *vma)
@ -85,11 +82,12 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
dev_dbg(q->dev, "vm_close %p [count=%u,vma=%08lx-%08lx]\n",
map, map->count, vma->vm_start, vma->vm_end);
videobuf_queue_lock(q);
if (!--map->count) {
map->count--;
if (0 == map->count) {
struct videobuf_dma_contig_memory *mem;
dev_dbg(q->dev, "munmap %p q=%p\n", map, q);
videobuf_queue_lock(q);
/* We need first to cancel streams, before unmapping */
if (q->streaming)
@ -128,8 +126,8 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
kfree(map);
videobuf_queue_unlock(q);
}
videobuf_queue_unlock(q);
}
static const struct vm_operations_struct videobuf_vm_ops = {

View File

@ -338,14 +338,11 @@ EXPORT_SYMBOL_GPL(videobuf_dma_free);
static void videobuf_vm_open(struct vm_area_struct *vma)
{
struct videobuf_mapping *map = vma->vm_private_data;
struct videobuf_queue *q = map->q;
dprintk(2, "vm_open %p [count=%d,vma=%08lx-%08lx]\n", map,
map->count, vma->vm_start, vma->vm_end);
videobuf_queue_lock(q);
map->count++;
videobuf_queue_unlock(q);
}
static void videobuf_vm_close(struct vm_area_struct *vma)
@ -358,9 +355,10 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
dprintk(2, "vm_close %p [count=%d,vma=%08lx-%08lx]\n", map,
map->count, vma->vm_start, vma->vm_end);
videobuf_queue_lock(q);
if (!--map->count) {
map->count--;
if (0 == map->count) {
dprintk(1, "munmap %p q=%p\n", map, q);
videobuf_queue_lock(q);
for (i = 0; i < VIDEO_MAX_FRAME; i++) {
if (NULL == q->bufs[i])
continue;
@ -376,9 +374,9 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
q->bufs[i]->baddr = 0;
q->ops->buf_release(q, q->bufs[i]);
}
videobuf_queue_unlock(q);
kfree(map);
}
videobuf_queue_unlock(q);
return;
}

View File

@ -54,14 +54,11 @@ MODULE_LICENSE("GPL");
static void videobuf_vm_open(struct vm_area_struct *vma)
{
struct videobuf_mapping *map = vma->vm_private_data;
struct videobuf_queue *q = map->q;
dprintk(2, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", map,
map->count, vma->vm_start, vma->vm_end);
videobuf_queue_lock(q);
map->count++;
videobuf_queue_unlock(q);
}
static void videobuf_vm_close(struct vm_area_struct *vma)
@ -73,11 +70,12 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", map,
map->count, vma->vm_start, vma->vm_end);
videobuf_queue_lock(q);
if (!--map->count) {
map->count--;
if (0 == map->count) {
struct videobuf_vmalloc_memory *mem;
dprintk(1, "munmap %p q=%p\n", map, q);
videobuf_queue_lock(q);
/* We need first to cancel streams, before unmapping */
if (q->streaming)
@ -116,8 +114,8 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
kfree(map);
videobuf_queue_unlock(q);
}
videobuf_queue_unlock(q);
return;
}

View File

@ -1776,6 +1776,11 @@ static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
return 0;
}
if (!q->num_buffers) {
dprintk(1, "streamon: no buffers have been allocated\n");
return -EINVAL;
}
/*
* If any buffers were queued before streamon,
* we can now pass them to driver for processing.

View File

@ -59,7 +59,7 @@ static int go7007_loader_probe(struct usb_interface *interface,
if (usbdev->descriptor.bNumConfigurations != 1) {
dev_err(&interface->dev, "can't handle multiple config\n");
return -ENODEV;
goto failed2;
}
vendor = le16_to_cpu(usbdev->descriptor.idVendor);
@ -108,6 +108,7 @@ static int go7007_loader_probe(struct usb_interface *interface,
return 0;
failed2:
usb_put_dev(usbdev);
dev_err(&interface->dev, "probe failed\n");
return -ENODEV;
}
@ -115,6 +116,7 @@ failed2:
static void go7007_loader_disconnect(struct usb_interface *interface)
{
dev_info(&interface->dev, "disconnect\n");
usb_put_dev(interface_to_usbdev(interface));
usb_set_intfdata(interface, NULL);
}