media: dvb_ca_en50221: Refactored dvb_ca_en50221_thread
Refactored "dvb_ca_en50221_thread" by moving the state machine into the new function "dvb_ca_en50221_thread_state_machine". This reduces the thread function size and reduces the structural complexity and of course gives us more space to meet the line length goal in the new function. Signed-off-by: Jasmin Jessich <jasmin@anw.at> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
parent
d105d08344
commit
a004b70e70
@ -1063,19 +1063,220 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca)
|
|||||||
ca->delay = curdelay;
|
ca->delay = curdelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thread state machine for one CA slot to perform the data transfer.
|
||||||
|
*
|
||||||
|
* @ca: CA instance.
|
||||||
|
* @slot: Slot to process.
|
||||||
|
*/
|
||||||
|
static void dvb_ca_en50221_thread_state_machine(struct dvb_ca_private *ca,
|
||||||
|
int slot)
|
||||||
|
{
|
||||||
|
struct dvb_ca_slot *sl = &ca->slot_info[slot];
|
||||||
|
int flags;
|
||||||
|
int status;
|
||||||
|
int pktcount;
|
||||||
|
void *rxbuf;
|
||||||
|
|
||||||
|
mutex_lock(&sl->slot_lock);
|
||||||
|
|
||||||
|
/* check the cam status + deal with CAMCHANGEs */
|
||||||
|
while (dvb_ca_en50221_check_camstatus(ca, slot)) {
|
||||||
|
/* clear down an old CI slot if necessary */
|
||||||
|
if (sl->slot_state != DVB_CA_SLOTSTATE_NONE)
|
||||||
|
dvb_ca_en50221_slot_shutdown(ca, slot);
|
||||||
|
|
||||||
|
/* if a CAM is NOW present, initialise it */
|
||||||
|
if (sl->camchange_type == DVB_CA_EN50221_CAMCHANGE_INSERTED)
|
||||||
|
sl->slot_state = DVB_CA_SLOTSTATE_UNINITIALISED;
|
||||||
|
|
||||||
|
/* we've handled one CAMCHANGE */
|
||||||
|
dvb_ca_en50221_thread_update_delay(ca);
|
||||||
|
atomic_dec(&sl->camchange_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CAM state machine */
|
||||||
|
switch (sl->slot_state) {
|
||||||
|
case DVB_CA_SLOTSTATE_NONE:
|
||||||
|
case DVB_CA_SLOTSTATE_INVALID:
|
||||||
|
/* no action needed */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DVB_CA_SLOTSTATE_UNINITIALISED:
|
||||||
|
sl->slot_state = DVB_CA_SLOTSTATE_WAITREADY;
|
||||||
|
ca->pub->slot_reset(ca->pub, slot);
|
||||||
|
sl->timeout = jiffies + (INIT_TIMEOUT_SECS * HZ);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DVB_CA_SLOTSTATE_WAITREADY:
|
||||||
|
if (time_after(jiffies, sl->timeout)) {
|
||||||
|
pr_err("dvb_ca adaptor %d: PC card did not respond :(\n",
|
||||||
|
ca->dvbdev->adapter->num);
|
||||||
|
sl->slot_state = DVB_CA_SLOTSTATE_INVALID;
|
||||||
|
dvb_ca_en50221_thread_update_delay(ca);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* no other action needed; will automatically change state when
|
||||||
|
* ready
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DVB_CA_SLOTSTATE_VALIDATE:
|
||||||
|
if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) {
|
||||||
|
/*
|
||||||
|
* we need this extra check for annoying interfaces like
|
||||||
|
* the budget-av
|
||||||
|
*/
|
||||||
|
if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE))
|
||||||
|
&& (ca->pub->poll_slot_status)) {
|
||||||
|
status = ca->pub->poll_slot_status(ca->pub,
|
||||||
|
slot, 0);
|
||||||
|
if (!(status &
|
||||||
|
DVB_CA_EN50221_POLL_CAM_PRESENT)) {
|
||||||
|
sl->slot_state = DVB_CA_SLOTSTATE_NONE;
|
||||||
|
dvb_ca_en50221_thread_update_delay(ca);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_err("dvb_ca adapter %d: Invalid PC card inserted :(\n",
|
||||||
|
ca->dvbdev->adapter->num);
|
||||||
|
sl->slot_state = DVB_CA_SLOTSTATE_INVALID;
|
||||||
|
dvb_ca_en50221_thread_update_delay(ca);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (dvb_ca_en50221_set_configoption(ca, slot) != 0) {
|
||||||
|
pr_err("dvb_ca adapter %d: Unable to initialise CAM :(\n",
|
||||||
|
ca->dvbdev->adapter->num);
|
||||||
|
sl->slot_state = DVB_CA_SLOTSTATE_INVALID;
|
||||||
|
dvb_ca_en50221_thread_update_delay(ca);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ca->pub->write_cam_control(ca->pub, slot,
|
||||||
|
CTRLIF_COMMAND,
|
||||||
|
CMDREG_RS) != 0) {
|
||||||
|
pr_err("dvb_ca adapter %d: Unable to reset CAM IF\n",
|
||||||
|
ca->dvbdev->adapter->num);
|
||||||
|
sl->slot_state = DVB_CA_SLOTSTATE_INVALID;
|
||||||
|
dvb_ca_en50221_thread_update_delay(ca);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dprintk("DVB CAM validated successfully\n");
|
||||||
|
|
||||||
|
sl->timeout = jiffies + (INIT_TIMEOUT_SECS * HZ);
|
||||||
|
sl->slot_state = DVB_CA_SLOTSTATE_WAITFR;
|
||||||
|
ca->wakeup = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DVB_CA_SLOTSTATE_WAITFR:
|
||||||
|
if (time_after(jiffies, sl->timeout)) {
|
||||||
|
pr_err("dvb_ca adapter %d: DVB CAM did not respond :(\n",
|
||||||
|
ca->dvbdev->adapter->num);
|
||||||
|
sl->slot_state = DVB_CA_SLOTSTATE_INVALID;
|
||||||
|
dvb_ca_en50221_thread_update_delay(ca);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS);
|
||||||
|
if (flags & STATUSREG_FR) {
|
||||||
|
sl->slot_state = DVB_CA_SLOTSTATE_LINKINIT;
|
||||||
|
ca->wakeup = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DVB_CA_SLOTSTATE_LINKINIT:
|
||||||
|
if (dvb_ca_en50221_link_init(ca, slot) != 0) {
|
||||||
|
/*
|
||||||
|
* we need this extra check for annoying interfaces like
|
||||||
|
* the budget-av
|
||||||
|
*/
|
||||||
|
if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE))
|
||||||
|
&& (ca->pub->poll_slot_status)) {
|
||||||
|
status = ca->pub->poll_slot_status(ca->pub,
|
||||||
|
slot, 0);
|
||||||
|
if (!(status &
|
||||||
|
DVB_CA_EN50221_POLL_CAM_PRESENT)) {
|
||||||
|
sl->slot_state = DVB_CA_SLOTSTATE_NONE;
|
||||||
|
dvb_ca_en50221_thread_update_delay(ca);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_err("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n",
|
||||||
|
ca->dvbdev->adapter->num);
|
||||||
|
sl->slot_state = DVB_CA_SLOTSTATE_UNINITIALISED;
|
||||||
|
dvb_ca_en50221_thread_update_delay(ca);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sl->rx_buffer.data) {
|
||||||
|
rxbuf = vmalloc(RX_BUFFER_SIZE);
|
||||||
|
if (!rxbuf) {
|
||||||
|
pr_err("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n",
|
||||||
|
ca->dvbdev->adapter->num);
|
||||||
|
sl->slot_state = DVB_CA_SLOTSTATE_INVALID;
|
||||||
|
dvb_ca_en50221_thread_update_delay(ca);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dvb_ringbuffer_init(&sl->rx_buffer, rxbuf,
|
||||||
|
RX_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ca->pub->slot_ts_enable(ca->pub, slot);
|
||||||
|
sl->slot_state = DVB_CA_SLOTSTATE_RUNNING;
|
||||||
|
dvb_ca_en50221_thread_update_delay(ca);
|
||||||
|
pr_err("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n",
|
||||||
|
ca->dvbdev->adapter->num);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DVB_CA_SLOTSTATE_RUNNING:
|
||||||
|
if (!ca->open)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* poll slots for data */
|
||||||
|
pktcount = 0;
|
||||||
|
while (dvb_ca_en50221_read_data(ca, slot, NULL, 0) > 0) {
|
||||||
|
if (!ca->open)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if a CAMCHANGE occurred at some point, do not do any
|
||||||
|
* more processing of this slot
|
||||||
|
*/
|
||||||
|
if (dvb_ca_en50221_check_camstatus(ca, slot)) {
|
||||||
|
/*
|
||||||
|
* we dont want to sleep on the next iteration
|
||||||
|
* so we can handle the cam change
|
||||||
|
*/
|
||||||
|
ca->wakeup = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check if we've hit our limit this time */
|
||||||
|
if (++pktcount >= MAX_RX_PACKETS_PER_ITERATION) {
|
||||||
|
/*
|
||||||
|
* dont sleep; there is likely to be more data
|
||||||
|
* to read
|
||||||
|
*/
|
||||||
|
ca->wakeup = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&sl->slot_lock);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kernel thread which monitors CA slots for CAM changes, and performs data transfers.
|
* Kernel thread which monitors CA slots for CAM changes, and performs data
|
||||||
|
* transfers.
|
||||||
*/
|
*/
|
||||||
static int dvb_ca_en50221_thread(void *data)
|
static int dvb_ca_en50221_thread(void *data)
|
||||||
{
|
{
|
||||||
struct dvb_ca_private *ca = data;
|
struct dvb_ca_private *ca = data;
|
||||||
int slot;
|
int slot;
|
||||||
int flags;
|
|
||||||
int status;
|
|
||||||
int pktcount;
|
|
||||||
void *rxbuf;
|
|
||||||
|
|
||||||
dprintk("%s\n", __func__);
|
dprintk("%s\n", __func__);
|
||||||
|
|
||||||
@ -1094,176 +1295,8 @@ static int dvb_ca_en50221_thread(void *data)
|
|||||||
ca->wakeup = 0;
|
ca->wakeup = 0;
|
||||||
|
|
||||||
/* go through all the slots processing them */
|
/* go through all the slots processing them */
|
||||||
for (slot = 0; slot < ca->slot_count; slot++) {
|
for (slot = 0; slot < ca->slot_count; slot++)
|
||||||
|
dvb_ca_en50221_thread_state_machine(ca, slot);
|
||||||
mutex_lock(&ca->slot_info[slot].slot_lock);
|
|
||||||
|
|
||||||
// check the cam status + deal with CAMCHANGEs
|
|
||||||
while (dvb_ca_en50221_check_camstatus(ca, slot)) {
|
|
||||||
/* clear down an old CI slot if necessary */
|
|
||||||
if (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_NONE)
|
|
||||||
dvb_ca_en50221_slot_shutdown(ca, slot);
|
|
||||||
|
|
||||||
/* if a CAM is NOW present, initialise it */
|
|
||||||
if (ca->slot_info[slot].camchange_type == DVB_CA_EN50221_CAMCHANGE_INSERTED) {
|
|
||||||
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_UNINITIALISED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we've handled one CAMCHANGE */
|
|
||||||
dvb_ca_en50221_thread_update_delay(ca);
|
|
||||||
atomic_dec(&ca->slot_info[slot].camchange_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
// CAM state machine
|
|
||||||
switch (ca->slot_info[slot].slot_state) {
|
|
||||||
case DVB_CA_SLOTSTATE_NONE:
|
|
||||||
case DVB_CA_SLOTSTATE_INVALID:
|
|
||||||
// no action needed
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DVB_CA_SLOTSTATE_UNINITIALISED:
|
|
||||||
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITREADY;
|
|
||||||
ca->pub->slot_reset(ca->pub, slot);
|
|
||||||
ca->slot_info[slot].timeout = jiffies + (INIT_TIMEOUT_SECS * HZ);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DVB_CA_SLOTSTATE_WAITREADY:
|
|
||||||
if (time_after(jiffies, ca->slot_info[slot].timeout)) {
|
|
||||||
pr_err("dvb_ca adaptor %d: PC card did not respond :(\n",
|
|
||||||
ca->dvbdev->adapter->num);
|
|
||||||
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
|
|
||||||
dvb_ca_en50221_thread_update_delay(ca);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// no other action needed; will automatically change state when ready
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DVB_CA_SLOTSTATE_VALIDATE:
|
|
||||||
if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) {
|
|
||||||
/* we need this extra check for annoying interfaces like the budget-av */
|
|
||||||
if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
|
|
||||||
(ca->pub->poll_slot_status)) {
|
|
||||||
status = ca->pub->poll_slot_status(ca->pub, slot, 0);
|
|
||||||
if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
|
|
||||||
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
|
|
||||||
dvb_ca_en50221_thread_update_delay(ca);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_err("dvb_ca adapter %d: Invalid PC card inserted :(\n",
|
|
||||||
ca->dvbdev->adapter->num);
|
|
||||||
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
|
|
||||||
dvb_ca_en50221_thread_update_delay(ca);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (dvb_ca_en50221_set_configoption(ca, slot) != 0) {
|
|
||||||
pr_err("dvb_ca adapter %d: Unable to initialise CAM :(\n",
|
|
||||||
ca->dvbdev->adapter->num);
|
|
||||||
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
|
|
||||||
dvb_ca_en50221_thread_update_delay(ca);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (ca->pub->write_cam_control(ca->pub, slot,
|
|
||||||
CTRLIF_COMMAND, CMDREG_RS) != 0) {
|
|
||||||
pr_err("dvb_ca adapter %d: Unable to reset CAM IF\n",
|
|
||||||
ca->dvbdev->adapter->num);
|
|
||||||
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
|
|
||||||
dvb_ca_en50221_thread_update_delay(ca);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dprintk("DVB CAM validated successfully\n");
|
|
||||||
|
|
||||||
ca->slot_info[slot].timeout = jiffies + (INIT_TIMEOUT_SECS * HZ);
|
|
||||||
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITFR;
|
|
||||||
ca->wakeup = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DVB_CA_SLOTSTATE_WAITFR:
|
|
||||||
if (time_after(jiffies, ca->slot_info[slot].timeout)) {
|
|
||||||
pr_err("dvb_ca adapter %d: DVB CAM did not respond :(\n",
|
|
||||||
ca->dvbdev->adapter->num);
|
|
||||||
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
|
|
||||||
dvb_ca_en50221_thread_update_delay(ca);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
flags = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS);
|
|
||||||
if (flags & STATUSREG_FR) {
|
|
||||||
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT;
|
|
||||||
ca->wakeup = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DVB_CA_SLOTSTATE_LINKINIT:
|
|
||||||
if (dvb_ca_en50221_link_init(ca, slot) != 0) {
|
|
||||||
/* we need this extra check for annoying interfaces like the budget-av */
|
|
||||||
if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) &&
|
|
||||||
(ca->pub->poll_slot_status)) {
|
|
||||||
status = ca->pub->poll_slot_status(ca->pub, slot, 0);
|
|
||||||
if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) {
|
|
||||||
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE;
|
|
||||||
dvb_ca_en50221_thread_update_delay(ca);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_err("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n",
|
|
||||||
ca->dvbdev->adapter->num);
|
|
||||||
ca->slot_info[slot].slot_state =
|
|
||||||
DVB_CA_SLOTSTATE_UNINITIALISED;
|
|
||||||
dvb_ca_en50221_thread_update_delay(ca);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ca->slot_info[slot].rx_buffer.data == NULL) {
|
|
||||||
rxbuf = vmalloc(RX_BUFFER_SIZE);
|
|
||||||
if (rxbuf == NULL) {
|
|
||||||
pr_err("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n",
|
|
||||||
ca->dvbdev->adapter->num);
|
|
||||||
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID;
|
|
||||||
dvb_ca_en50221_thread_update_delay(ca);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dvb_ringbuffer_init(&ca->slot_info[slot].rx_buffer, rxbuf, RX_BUFFER_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
ca->pub->slot_ts_enable(ca->pub, slot);
|
|
||||||
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING;
|
|
||||||
dvb_ca_en50221_thread_update_delay(ca);
|
|
||||||
pr_err("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n",
|
|
||||||
ca->dvbdev->adapter->num);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DVB_CA_SLOTSTATE_RUNNING:
|
|
||||||
if (!ca->open)
|
|
||||||
break;
|
|
||||||
|
|
||||||
// poll slots for data
|
|
||||||
pktcount = 0;
|
|
||||||
while ((status = dvb_ca_en50221_read_data(ca, slot, NULL, 0)) > 0) {
|
|
||||||
if (!ca->open)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* if a CAMCHANGE occurred at some point, do not do any more processing of this slot */
|
|
||||||
if (dvb_ca_en50221_check_camstatus(ca, slot)) {
|
|
||||||
// we dont want to sleep on the next iteration so we can handle the cam change
|
|
||||||
ca->wakeup = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check if we've hit our limit this time */
|
|
||||||
if (++pktcount >= MAX_RX_PACKETS_PER_ITERATION) {
|
|
||||||
// dont sleep; there is likely to be more data to read
|
|
||||||
ca->wakeup = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_unlock(&ca->slot_info[slot].slot_lock);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user