in sx8.c [1096:1220]
static void carm_fsm_task (struct work_struct *work)
{
struct carm_host *host =
container_of(work, struct carm_host, fsm_task);
unsigned long flags;
unsigned int state;
int rc, i, next_dev;
int reschedule = 0;
int new_state = HST_INVALID;
spin_lock_irqsave(&host->lock, flags);
state = host->state;
spin_unlock_irqrestore(&host->lock, flags);
DPRINTK("ENTER, state == %s\n", state_name[state]);
switch (state) {
case HST_PROBE_START:
new_state = HST_ALLOC_BUF;
reschedule = 1;
break;
case HST_ALLOC_BUF:
rc = carm_send_special(host, carm_fill_alloc_buf);
if (rc) {
new_state = HST_ERROR;
reschedule = 1;
}
break;
case HST_SYNC_TIME:
rc = carm_send_special(host, carm_fill_sync_time);
if (rc) {
new_state = HST_ERROR;
reschedule = 1;
}
break;
case HST_GET_FW_VER:
rc = carm_send_special(host, carm_fill_get_fw_ver);
if (rc) {
new_state = HST_ERROR;
reschedule = 1;
}
break;
case HST_PORT_SCAN:
rc = carm_send_special(host, carm_fill_scan_channels);
if (rc) {
new_state = HST_ERROR;
reschedule = 1;
}
break;
case HST_DEV_SCAN_START:
host->cur_scan_dev = -1;
new_state = HST_DEV_SCAN;
reschedule = 1;
break;
case HST_DEV_SCAN:
next_dev = -1;
for (i = host->cur_scan_dev + 1; i < CARM_MAX_PORTS; i++)
if (host->dev_present & (1 << i)) {
next_dev = i;
break;
}
if (next_dev >= 0) {
host->cur_scan_dev = next_dev;
rc = carm_array_info(host, next_dev);
if (rc) {
new_state = HST_ERROR;
reschedule = 1;
}
} else {
new_state = HST_DEV_ACTIVATE;
reschedule = 1;
}
break;
case HST_DEV_ACTIVATE: {
int activated = 0;
for (i = 0; i < CARM_MAX_PORTS; i++)
if (host->dev_active & (1 << i)) {
struct carm_port *port = &host->port[i];
struct gendisk *disk = port->disk;
set_capacity(disk, port->capacity);
host->probe_err = add_disk(disk);
if (!host->probe_err)
activated++;
else
break;
}
printk(KERN_INFO DRV_NAME "(%s): %d ports activated\n",
pci_name(host->pdev), activated);
new_state = HST_PROBE_FINISHED;
reschedule = 1;
break;
}
case HST_PROBE_FINISHED:
complete(&host->probe_comp);
break;
case HST_ERROR:
/* FIXME: TODO */
break;
default:
/* should never occur */
printk(KERN_ERR PFX "BUG: unknown state %d\n", state);
assert(0);
break;
}
if (new_state != HST_INVALID) {
spin_lock_irqsave(&host->lock, flags);
host->state = new_state;
spin_unlock_irqrestore(&host->lock, flags);
}
if (reschedule)
schedule_work(&host->fsm_task);
}