From 0f89cfe19aa961e1433080b1bb36ab7314248d36 Mon Sep 17 00:00:00 2001 From: Jasmin Jessich Date: Sat, 12 Aug 2017 18:31:16 +0200 Subject: [PATCH] ddbridge: Added mutex to CA interface functions This fixes CAM write errors on the DD Octopus CI dual card. Changed also the return values of wait_ci_ready and read_cam_control to -EIO. Signed-off-by: Jasmin Jessich --- ddbridge/ddbridge-core.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/ddbridge/ddbridge-core.c b/ddbridge/ddbridge-core.c index 95ce288..b288a1c 100644 --- a/ddbridge/ddbridge-core.c +++ b/ddbridge/ddbridge-core.c @@ -2470,7 +2470,7 @@ static int wait_ci_ready(struct ddb_ci *ci) break; usleep_range(1, 2); if ((--count) == 0) - return -1; + return -EIO; } while (1); return 0; } @@ -2483,10 +2483,12 @@ static int read_attribute_mem(struct dvb_ca_en50221 *ca, if (address > CI_BUFFER_SIZE) return -1; + mutex_lock(&ci->lock); ddbwritel(ci->port->dev, CI_READ_CMD | (1 << 16) | address, CI_DO_READ_ATTRIBUTES(ci->nr)); wait_ci_ready(ci); val = 0xff & ddbreadl(ci->port->dev, CI_BUFFER(ci->nr) + off); + mutex_unlock(&ci->lock); return val; } @@ -2495,9 +2497,11 @@ static int write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, { struct ddb_ci *ci = ca->data; + mutex_lock(&ci->lock); ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, CI_DO_ATTRIBUTE_RW(ci->nr)); wait_ci_ready(ci); + mutex_unlock(&ci->lock); return 0; } @@ -2508,6 +2512,7 @@ static int read_cam_control(struct dvb_ca_en50221 *ca, struct ddb_ci *ci = ca->data; u32 res; + mutex_lock(&ci->lock); ddbwritel(ci->port->dev, CI_READ_CMD | address, CI_DO_IO_RW(ci->nr)); ndelay(500); @@ -2516,9 +2521,12 @@ static int read_cam_control(struct dvb_ca_en50221 *ca, if (res & CI_READY) break; usleep_range(1, 2); - if ((--count) == 0) - return -1; + if ((--count) == 0) { + mutex_unlock(&ci->lock); + return -EIO; + } } while (1); + mutex_unlock(&ci->lock); return 0xff & res; } @@ -2527,9 +2535,11 @@ static int write_cam_control(struct dvb_ca_en50221 *ca, int slot, { struct ddb_ci *ci = ca->data; + mutex_lock(&ci->lock); ddbwritel(ci->port->dev, CI_WRITE_CMD | (value << 16) | address, CI_DO_IO_RW(ci->nr)); wait_ci_ready(ci); + mutex_unlock(&ci->lock); return 0; } @@ -2537,6 +2547,7 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot) { struct ddb_ci *ci = ca->data; + mutex_lock(&ci->lock); ddbwritel(ci->port->dev, CI_POWER_ON, CI_CONTROL(ci->nr)); msleep(100); @@ -2547,6 +2558,7 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot) udelay(20); ddbwritel(ci->port->dev, CI_ENABLE | CI_POWER_ON, CI_CONTROL(ci->nr)); + mutex_unlock(&ci->lock); return 0; } @@ -2554,27 +2566,36 @@ static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot) { struct ddb_ci *ci = ca->data; + mutex_lock(&ci->lock); ddbwritel(ci->port->dev, 0, CI_CONTROL(ci->nr)); msleep(300); + mutex_unlock(&ci->lock); return 0; } static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) { struct ddb_ci *ci = ca->data; - u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); + u32 val; + mutex_lock(&ci->lock); + val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); ddbwritel(ci->port->dev, val | CI_BYPASS_DISABLE, CI_CONTROL(ci->nr)); + mutex_unlock(&ci->lock); return 0; } static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) { struct ddb_ci *ci = ca->data; - u32 val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); + u32 val; int stat = 0; + mutex_lock(&ci->lock); + val = ddbreadl(ci->port->dev, CI_CONTROL(ci->nr)); + mutex_unlock(&ci->lock); + if (val & CI_CAM_DETECT) stat |= DVB_CA_EN50221_POLL_CAM_PRESENT; if (val & CI_CAM_READY) @@ -2605,6 +2626,7 @@ static void ci_attach(struct ddb_port *port) port->en = &ci->en; ci->port = port; ci->nr = port->nr - 2; + mutex_init(&ci->lock); } /****************************************************************************/