12 Commits

Author SHA1 Message Date
mvoelkel
411a142c21 Release 0.9.20
some CAMs are really slow, increase timeout for link init
  more I2C debugging
  added README.md
  store ids for all links in link structure and add devid attribute
  - fix dynamic fmode changes - 69Mhz no longer needed for MaxS8 on GT link - show state in GT link change
  do not reference eth_rebuild_header in newer kernels
  fix reference to struct
  inc copyright year
  inc version number
  added support for SPANSION flash
2015-09-17 16:28:15 +02:00
Ralph Metzler
5932c6c52f some CAMs are really slow, increase timeout for link init 2015-09-16 22:50:53 +02:00
Ralph Metzler
4209e3a03a more I2C debugging 2015-09-09 12:13:11 +02:00
mvoelkel
71e4972863 added README.md 2015-09-07 16:50:43 +02:00
Ralph Metzler
4f53aa9a1b store ids for all links in link structure and add devid attribute 2015-09-06 19:08:57 +02:00
Ralph Metzler
4e1b527c35 - fix dynamic fmode changes
- 69Mhz no longer needed for MaxS8 on GT link
- show state in GT link change
2015-08-31 20:53:22 +02:00
Ralph Metzler
5c4db2b594 do not reference eth_rebuild_header in newer kernels 2015-08-31 20:51:44 +02:00
Ralph Metzler
5ed590a3c7 fix reference to struct 2015-08-31 20:47:19 +02:00
Ralph Metzler
5af6007152 inc copyright year 2015-08-31 20:46:28 +02:00
Ralph Metzler
151770c0d8 inc version number 2015-08-31 20:45:25 +02:00
Ralph Metzler
f2b6dbabd7 added support for SPANSION flash 2015-08-31 20:43:20 +02:00
mvoelkel
4c7e7afc84 Add gitignore 2015-08-05 18:37:42 +02:00
12 changed files with 264 additions and 63 deletions

15
.gitignore vendored Normal file
View File

@@ -0,0 +1,15 @@
#
# Normal rules
#
.*
*.o
*.o.*
*.a
*.s
*.ko
*.so
*.so.dbg
*.orig
*~
\#*#

11
README.md Normal file
View File

@@ -0,0 +1,11 @@
# DDBridge Driver
###Prepare for Building
TBD
###Building
TBD

View File

