--- a/drivers/media/dvb/ttpci/budget-av.c 2008-07-13 23:51:29.000000000 +0200 +++ b/drivers/media/dvb/ttpci/budget-av.c 2008-08-18 21:53:10.000000000 +0200 @@ -65,10 +65,11 @@ struct budget_av { struct tasklet_struct ciintf_irq_tasklet; int slot_status; struct dvb_ca_en50221 ca; + struct mutex camlock; u8 reinitialise_demod:1; }; -static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot); +static int ciintf_unlocked_slot_shutdown(struct dvb_ca_en50221 *ca, int slot); /* GPIO Connections: @@ -128,7 +129,7 @@ static int i2c_writereg(struct i2c_adapt return i2c_transfer(i2c, &msgs, 1); } -static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) +static int ciintf_unlocked_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) { struct budget_av *budget_av = (struct budget_av *) ca->data; int result; @@ -141,9 +142,22 @@ static int ciintf_read_attribute_mem(str result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1); if (result == -ETIMEDOUT) { - ciintf_slot_shutdown(ca, slot); + ciintf_unlocked_slot_shutdown(ca, slot); printk(KERN_INFO "budget-av: cam ejected 1\n"); } + + return result; +} + +static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address) +{ + struct budget_av *budget_av = (struct budget_av *) ca->data; + int result; + + mutex_lock(&budget_av->camlock); + result = ciintf_unlocked_read_attribute_mem(ca, slot, address); + mutex_unlock(&budget_av->camlock); + return result; } @@ -155,14 +169,19 @@ static int ciintf_write_attribute_mem(st if (slot != 0) return -EINVAL; + mutex_lock(&budget_av->camlock); + saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI); udelay(1); result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1); if (result == -ETIMEDOUT) { - ciintf_slot_shutdown(ca, slot); + ciintf_unlocked_slot_shutdown(ca, slot); printk(KERN_INFO "budget-av: cam ejected 2\n"); } + + mutex_unlock(&budget_av->camlock); + return result; } @@ -174,15 +193,19 @@ static int ciintf_read_cam_control(struc if (slot != 0) return -EINVAL; + mutex_lock(&budget_av->camlock); + saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); udelay(1); result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0); if (result == -ETIMEDOUT) { - ciintf_slot_shutdown(ca, slot); + ciintf_unlocked_slot_shutdown(ca, slot); printk(KERN_INFO "budget-av: cam ejected 3\n"); - return -ETIMEDOUT; } + + mutex_unlock(&budget_av->camlock); + return result; } @@ -194,14 +217,19 @@ static int ciintf_write_cam_control(stru if (slot != 0) return -EINVAL; + mutex_lock(&budget_av->camlock); + saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO); udelay(1); result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0); if (result == -ETIMEDOUT) { - ciintf_slot_shutdown(ca, slot); + ciintf_unlocked_slot_shutdown(ca, slot); printk(KERN_INFO "budget-av: cam ejected 5\n"); } + + mutex_unlock(&budget_av->camlock); + return result; } @@ -213,6 +241,8 @@ static int ciintf_slot_reset(struct dvb_ if (slot != 0) return -EINVAL; + mutex_lock(&budget_av->camlock); + dprintk(1, "ciintf_slot_reset\n"); budget_av->slot_status = SLOTSTATUS_RESET; @@ -231,10 +261,12 @@ static int ciintf_slot_reset(struct dvb_ if (budget_av->reinitialise_demod) dvb_frontend_reinitialise(budget_av->budget.dvb_frontend); + mutex_unlock(&budget_av->camlock); + return 0; } -static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) +static int ciintf_unlocked_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) { struct budget_av *budget_av = (struct budget_av *) ca->data; struct saa7146_dev *saa = budget_av->budget.dev; @@ -250,6 +282,18 @@ static int ciintf_slot_shutdown(struct d return 0; } +static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot) +{ + struct budget_av *budget_av = (struct budget_av *) ca->data; + int result; + + mutex_lock(&budget_av->camlock); + result = ciintf_unlocked_slot_shutdown(ca, slot); + mutex_unlock(&budget_av->camlock); + + return result; +} + static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) { struct budget_av *budget_av = (struct budget_av *) ca->data; @@ -258,10 +302,13 @@ static int ciintf_slot_ts_enable(struct if (slot != 0) return -EINVAL; - dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status); + mutex_lock(&budget_av->camlock); + dprintk(1, "ciintf_slot_ts_enable: %d\n", budget_av->slot_status); ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA); + mutex_unlock(&budget_av->camlock); + return 0; } @@ -274,6 +321,8 @@ static int ciintf_poll_slot_status(struc if (slot != 0) return -EINVAL; + mutex_lock(&budget_av->camlock); + /* test the card detect line - needs to be done carefully * since it never goes high for some CAMs on this interface (e.g. topuptv) */ if (budget_av->slot_status == SLOTSTATUS_NONE) { @@ -302,8 +351,9 @@ static int ciintf_poll_slot_status(struc printk(KERN_INFO "budget-av: cam inserted B\n"); } else if (result < 0) { if (budget_av->slot_status != SLOTSTATUS_NONE) { - ciintf_slot_shutdown(ca, slot); + ciintf_unlocked_slot_shutdown(ca, slot); printk(KERN_INFO "budget-av: cam ejected 5\n"); + mutex_unlock(&budget_av->camlock); return 0; } } @@ -311,20 +361,23 @@ static int ciintf_poll_slot_status(struc /* read from attribute memory in reset/ready state to know when the CAM is ready */ if (budget_av->slot_status == SLOTSTATUS_RESET) { - result = ciintf_read_attribute_mem(ca, slot, 0); + result = ciintf_unlocked_read_attribute_mem(ca, slot, 0); if (result == 0x1d) { budget_av->slot_status = SLOTSTATUS_READY; } } /* work out correct return code */ + result = 0; if (budget_av->slot_status != SLOTSTATUS_NONE) { - if (budget_av->slot_status & SLOTSTATUS_READY) { - return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; - } - return DVB_CA_EN50221_POLL_CAM_PRESENT; + result = DVB_CA_EN50221_POLL_CAM_PRESENT; + if (budget_av->slot_status & SLOTSTATUS_READY) + result |= DVB_CA_EN50221_POLL_CAM_READY; } - return 0; + + mutex_unlock(&budget_av->camlock); + + return result; } static int ciintf_init(struct budget_av *budget_av) @@ -332,6 +385,7 @@ static int ciintf_init(struct budget_av struct saa7146_dev *saa = budget_av->budget.dev; int result; + mutex_init(&budget_av->camlock); memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221)); saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);