提交 a004b70e 编写于 作者: J Jasmin Jessich 提交者: Mauro Carvalho Chehab

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: NJasmin Jessich <jasmin@anw.at>
Signed-off-by: NMauro Carvalho Chehab <mchehab@s-opensource.com>
上级 d105d083
...@@ -1063,207 +1063,240 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca) ...@@ -1063,207 +1063,240 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca)
ca->delay = curdelay; ca->delay = curdelay;
} }
/** /**
* Kernel thread which monitors CA slots for CAM changes, and performs data transfers. * Thread state machine for one CA slot to perform the data transfer.
*
* @ca: CA instance.
* @slot: Slot to process.
*/ */
static int dvb_ca_en50221_thread(void *data) static void dvb_ca_en50221_thread_state_machine(struct dvb_ca_private *ca,
int slot)
{ {
struct dvb_ca_private *ca = data; struct dvb_ca_slot *sl = &ca->slot_info[slot];
int slot;
int flags; int flags;
int status; int status;
int pktcount; int pktcount;
void *rxbuf; void *rxbuf;
dprintk("%s\n", __func__); mutex_lock(&sl->slot_lock);
/* choose the correct initial delay */ /* check the cam status + deal with CAMCHANGEs */
dvb_ca_en50221_thread_update_delay(ca); 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);
/* main loop */ /* if a CAM is NOW present, initialise it */
while (!kthread_should_stop()) { if (sl->camchange_type == DVB_CA_EN50221_CAMCHANGE_INSERTED)
/* sleep for a bit */ sl->slot_state = DVB_CA_SLOTSTATE_UNINITIALISED;
if (!ca->wakeup) {
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(ca->delay);
if (kthread_should_stop())
return 0;
}
ca->wakeup = 0;
/* go through all the slots processing them */ /* we've handled one CAMCHANGE */
for (slot = 0; slot < ca->slot_count; slot++) { dvb_ca_en50221_thread_update_delay(ca);
atomic_dec(&sl->camchange_count);
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 */ /* CAM state machine */
dvb_ca_en50221_thread_update_delay(ca); switch (sl->slot_state) {
atomic_dec(&ca->slot_info[slot].camchange_count); case DVB_CA_SLOTSTATE_NONE:
} case DVB_CA_SLOTSTATE_INVALID:
/* no action needed */
break;
// CAM state machine case DVB_CA_SLOTSTATE_UNINITIALISED:
switch (ca->slot_info[slot].slot_state) { sl->slot_state = DVB_CA_SLOTSTATE_WAITREADY;
case DVB_CA_SLOTSTATE_NONE: ca->pub->slot_reset(ca->pub, slot);
case DVB_CA_SLOTSTATE_INVALID: sl->timeout = jiffies + (INIT_TIMEOUT_SECS * HZ);
// no action needed break;
break;
case DVB_CA_SLOTSTATE_UNINITIALISED: case DVB_CA_SLOTSTATE_WAITREADY:
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITREADY; if (time_after(jiffies, sl->timeout)) {
ca->pub->slot_reset(ca->pub, slot); pr_err("dvb_ca adaptor %d: PC card did not respond :(\n",
ca->slot_info[slot].timeout = jiffies + (INIT_TIMEOUT_SECS * HZ); ca->dvbdev->adapter->num);
break; 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_WAITREADY: case DVB_CA_SLOTSTATE_VALIDATE:
if (time_after(jiffies, ca->slot_info[slot].timeout)) { if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) {
pr_err("dvb_ca adaptor %d: PC card did not respond :(\n", /*
ca->dvbdev->adapter->num); * we need this extra check for annoying interfaces like
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; * 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); dvb_ca_en50221_thread_update_delay(ca);
break; break;
} }
// no other action needed; will automatically change state when ready }
break;
case DVB_CA_SLOTSTATE_VALIDATE: pr_err("dvb_ca adapter %d: Invalid PC card inserted :(\n",
if (dvb_ca_en50221_parse_attributes(ca, slot) != 0) { ca->dvbdev->adapter->num);
/* we need this extra check for annoying interfaces like the budget-av */ sl->slot_state = DVB_CA_SLOTSTATE_INVALID;
if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) && dvb_ca_en50221_thread_update_delay(ca);
(ca->pub->poll_slot_status)) { break;
status = ca->pub->poll_slot_status(ca->pub, slot, 0); }
if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) { if (dvb_ca_en50221_set_configoption(ca, slot) != 0) {
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; pr_err("dvb_ca adapter %d: Unable to initialise CAM :(\n",
dvb_ca_en50221_thread_update_delay(ca); ca->dvbdev->adapter->num);
break; sl->slot_state = DVB_CA_SLOTSTATE_INVALID;
} dvb_ca_en50221_thread_update_delay(ca);
} break;
}
pr_err("dvb_ca adapter %d: Invalid PC card inserted :(\n", if (ca->pub->write_cam_control(ca->pub, slot,
ca->dvbdev->adapter->num); CTRLIF_COMMAND,
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; CMDREG_RS) != 0) {
dvb_ca_en50221_thread_update_delay(ca); pr_err("dvb_ca adapter %d: Unable to reset CAM IF\n",
break; ca->dvbdev->adapter->num);
} sl->slot_state = DVB_CA_SLOTSTATE_INVALID;
if (dvb_ca_en50221_set_configoption(ca, slot) != 0) { dvb_ca_en50221_thread_update_delay(ca);
pr_err("dvb_ca adapter %d: Unable to initialise CAM :(\n", break;
ca->dvbdev->adapter->num); }
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; dprintk("DVB CAM validated successfully\n");
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); sl->timeout = jiffies + (INIT_TIMEOUT_SECS * HZ);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_WAITFR; sl->slot_state = DVB_CA_SLOTSTATE_WAITFR;
ca->wakeup = 1; ca->wakeup = 1;
break; break;
case DVB_CA_SLOTSTATE_WAITFR: case DVB_CA_SLOTSTATE_WAITFR:
if (time_after(jiffies, ca->slot_info[slot].timeout)) { if (time_after(jiffies, sl->timeout)) {
pr_err("dvb_ca adapter %d: DVB CAM did not respond :(\n", pr_err("dvb_ca adapter %d: DVB CAM did not respond :(\n",
ca->dvbdev->adapter->num); ca->dvbdev->adapter->num);
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; sl->slot_state = DVB_CA_SLOTSTATE_INVALID;
dvb_ca_en50221_thread_update_delay(ca); dvb_ca_en50221_thread_update_delay(ca);
break; break;
} }
flags = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS); flags = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS);
if (flags & STATUSREG_FR) { if (flags & STATUSREG_FR) {
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; sl->slot_state = DVB_CA_SLOTSTATE_LINKINIT;
ca->wakeup = 1; ca->wakeup = 1;
} }
break; break;
case DVB_CA_SLOTSTATE_LINKINIT: case DVB_CA_SLOTSTATE_LINKINIT:
if (dvb_ca_en50221_link_init(ca, slot) != 0) { 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)) && * we need this extra check for annoying interfaces like
(ca->pub->poll_slot_status)) { * the budget-av
status = ca->pub->poll_slot_status(ca->pub, slot, 0); */
if (!(status & DVB_CA_EN50221_POLL_CAM_PRESENT)) { if ((!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE))
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_NONE; && (ca->pub->poll_slot_status)) {
dvb_ca_en50221_thread_update_delay(ca); status = ca->pub->poll_slot_status(ca->pub,
break; slot, 0);
} if (!(status &
} DVB_CA_EN50221_POLL_CAM_PRESENT)) {
sl->slot_state = DVB_CA_SLOTSTATE_NONE;
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); dvb_ca_en50221_thread_update_delay(ca);
break; break;
} }
}
if (ca->slot_info[slot].rx_buffer.data == NULL) { pr_err("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n",
rxbuf = vmalloc(RX_BUFFER_SIZE); ca->dvbdev->adapter->num);
if (rxbuf == NULL) { sl->slot_state = DVB_CA_SLOTSTATE_UNINITIALISED;
pr_err("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n", dvb_ca_en50221_thread_update_delay(ca);
ca->dvbdev->adapter->num); break;
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); if (!sl->rx_buffer.data) {
ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_RUNNING; rxbuf = vmalloc(RX_BUFFER_SIZE);
dvb_ca_en50221_thread_update_delay(ca); if (!rxbuf) {
pr_err("dvb_ca adapter %d: DVB CAM detected and initialised successfully\n", pr_err("dvb_ca adapter %d: Unable to allocate CAM rx buffer :(\n",
ca->dvbdev->adapter->num); ca->dvbdev->adapter->num);
sl->slot_state = DVB_CA_SLOTSTATE_INVALID;
dvb_ca_en50221_thread_update_delay(ca);
break; break;
}
dvb_ringbuffer_init(&sl->rx_buffer, rxbuf,
RX_BUFFER_SIZE);
}
case DVB_CA_SLOTSTATE_RUNNING: ca->pub->slot_ts_enable(ca->pub, slot);
if (!ca->open) sl->slot_state = DVB_CA_SLOTSTATE_RUNNING;
break; 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;
// poll slots for data case DVB_CA_SLOTSTATE_RUNNING:
pktcount = 0; if (!ca->open)
while ((status = dvb_ca_en50221_read_data(ca, slot, NULL, 0)) > 0) { break;
if (!ca->open)
break; /* poll slots for data */
pktcount = 0;
/* if a CAMCHANGE occurred at some point, do not do any more processing of this slot */ while (dvb_ca_en50221_read_data(ca, slot, NULL, 0) > 0) {
if (dvb_ca_en50221_check_camstatus(ca, slot)) { if (!ca->open)
// we dont want to sleep on the next iteration so we can handle the cam change break;
ca->wakeup = 1;
break; /*
} * if a CAMCHANGE occurred at some point, do not do any
* more processing of this slot
/* check if we've hit our limit this time */ */
if (++pktcount >= MAX_RX_PACKETS_PER_ITERATION) { if (dvb_ca_en50221_check_camstatus(ca, slot)) {
// dont sleep; there is likely to be more data to read /*
ca->wakeup = 1; * we dont want to sleep on the next iteration
break; * so we can handle the cam change
} */
} ca->wakeup = 1;
break; break;
} }
mutex_unlock(&ca->slot_info[slot].slot_lock); /* 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.
*/
static int dvb_ca_en50221_thread(void *data)
{
struct dvb_ca_private *ca = data;
int slot;
dprintk("%s\n", __func__);
/* choose the correct initial delay */
dvb_ca_en50221_thread_update_delay(ca);
/* main loop */
while (!kthread_should_stop()) {
/* sleep for a bit */
if (!ca->wakeup) {
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(ca->delay);
if (kthread_should_stop())
return 0;
} }
ca->wakeup = 0;
/* go through all the slots processing them */
for (slot = 0; slot < ca->slot_count; slot++)
dvb_ca_en50221_thread_state_machine(ca, slot);
} }
return 0; return 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册