@@ -61,6 +61,7 @@ struct ddflash {
uint32_t type;
uint32_t version;
uint32_t flash_type;
uint32_t sector_size;
uint32_t size;
@@ -88,6 +89,8 @@ enum {
ATMEL_AT45DB642D = 1,
SSTI_SST25VF016B = 2,
SSTI_SST25VF032B = 3,
SSTI_SST25VF064C = 4,
SPANSION_S25FL116K = 5,
};
static int flashread(int ddb, uint8_t *buf, uint32_t addr, uint32_t len)
@@ -131,6 +134,128 @@ void dump(const uint8_t *b, int l)
}
}
int flashwrite_pagemode(struct ddflash *ddf, int dev, uint32_t FlashOffset,
uint8_t LockBits, uint32_t fw_off)
{
int err = 0;
uint8_t cmd[260];
int i, j;
uint32_t flen, blen;
blen = flen = lseek(dev, 0, SEEK_END) - fw_off;
if (blen % 0xff)
blen = (blen + 0xff) & 0xffffff00;
printf("blen = %u, flen = %u\n", blen, flen);
do {
cmd[0] = 0x50; // EWSR
err = flashio(ddf->fd, cmd, 1, NULL, 0);
if (err < 0)
break;
cmd[0] = 0x01; // WRSR
cmd[1] = 0x00; // BPx = 0, Unlock all blocks
err = flashio(ddf->fd, cmd, 2, NULL, 0);
if (err < 0)
break;
for (i = 0; i < flen; i += 4096) {
if ((i & 0xFFFF) == 0)
printf(" Erase %08x\n", FlashOffset + i);
cmd[0] = 0x06; // WREN
err = flashio(ddf->fd, cmd, 1, NULL, 0);
if (err < 0)
break;
cmd[0] = 0x20; // Sector erase ( 4Kb)
cmd[1] = ( (( FlashOffset + i ) >> 16) & 0xFF );
cmd[2] = ( (( FlashOffset + i ) >> 8) & 0xFF );
cmd[3] = 0x00;
err = flashio(ddf->fd, cmd, 4, NULL, 0);
if (err < 0)
break;
while (1) {
cmd[0] = 0x05; // RDRS
err = flashio(ddf->fd, cmd, 1, &cmd[0], 1);
if (err < 0)
break;
if ((cmd[0] & 0x01) == 0)
break;
}
if (err < 0)
break;
}
if (err < 0)
break;
for (j = blen - 256; j >= 0; j -= 256 ) {
uint32_t len = 256;
ssize_t rlen;
if (lseek(dev, j + fw_off, SEEK_SET) < 0) {
printf("seek error\n");
return -1;
}
if (flen - j < 256) {
len = flen - j;
memset(ddf->buffer, 0xff, 256);
}
rlen = read(dev, ddf->buffer, len);
if (rlen < 0 || rlen != len) {
printf("file read error %d,%d at %u\n", rlen, errno, j);
return -1;
}
printf ("write %u bytes at %08x\n", len, j);
if ((j & 0xFFFF) == 0)
printf(" Programm %08x\n", FlashOffset + j);
cmd[0] = 0x06; // WREN
err = flashio(ddf->fd, cmd, 1, NULL, 0);
if (err < 0)
break;
cmd[0] = 0x02; // PP
cmd[1] = ( (( FlashOffset + j ) >> 16) & 0xFF );
cmd[2] = ( (( FlashOffset + j ) >> 8) & 0xFF );
cmd[3] = 0x00;
memcpy(&cmd[4], ddf->buffer, 256);
err = flashio(ddf->fd, cmd, 260, NULL, 0);
if (err < 0)
break;
while(1) {
cmd[0] = 0x05; // RDRS
err = flashio(ddf->fd, cmd,1, &cmd[0], 1);
if (err < 0)
break;
if ((cmd[0] & 0x01) == 0)
break;
}
if (err < 0)
break;
}
if (err < 0)
break;
cmd[0] = 0x50; // EWSR
err = flashio(ddf->fd, cmd, 1, NULL, 0);
if (err < 0)
break;
cmd[0] = 0x01; // WRSR
cmd[1] = LockBits; // BPx = 0, Lock all blocks
err = flashio(ddf->fd, cmd, 2, NULL, 0);
} while(0);
return err;
}
static int flashwrite_SSTI(struct ddflash *ddf, int fs, uint32_t FlashOffset, uint32_t maxlen, uint32_t fw_off)
{
int err = 0;
@@ -261,7 +386,16 @@ static int flashwrite_SSTI(struct ddflash *ddf, int fs, uint32_t FlashOffset, ui
static int flashwrite(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen, uint32_t fw_off)
{
flashwrite_SSTI(ddf, fs, addr, maxlen, fw_off);
switch (ddf->flash_type) {
case SSTI_SST25VF016B:
case SSTI_SST25VF032B:
return flashwrite_SSTI(ddf, fs, addr, maxlen, fw_off);
case SSTI_SST25VF064C:
return flashwrite_pagemode(ddf, fs, addr, 0x3c, fw_off);
case SPANSION_S25FL116K:
return flashwrite_pagemode(ddf, fs, addr, 0x1c, fw_off);
}
return -1;
}
static int flashcmp(struct ddflash *ddf, int fs, uint32_t addr, uint32_t maxlen, uint32_t fw_off)
@@ -314,29 +448,41 @@ static int flash_detect(struct ddflash *ddf)
return r;
if (id[0] == 0xBF && id[1] == 0x25 && id[2] == 0x41) {
r = SSTI_SST25VF016B;
//printf("Flash: SSTI SST25VF016B 16 MBit\n");
ddf->flash_type = SSTI_SST25VF016B;
printf("Flash: SSTI SST25VF016B 16 MBit\n");
ddf->sector_size = 4096;
ddf->size = 0x200000;
} else if (id[0] == 0xBF && id[1] == 0x25 && id[2] == 0x4A) {
r = SSTI_SST25VF032B;
//printf("Flash: SSTI SST25VF032B 32 MBit\n");
ddf->flash_type = SSTI_SST25VF032B;
printf("Flash: SSTI SST25VF032B 32 MBit\n");
ddf->sector_size = 4096;
ddf->size = 0x400000;
} else if (id[0] == 0xBF && id[1] == 0x25 && id[2] == 0x4B) {
ddf->flash_type = SSTI_SST25VF064C;
printf("Flash: SSTI SST25VF064C 64 MBit\n");
ddf->sector_size = 4096;
ddf->size = 0x800000;
} else if (id[0] == 0x01 && id[1] == 0x40 && id[2] == 0x15) {
ddf->flash_type = SPANSION_S25FL116K;
printf("Flash: SPANSION S25FL116K 16 MBit\n");
ddf->sector_size = 4096;
ddf->size = 0x200000;
} else if (id[0] == 0x1F && id[1] == 0x28) {
r = ATMEL_AT45DB642D;
//printf("Flash: Atmel AT45DB642D 64 MBit\n");
ddf->flash_type = ATMEL_AT45DB642D;
printf("Flash: Atmel AT45DB642D 64 MBit\n");
ddf->sector_size = 1024;
ddf->size = 0x800000;
} else {
r = UNKNOWN_FLASH;
//printf("Unknown Flash Flash ID = %02x %02x %02x\n", id[0], id[1], id[2]);
printf("Unknown Flash Flash ID = %02x %02x %02x\n", id[0], id[1], id[2]);
return -1;
}
if (ddf->sector_size) {
ddf->buffer = malloc(ddf->sector_size);
//printf("allocated buffer %08x@%08x\n", ddf->sector_size, (uint32_t) ddf->buffer);
printf("allocated buffer %08x@%08x\n", ddf->sector_size, (uint32_t) ddf->buffer);
if (!ddf->buffer)
return -1;
}
return r;
return 0;
}
@@ -777,6 +923,8 @@ int main(int argc, char **argv)
}
}
flash = flash_detect(&ddf);
if (flash < 0)
return -1;
get_id(&ddf);
res = update_flash(&ddf);

