Em 15-01-2012 22:16, Mauro Carvalho Chehab escreveu: > Em 15-01-2012 19:47, Antti Palosaari escreveu: >> On 01/15/2012 11:08 PM, Mauro Carvalho Chehab wrote: >>> There was a bug at the error code handling on dvb-fe-tool: basically, if it >>> can't open >>> a device, it were using a NULL pointer. It was likely fixed by this commit: >>> >>> http://git.linuxtv.org/v4l-utils.git/commit/1f669eed5433d17df4d8fb1fa43d2886f99d3991 >> >> That bug was fixed as I tested. >> >> But could you tell why dvb-fe-tool --set-delsys=DVBC/ANNEX_A calls >> get_frontent() ? > > That's what happens here, at the application level: > > $ strace dvb-fe-tool -d DVBC/ANNEX_A > > open("/dev/dvb/adapter0/frontend0", O_RDWR) = 3 > ioctl(3, FE_GET_INFO, 0xb070c4) = 0 > fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0 > mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = > 0x7f37922be000 > write(1, "Device DRXK DVB-C DVB-T (/dev/dv"..., 68Device DRXK DVB-C DVB-T > (/dev/dvb/adapter0/frontend0) capabilities: > ) = 68 > write(1, "\tCAN_FEC_1_2 CAN_FEC_2_3 CAN_FEC"..., 245 CAN_FEC_1_2 CAN_FEC_2_3 > CAN_FEC_3_4 CAN_FEC_5_6 CAN_FEC_7_8 CAN_FEC_AUTO CAN_GUARD_INTERVAL_AUTO > CAN_HIERARCHY_AUTO CAN_INVERSION_AUTO CAN_MUTE_TS CAN_QAM_16 CAN_QAM_32 > CAN_QAM_64 CAN_QAM_128 CAN_QAM_256 CAN_RECOVER CAN_TRANSMISSION_MODE_AUTO > ) = 245 > ioctl(3, FE_GET_PROPERTY, 0x7fff326ce310) = 0 > write(1, "DVB API Version 5.5, Current v5 "..., 54DVB API Version 5.5, > Current v5 delivery system: DVBT > ) = 54 > ioctl(3, FE_GET_PROPERTY, 0x7fff326ce310) = 0 > write(1, "Supported delivery systems: DVBC"..., 62Supported delivery systems: > DVBC/ANNEX_A DVBC/ANNEX_C [DVBT] > ) = 62 > write(1, "Changing delivery system to: DVB"..., 42Changing delivery system > to: DVBC/ANNEX_A > ) = 42 > ioctl(3, FE_SET_PROPERTY, 0x7fff326ce340) = 0 > close(3) = 0 > exit_group(0) = ? > > > The first FE_GET_PROPERTY reads the DVB API version and the current delivery > system: > > parms->dvb_prop[0].cmd = DTV_API_VERSION; > parms->dvb_prop[1].cmd = DTV_DELIVERY_SYSTEM; > > dtv_prop.num = 2; > dtv_prop.props = parms->dvb_prop; > > /* Detect a DVBv3 device */ > if (ioctl(fd, FE_GET_PROPERTY, &dtv_prop) == -1) { > parms->dvb_prop[0].u.data = 0x300; > parms->dvb_prop[1].u.data = SYS_UNDEFINED; > } > parms->version = parms->dvb_prop[0].u.data; > parms->current_sys = parms->dvb_prop[1].u.data; > > The second FE_GET_PROPERTY is used only if DVB API v5.5 or upper is detected, > and does: > > parms->dvb_prop[0].cmd = DTV_ENUM_DELSYS; > parms->n_props = 1; > dtv_prop.num = 1; > dtv_prop.props = parms->dvb_prop; > if (ioctl(fd, FE_GET_PROPERTY, &dtv_prop) == -1) { > perror("FE_GET_PROPERTY"); > dvb_v5_free(parms); > close(fd); > return NULL; > } > > Both were called inside dvb_fe_open(). > > The FE_SET_PROPERTY changes the property inside the DVBv5 cache, > at dvb_set_sys(): > > dvb_prop[0].cmd = DTV_DELIVERY_SYSTEM; > dvb_prop[0].u.data = sys; > prop.num = 1; > prop.props = dvb_prop; > > if (ioctl(parms->fd, FE_SET_PROPERTY, &prop) == -1) { > perror("Set delivery system"); > return errno; > } > > The FE_SET_PROPERTY doesn't call a DTV_TUNE, so it shouldn't be calling the > set frontend methods inside the driver. > > So, from the userspace applications standpoint, I'm not seeing anything wrong. > >> That will cause this kind of calls in demod driver: >> init() >> get_frontend() >> get_frontend() >> sleep() >> >> My guess is that it resolves current delivery system. But as demod is >> usually sleeping (not tuned) at that phase it does not know frontend >> settings asked, like modulation etc. In case of cxd2820r those are available >> after set_frontend() call. I think I will add check and return -EINVAL in >> that case. > > > What seems to be happening at dvb-core/dvb_frontend.h is due to this code: > > if(cmd == FE_GET_PROPERTY) { > ... > /* > * Fills the cache out struct with the cache contents, plus > * the data retrieved from get_frontend. > */ > dtv_get_frontend(fe, NULL); > for (i = 0; i < tvps->num; i++) { > err = dtv_property_process_get(fe, c, tvp + i, file); > if (err < 0) > goto out; > (tvp + i)->result = err; > } > > E. g. even if the FE_GET_PROPERTY is only reading the DVB version and calling > DTV_ENUM_DELSYS, it is calling the dtv_get_frontend() to retrieve more data. > > What it can be done is to do something like: > > static bool need_get_frontend() > { > ... > for (i = 0; i < tvps->num; i++) > ... > } > > if (need_get_frontend(tvps)) > dtv_get_frontend(fe, NULL); > for (i = 0; i < tvps->num; i++) { > err = dtv_property_process_get(fe, c, tvp + i, file); > if (err < 0) > goto out; > (tvp + i)->result = err; > } > > And add some logic inside need_get_frontend() to return false if the > FE_GET_PROPERTY only wants static info, like DTV_ENUM_DELSYS, DTV_VERSION > and DTV_DELIVERY_SYSTEM.
The enclosed patch should do the trick - [PATCH RFC] Don't call get_frontend() if not needed If the frontend is in idle state, or a FE_GET_PROPERTY is called for reading the enumsys, api version or delivery system, don't call the frontend, as it is not needed. Signed-off-by: Mauro Carvalho Chehab <mche...@redhat.com> PS.: There's one extra printk here for test purposes. Of course, this should be removed at the final version. diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index f5fa7aa..3c80c92 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1234,6 +1234,8 @@ static int dtv_get_frontend(struct dvb_frontend *fe, { int r; +printk("%s()\n", __func__); + if (fe->ops.get_frontend) { r = fe->ops.get_frontend(fe); if (unlikely(r < 0)) @@ -1739,12 +1741,35 @@ static int dvb_frontend_ioctl(struct file *file, return err; } +static bool need_get_frontend_call(struct dtv_properties *tvps, + struct dtv_property *tvp) +{ + int i; + + /* + * If the DTV command is just informational or cache read, + * don't bother to call the frontend to handle. + */ + for (i = 0; i < tvps->num; i++) { + switch(tvp->cmd) { + case DTV_ENUM_DELSYS: + case DTV_DELIVERY_SYSTEM: + case DTV_API_VERSION: + break; + default: + return true; + } + } + return false; +} + static int dvb_frontend_ioctl_properties(struct file *file, unsigned int cmd, void *parg) { struct dvb_device *dvbdev = file->private_data; struct dvb_frontend *fe = dvbdev->priv; struct dtv_frontend_properties *c = &fe->dtv_property_cache; + struct dvb_frontend_private *fepriv = fe->frontend_priv; int err = 0; struct dtv_properties *tvps = NULL; @@ -1812,7 +1837,8 @@ static int dvb_frontend_ioctl_properties(struct file *file, * Fills the cache out struct with the cache contents, plus * the data retrieved from get_frontend. */ - dtv_get_frontend(fe, NULL); + if (need_get_frontend_call(tvps, tvp) && fepriv->state != FESTATE_IDLE) + dtv_get_frontend(fe, NULL); for (i = 0; i < tvps->num; i++) { err = dtv_property_process_get(fe, c, tvp + i, file); if (err < 0) -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html