I have poked around in the source code and found some inconsistencies.

=====================================
Summary:
There are multiple definitions of MAX_XFER_SIZE in the drivers/media 
sub-directory, containing values such as 64, 80, 128, 256.
The definition that appears to matter is in 
drivers/media/usb/dvb-usb/cxusb.c
#define MAX_XFER_SIZE  64
It seems that passing a larger msg.len to cxusb_i2c_xfer causes the errors 
noted in this report.
The buffer size is declared separately in various places, having many different 
sizes. It seems that there are many ways that this error could be caused.

I have changed MAX_XFER_SIZE in tuner-xc2028.c from 80 to 64. With this
change, the kernel logs no longer contain an error when the firmare is
loaded. Indeed, the firmware appears to load successfully.

However, I have not yet been able to test whether a DVB signal can be
received and decoded.

These tests were performed after upgrading to trusty 14.04, using kernel 
3.13.0-24-generic.
=====================================

Notes

Initial testing performed using 3.14.0-031400rc6-generic on Ubuntu 14.04 (same 
kernel as used previously, but the rest of the OS was upgraded).
Apr 29 14:56:17 mythtv kernel: [ 2385.788462] cxusb: No IR receiver detected on 
this device.
Apr 29 14:56:17 mythtv kernel: [ 2385.788472] usb 3-2: DVB: registering adapter 
2 frontend 0 (Zarlink ZL10353 DVB-T)...
Apr 29 14:56:17 mythtv kernel: [ 2385.788565] xc2028 11-0061: creating new 
instance
Apr 29 14:56:17 mythtv kernel: [ 2385.788568] xc2028 11-0061: type set to 
XCeive xc2028/xc3028 tuner
Apr 29 14:56:17 mythtv kernel: [ 2385.790357] xc2028 11-0061: Loading 80 
firmware images from xc3028-v27.fw, type: xc2028 firmware, ver 2.7
Apr 29 14:56:17 mythtv kernel: [ 2385.790714] dvb-usb: DViCO FusionHDTV DVB-T 
Dual Digital 4 successfully initialized and connected.
Apr 29 14:56:17 mythtv kernel: [ 2385.790760] usbcore: registered new interface 
driver dvb_usb_cxusb

Apr 29 14:58:32 mythtv kernel: [ 2520.932221] xc2028 10-0061: Loading firmware 
for type=BASE F8MHZ (3), id 0000000000000000.
Apr 29 14:58:32 mythtv kernel: [ 2520.944221] cxusb: i2c wr: len=64 is too big!
Apr 29 14:58:32 mythtv kernel: [ 2520.944221] 
Apr 29 14:58:32 mythtv kernel: [ 2520.944226] xc2028 10-0061: i2c output error: 
rc = -95 (should be 64)
Apr 29 14:58:32 mythtv kernel: [ 2520.944228] xc2028 10-0061: -95 returned from 
send
Apr 29 14:58:32 mythtv kernel: [ 2520.944231] xc2028 10-0061: Error -22 while 
loading base firmware
<repeats 8 times>

I have located the origin of each of these messages:

Apr 29 14:58:32 mythtv kernel: [ 2520.932221] xc2028 10-0061: Loading firmware 
for type=BASE F8MHZ (3), id 0000000000000000.
drivers/media/tuners/tuner-xc2028.c
static int load_firmware(struct dvb_frontend *fe, unsigned int type,
                         v4l2_std_id *id)

        tuner_info("Loading firmware for type=");
        dump_firm_type(priv->firm[pos].type);
        printk("(%x), id %016llx.\n", priv->firm[pos].type,
               (unsigned long long)*id);

further down

                /* Sends message chunks */
                while (size > 0) {
                        int len = (size < priv->ctrl.max_len - 1) ?
                                   size : priv->ctrl.max_len - 1;

                        memcpy(buf + 1, p, len);

                        rc = i2c_send(priv, buf, len + 1);
                        if (rc < 0) {
                                tuner_err("%d returned from send\n", rc);
                                return -EINVAL;
                        }

                        p += len;
                        size -= len;
                }