View File

@@ -1292,6 +1292,8 @@ static int lnb_command(struct ddb *dev, u32 link, u32 lnb, u32 cmd)
break;
msleep(20);
}
if (c == 10)
pr_info("lnb_command lnb = %08x cmd = %08x\n", lnb, cmd);
return 0;
}
@@ -1542,14 +1544,15 @@ static int mxl_fw_read(void *priv, u8 *buf, u32 len)
return ddbridge_flashread(dev, link->nr, buf, 0xc0000, len);
}
static int lnb_init_fmode(struct ddb *dev, struct ddb_link *link, u32 fmode)
static int lnb_init_fmode(struct ddb *dev, struct ddb_link *link, u32 fm)
{
u32 l = link->nr;
if (link->lnb.setmode == fmode)
if (link->lnb.fmode == fm)
return 0;
if (fmode == 2 || fmode == 1) {
mutex_lock(&link->lnb.lock);
pr_info("Set fmode link %u = %u\n", l, fm);
mutex_lock(&link->lnb.lock);
if (fm == 2 || fm == 1) {
lnb_set_tone(dev, l, 0, SEC_TONE_OFF);
if (old_quattro) {
lnb_set_tone(dev, l, 1, SEC_TONE_OFF);
@@ -1559,9 +1562,9 @@ static int lnb_init_fmode(struct ddb *dev, struct ddb_link *link, u32 fmode)
lnb_set_tone(dev, l, 2, SEC_TONE_OFF);
}
lnb_set_tone(dev, l, 3, SEC_TONE_ON);
mutex_unlock(&link->lnb.lock);
}
link->lnb.setmode = fmode;
link->lnb.fmode = fm;
mutex_unlock(&link->lnb.lock);
return 0;
}
@@ -1584,12 +1587,10 @@ static int fe_attach_mxl5xx(struct ddb_input *input)
struct mxl5xx_cfg cfg;
int demod, tuner;
link->lnb.fmode = fmode;
cfg = mxl5xx;
cfg.fw_priv = link;
if (dev->link[0].info->type == DDB_OCTONET)
cfg.ts_clk = 69;
;//cfg.ts_clk = 69;
demod = input->nr;
tuner = demod & 3;
@@ -3660,10 +3661,10 @@ static long ddb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct ddb_id ddbid;
ddbid.vendor = dev->ids.vendor;
ddbid.device = dev->ids.device;
ddbid.subvendor = dev->ids.subvendor;
ddbid.subdevice = dev->ids.subdevice;
ddbid.vendor = dev->link[0].ids.vendor;
ddbid.device = dev->link[0].ids.device;
ddbid.subvendor = dev->link[0].ids.subvendor;
ddbid.subdevice = dev->link[0].ids.subdevice;
ddbid.hw = ddbreadl(dev, 0);
ddbid.regmap = ddbreadl(dev, 4);
if (copy_to_user(parg, &ddbid, sizeof(ddbid)))
@@ -4164,7 +4165,7 @@ static ssize_t version_show(struct device *device,
struct ddb *dev = dev_get_drvdata(device);
return sprintf(buf, "%08x %08x\n",
dev->ids.hwid, dev->ids.regmapid);
dev->link[0].ids.hwid, dev->link[0].ids.regmapid);
}
static ssize_t hwid_show(struct device *device,
@@ -4172,7 +4173,7 @@ static ssize_t hwid_show(struct device *device,
{
struct ddb *dev = dev_get_drvdata(device);
return sprintf(buf, "0x%08X\n", dev->ids.hwid);
return sprintf(buf, "0x%08X\n", dev->link[0].ids.hwid);
}
static ssize_t regmap_show(struct device *device,
@@ -4180,7 +4181,7 @@ static ssize_t regmap_show(struct device *device,
{
struct ddb *dev = dev_get_drvdata(device);
return sprintf(buf, "0x%08X\n", dev->ids.regmapid);
return sprintf(buf, "0x%08X\n", dev->link[0].ids.regmapid);
}
static ssize_t vlan_show(struct device *device,
@@ -4217,6 +4218,15 @@ static ssize_t fmode_show(struct device *device,
return sprintf(buf, "%u\n", dev->link[num].lnb.fmode);
}
static ssize_t devid_show(struct device *device,
struct device_attribute *attr, char *buf)
{
int num = attr->attr.name[5] - 0x30;
struct ddb *dev = dev_get_drvdata(device);
return sprintf(buf, "%08x\n", dev->link[num].ids.devid);
}
static ssize_t fmode_store(struct device *device, struct device_attribute *attr,
const char *buf, size_t count)
{
@@ -4228,8 +4238,7 @@ static ssize_t fmode_store(struct device *device, struct device_attribute *attr,
return -EINVAL;
if (val > 3)
return -EINVAL;
dev->link[num].lnb.fmode = val;
lnb_init_fmode(dev, &dev->link[num], fmode);
lnb_init_fmode(dev, &dev->link[num], val);
return count;
}
@@ -4247,6 +4256,10 @@ static struct device_attribute ddb_attrs[] = {
__ATTR(fmode1, 0664, fmode_show, fmode_store),
__ATTR(fmode2, 0664, fmode_show, fmode_store),
__ATTR(fmode3, 0664, fmode_show, fmode_store),
__ATTR_MRO(devid0, devid_show),
__ATTR_MRO(devid1, devid_show),
__ATTR_MRO(devid2, devid_show),
__ATTR_MRO(devid3, devid_show),
__ATTR_RO(hwid),
__ATTR_RO(regmap),
#if 0
@@ -4421,7 +4434,11 @@ static void ddb_device_destroy(struct ddb *dev)
static void gtl_link_handler(unsigned long priv)
{
printk("GT link change\n");
struct ddb *dev = (struct ddb *) priv;
u32 regs = dev->link[0].info->regmap->gtl->base;
printk("GT link change: %u\n",
(1 & ddbreadl(dev, regs)));
}
static void link_tasklet(unsigned long data)
@@ -4502,6 +4519,7 @@ static int ddb_gtl_init_link(struct ddb *dev, u32 l)
spin_lock_init(&link->lock);
mutex_init(&link->lnb.lock);
link->lnb.fmode = 0xffffffff;
mutex_init(&link->flash_mutex);
if (!(1 & ddbreadl(dev, regs))) {
@@ -4531,6 +4549,7 @@ static int ddb_gtl_init_link(struct ddb *dev, u32 l)
id);
return -1;
}
link->ids.devid = id;
ddbwritel(dev, 1, 0x1a0);

View File

@@ -113,20 +113,27 @@ static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd)
ddbwritel(dev, (adr << 9) | cmd, i2c->regs + I2C_COMMAND);
stat = wait_for_completion_timeout(&i2c->completion, HZ);
val = ddbreadl(dev, i2c->regs + I2C_COMMAND);
if (stat == 0) {
pr_err("DDBridge I2C timeout, card %d, port %d, link %u\n",
dev->nr, i2c->nr, i2c->link);
#ifdef CONFIG_PCI_MSI
{ /* MSI debugging*/
#if 1
{
u32 istat = ddbreadl(dev, INTERRUPT_STATUS);
dev_err(dev->dev, "DDBridge IRS %08x\n", istat);
ddbwritel(dev, istat, INTERRUPT_ACK);
if (istat & 1) {
ddbwritel(dev, istat & 1, INTERRUPT_ACK);
} else {
u32 mon = ddbreadl(dev, i2c->regs + I2C_MONITOR);
dev_err(dev->dev, "I2C cmd=%08x mon=%08x\n",
val, mon);
}
}
#endif
return -EIO;
}
val = ddbreadl(dev, i2c->regs + I2C_COMMAND);
if (val & 0x70000)
return -EIO;
return 0;

View File

@@ -102,7 +102,7 @@ static int ns_set_pids(struct dvbnss *nss)
struct ddb *dev = input->port->dev;
struct ddb_ns *dns = (struct ddb_ns *) nss->priv;
if (dev->ids.devid == 0x0301dd01) {
if (dev->link[0].ids.devid == 0x0301dd01) {
u32 sys = 0;
int pid, j = 1;
@@ -134,7 +134,7 @@ static int ns_set_pid(struct dvbnss *nss, u16 pid)
u32 off = STREAM_PIDS(dns->nr);
#if 1
if (dev->ids.devid == 0x0301dd01) {
if (dev->link[0].ids.devid == 0x0301dd01) {
if (pid & 0x2000) {
if (pid & 0x8000)
memset(nss->pids, 0xff, 0x400);

View File

@@ -112,10 +112,10 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
dev->dev = &pdev->dev;
pci_set_drvdata(pdev, dev);
dev->ids.vendor = id->vendor;
dev->ids.device = id->device;
dev->ids.subvendor = id->subvendor;
dev->ids.subdevice = id->subdevice;
dev->link[0].ids.vendor = id->vendor;
dev->link[0].ids.device = id->device;
dev->link[0].ids.subvendor = id->subvendor;
dev->link[0].ids.subdevice = id->subdevice;
dev->link[0].dev = dev;
dev->link[0].info = (struct ddb_info *) id->driver_data;
@@ -136,11 +136,11 @@ static int __devinit ddb_probe(struct pci_dev *pdev,
goto fail;
}
dev->ids.hwid = ddbreadl(dev, 0);
dev->ids.regmapid = ddbreadl(dev, 4);
dev->link[0].ids.hwid = ddbreadl(dev, 0);
dev->link[0].ids.regmapid = ddbreadl(dev, 4);
pr_info("DDBridge: HW %08x REGMAP %08x\n",
dev->ids.hwid, dev->ids.regmapid);
dev->link[0].ids.hwid, dev->link[0].ids.regmapid);
if (dev->link[0].info->ns_num) {
int i;

View File

@@ -371,7 +371,6 @@ struct ddb_lnb {
u32 voltage[4];
u32 voltages;
u32 fmode;
u32 setmode;
};
struct ddb_link {
@@ -383,13 +382,13 @@ struct ddb_link {
struct mutex flash_mutex;
struct ddb_lnb lnb;
struct tasklet_struct tasklet;
struct ddb_ids ids;
};
struct ddb {
struct pci_dev *pdev;
struct platform_device *pfdev;
struct device *dev;
struct ddb_ids ids;
int msi;
struct workqueue_struct *wq;
@@ -706,6 +705,6 @@ void ddbridge_mod_rate_handler(unsigned long data);
int ddbridge_flashread(struct ddb *dev, u32 link, u8 *buf, u32 addr, u32 len);
#define DDBRIDGE_VERSION "0.9.19"
#define DDBRIDGE_VERSION "0.9.20"
#endif

View File

@@ -156,28 +156,28 @@ static int __init octonet_probe(struct platform_device *pdev)
return -ENOMEM;
}
dev->ids.hwid = ddbreadl(dev, 0);
dev->ids.regmapid = ddbreadl(dev, 4);
dev->ids.devid = ddbreadl(dev, 8);
dev->ids.mac = ddbreadl(dev, 12);
dev->link[0].ids.hwid = ddbreadl(dev, 0);
dev->link[0].ids.regmapid = ddbreadl(dev, 4);
dev->link[0].ids.devid = ddbreadl(dev, 8);
dev->link[0].ids.mac = ddbreadl(dev, 12);
dev->ids.vendor = dev->ids.devid & 0xffff;
dev->ids.device = dev->ids.devid >> 16;
dev->ids.subvendor = dev->ids.devid & 0xffff;
dev->ids.subdevice = dev->ids.devid >> 16;
dev->link[0].ids.vendor = dev->link[0].ids.devid & 0xffff;
dev->link[0].ids.device = dev->link[0].ids.devid >> 16;
dev->link[0].ids.subvendor = dev->link[0].ids.devid & 0xffff;
dev->link[0].ids.subdevice = dev->link[0].ids.devid >> 16;
dev->link[0].dev = dev;
if (dev->ids.devid == 0x0300dd01)
if (dev->link[0].ids.devid == 0x0300dd01)
dev->link[0].info = &ddb_octonet;
else if (dev->ids.devid == 0x0301dd01)
else if (dev->link[0].ids.devid == 0x0301dd01)
dev->link[0].info = &ddb_octonet_jse;
else if (dev->ids.devid == 0x0307dd01)
else if (dev->link[0].ids.devid == 0x0307dd01)
dev->link[0].info = &ddb_octonet_gtl;
else
dev->link[0].info = &ddb_octonet_tbd;
pr_info("HW %08x REGMAP %08x\n", dev->ids.hwid, dev->ids.regmapid);
pr_info("MAC %08x DEVID %08x\n", dev->ids.mac, dev->ids.devid);
pr_info("HW %08x REGMAP %08x\n", dev->link[0].ids.hwid, dev->link[0].ids.regmapid);
pr_info("MAC %08x DEVID %08x\n", dev->link[0].ids.mac, dev->link[0].ids.devid);
ddbwritel(dev, 0, ETHER_CONTROL);
ddbwritel(dev, 0x00000000, INTERRUPT_ENABLE);
@@ -233,7 +233,7 @@ static __init int init_octonet(void)
int res;
pr_info("Digital Devices OctopusNet driver " DDBRIDGE_VERSION
", Copyright (C) 2010-14 Digital Devices GmbH\n");
", Copyright (C) 2010-15 Digital Devices GmbH\n");
res = ddb_class_create();
if (res)
return res;

View File

@@ -315,7 +315,7 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot)
/* read the buffer size from the CAM */
if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SR)) != 0)
return ret;
if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, HZ / 10)) != 0)
if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, HZ)) != 0)
return ret;
if ((ret = dvb_ca_en50221_read_data(ca, slot, buf, 2)) != 2)
return -EIO;

View File

@@ -1227,7 +1227,9 @@ static int dvb_net_stop(struct net_device *dev)
static const struct header_ops dvb_header_ops = {
.create = eth_header,
.parse = eth_header_parse,
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 2)
.rebuild = eth_rebuild_header,
#endif
};

View File

@@ -585,7 +585,7 @@ static int sleep(struct dvb_frontend *fe)
if (p->tuner_in_use == state->tuner)
break;
}
if (p == &state->base->mxls)
if (&p->mxl == &state->base->mxls)
enable_tuner(state, state->tuner, 0);
mutex_unlock(&state->base->tune_lock);
}