i2c_send is a macro, defined near the top of tuner-xc2028.c

#define i2c_send(priv, buf, size) ({                                    \
        int _rc;                                                        \
        _rc = tuner_i2c_xfer_send(&priv->i2c_props, buf, size);         \
        if (size != _rc)                                                \
                tuner_info("i2c output error: rc = %d (should be %d)\n",\
                           _rc, (int)size);                             \
        if (priv->ctrl.msleep)                                          \
                msleep(priv->ctrl.msleep);                              \
        _rc;                                                            \
})

tuner_i2c_xfer_send
drivers/media/tuners/tuner-i2c.h

static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, char *buf, 
int len)
{
        struct i2c_msg msg = { .addr = props->addr, .flags = 0,
                               .buf = buf, .len = len };
        int ret = i2c_transfer(props->adap, &msg, 1);

        return (ret == 1) ? len : ret;
}

FIXME I don't understand how it gets from there to what comes next.
These messages must be produced by i2c_transfer!

Apr 29 14:58:32 mythtv kernel: [ 2520.944221] cxusb: i2c wr: len=64 is
too big!

drivers/media/usb/dvb-usb/cxusb.c
static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
                          int num)
                          
                        /* write only */
                        u8 obuf[MAX_XFER_SIZE], ibuf;

                        if (2 + msg[i].len > sizeof(obuf)) {
                                warn("i2c wr: len=%d is too big!\n",
                                     msg[i].len);
                                ret = -EOPNOTSUPP;
                                goto unlock;
                        }

                        
Apr 29 14:58:32 mythtv kernel: [ 2520.944221] 

FIXME I don't understand where this line comes from.

Apr 29 14:58:32 mythtv kernel: [ 2520.944226] xc2028 10-0061: i2c output
error: rc = -95 (should be 64)

This message comes from tuner-xc2028.c
i2c_send macro
-95 is the return code of tuner_i2c_xfer_send, which in turn is the return code 
of i2c_transfer.
include/uapi/asm-generic/errno.h
#define EOPNOTSUPP      95      /* Operation not supported on transport 
endpoint */

Apr 29 14:58:32 mythtv kernel: [ 2520.944228] xc2028 10-0061: -95 returned from 
send
drivers/media/tuners/tuner-xc2028.c load_firmware
                /* Sends message chunks */
                while (size > 0) {
                        int len = (size < priv->ctrl.max_len - 1) ?
                                   size : priv->ctrl.max_len - 1;

                        memcpy(buf + 1, p, len);

                        rc = i2c_send(priv, buf, len + 1);
                        if (rc < 0) {
                                tuner_err("%d returned from send\n", rc);
                                return -EINVAL;
                        }

                        p += len;
                        size -= len;
                }


Apr 29 14:58:32 mythtv kernel: [ 2520.944231] xc2028 10-0061: Error -22 while 
loading base firmware
include/uapi/asm-generic/errno-base.h
#define EINVAL          22      /* Invalid argument */


It seems that the MAX_XFER_SIZE is inconsistent between several places:

drivers/media/tuners/tuner-xc2028.c
/* Max transfer size done by I2C transfer functions */
#define MAX_XFER_SIZE  80

drivers/media/usb/dvb-usb/cxusb.c
/* Max transfer size done by I2C transfer functions */
#define MAX_XFER_SIZE  64

In fact, it would seem that tuner-xc2028.c should have 
/* Max transfer size done by I2C transfer functions */
#define MAX_XFER_SIZE  62
because cxusb_i2c_xfer requires 2 extra bytes for its own purposes.

There are a great many definitions of MAX_XFER_SIZE under drivers/media .
Many are 64, some are 128, some are 256! There needs to be consistency!!!
It seems that the macro should be defined in ONE place instead of
separately in every .c file!


After making this change, the system logs appear as follows:
=============================================================
Apr 29 21:06:35 mythtv kernel: [  155.767660] dvb-usb: found a 'DViCO 
FusionHDTV DVB-T Dual Digital 4' in warm state.
Apr 29 21:06:35 mythtv kernel: [  155.767793] dvb-usb: will pass the complete 
MPEG2 transport stream to the software demuxer.
Apr 29 21:06:35 mythtv kernel: [  155.798893] DVB: registering new adapter 
(DViCO FusionHDTV DVB-T Dual Digital 4)
Apr 29 21:06:35 mythtv kernel: [  155.949154] usb 3-1: DVB: registering adapter 
1 frontend 0 (Zarlink ZL10353 DVB-T)...
Apr 29 21:06:35 mythtv kernel: [  155.964139] xc2028 10-0061: creating new 
instance
Apr 29 21:06:35 mythtv kernel: [  155.964143] xc2028 10-0061: type set to 
XCeive xc2028/xc3028 tuner
Apr 29 21:06:35 mythtv kernel: [  155.964714] input: IR-receiver inside an USB 
DVB receiver as 
/devices/pci0000:00/0000:00:1e.0/0000:05:01.2/usb3/3-1/input/input16
Apr 29 21:06:35 mythtv kernel: [  155.964838] dvb-usb: schedule remote query 
interval to 100 msecs.
Apr 29 21:06:35 mythtv kernel: [  155.964901] dvb-usb: DViCO FusionHDTV DVB-T 
Dual Digital 4 successfully initialized and connected.
Apr 29 21:06:35 mythtv kernel: [  155.964923] dvb-usb: found a 'DViCO 
FusionHDTV DVB-T Dual Digital 4' in warm state.
Apr 29 21:06:35 mythtv kernel: [  155.965068] dvb-usb: will pass the complete 
MPEG2 transport stream to the software demuxer.
Apr 29 21:06:35 mythtv kernel: [  155.973845] xc2028 10-0061: Loading 80 
firmware images from xc3028-v27.fw, type: xc2028 firmware, ver 2.7
Apr 29 21:06:35 mythtv kernel: [  155.996183] DVB: registering new adapter 
(DViCO FusionHDTV DVB-T Dual Digital 4)
Apr 29 21:06:35 mythtv kernel: [  156.044540] cxusb: No IR receiver detected on 
this device.
Apr 29 21:06:35 mythtv kernel: [  156.044549] usb 3-2: DVB: registering adapter 
2 frontend 0 (Zarlink ZL10353 DVB-T)...
Apr 29 21:06:35 mythtv kernel: [  156.044633] xc2028 11-0061: creating new 
instance
Apr 29 21:06:35 mythtv kernel: [  156.044636] xc2028 11-0061: type set to 
XCeive xc2028/xc3028 tuner
Apr 29 21:06:35 mythtv kernel: [  156.045705] xc2028 11-0061: Loading 80 
firmware images from xc3028-v27.fw, type: xc2028 firmware, ver 2.7
Apr 29 21:06:35 mythtv kernel: [  156.046917] dvb-usb: DViCO FusionHDTV DVB-T 
Dual Digital 4 successfully initialized and connected.
Apr 29 21:06:35 mythtv kernel: [  156.046957] usbcore: registered new interface 
driver dvb_usb_cxusb
=============================================================

It appears that the firmware has been loaded successfully.

-- 
You received this bug notification because you are a member of Ubuntu
Bugs, which is subscribed to Ubuntu.
https://bugs.launchpad.net/bugs/1291459

Title:
  ioctl FE_GET_INFO hangs with DViCO FusionHDTV DVB-T Dual Digital 4
  card

To manage notifications about this bug go to:
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1291459/+subscriptions

-- 
ubuntu-bugs mailing list
ubuntu-bugs@lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/ubuntu-bugs

Reply via email to