static int ina230_hotplug_notify(struct notifier_block *nb, unsigned long event,
				void *hcpu)
{
	struct ina230_data *data = container_of(nb, struct ina230_data,
						nb);
	struct i2c_client *client = data->client;

	if (event == CPU_ONLINE || event == CPU_DEAD)
		evaluate_state(client);

	return 0;
}
static int ina230_resume(struct i2c_client *client)
{
	evaluate_state(client);
	return 0;
}
static int ina230_resume(struct i2c_client *client)
{
	printk(KERN_INFO "[BPC] ina230_resume\n");
	evaluate_state(client);
	return 0;
}
/**
 * @name best_first_search
 *
 * Find the best segmentation by doing a best first search of the
 * solution space.
 */
void Wordrec::best_first_search(CHUNKS_RECORD *chunks_record,
                                WERD_CHOICE *best_choice,
                                WERD_CHOICE *raw_choice,
                                STATE *state,
                                DANGERR *fixpt,
                                STATE *best_state) {
  SEARCH_RECORD *the_search;
  inT16 keep_going;
  STATE guided_state;   // not used

  num_joints = chunks_record->ratings->dimension() - 1;
  the_search = new_search(chunks_record, num_joints,
                          best_choice, raw_choice, state);

  // The default state is initialized as the best choice.  In order to apply
  // segmentation adjustment, or any other contextual processing in permute,
  // we give the best choice a poor rating to force the processed raw choice
  // to be promoted to best choice.
  the_search->best_choice->set_rating(100000.0);
  evaluate_state(chunks_record, the_search, fixpt);
  if (permute_debug) {
    tprintf("\n\n\n =========== BestFirstSearch ==============\n");
    best_choice->print("**Initial BestChoice**");
  }

#ifndef GRAPHICS_DISABLED
  save_best_state(chunks_record);
#endif
  start_recording();
  FLOAT32 worst_priority = 2.0f * prioritize_state(chunks_record, the_search);
  if (worst_priority < wordrec_worst_state)
    worst_priority = wordrec_worst_state;
  if (segment_debug) {
    print_state("BestFirstSearch", best_state, num_joints);
  }

  guided_state = *state;
  do {
                                 /* Look for answer */
    if (!hash_lookup (the_search->closed_states, the_search->this_state)) {

      if (tord_blob_skip) {
        free_state (the_search->this_state);
        break;
      }

      guided_state = *(the_search->this_state);
      keep_going = evaluate_state(chunks_record, the_search, fixpt);
      hash_add (the_search->closed_states, the_search->this_state);

      if (!keep_going ||
          (the_search->num_states > wordrec_num_seg_states) ||
          (tord_blob_skip)) {
        if (segment_debug)
          tprintf("Breaking best_first_search on keep_going %s numstates %d\n",
                  ((keep_going) ? "T" :"F"), the_search->num_states);
        free_state (the_search->this_state);
        break;
      }

      FLOAT32 new_worst_priority = 2.0f * prioritize_state(chunks_record,
                                                           the_search);
      if (new_worst_priority < worst_priority) {
        if (segment_debug)
          tprintf("Lowering WorstPriority %f --> %f\n",
                  worst_priority, new_worst_priority);
        // Tighten the threshold for admitting new paths as better search
        // candidates are found.  After lowering this threshold, we can safely
        // popout everything that is worse than this score also.
        worst_priority = new_worst_priority;
      }
      expand_node(worst_priority, chunks_record, the_search);
    }

    free_state (the_search->this_state);
    num_popped++;
    the_search->this_state = pop_queue (the_search->open_states);
    if (segment_debug && !the_search->this_state)
      tprintf("No more states to evalaute after %d evals", num_popped);
  }
  while (the_search->this_state);

  state->part1 = the_search->best_state->part1;
  state->part2 = the_search->best_state->part2;
  stop_recording();
  if (permute_debug) {
    tprintf("\n\n\n =========== BestFirstSearch ==============\n");
            // best_choice->debug_string(getDict().getUnicharset()).string());
    best_choice->print("**Final BestChoice**");
  }
  // save the best_state stats
  delete_search(the_search);
}
static int __devinit ina230_probe(struct i2c_client *client,
				const struct i2c_device_id *id)
{
	struct ina230_data *data;
	int err;
	u8 i;

	data = devm_kzalloc(&client->dev, sizeof(struct ina230_data),
			    GFP_KERNEL);
	if (!data) {
		err = -ENOMEM;
		goto exit;
	}

	i2c_set_clientdata(client, data);
	data->pdata = client->dev.platform_data;
	data->running = false;
	data->nb.notifier_call = ina230_hotplug_notify;
	data->client = client;
	mutex_init(&data->mutex);

	err = i2c_smbus_write_word_data(client, INA230_CONFIG,
		__constant_cpu_to_be16(INA230_RESET));
	if (err < 0) {
		dev_err(&client->dev, "ina230 reset failure status: 0x%x\n",
			err);
		goto exit;
	}

	err = i2c_smbus_write_word_data(client, INA230_CAL,
		__constant_cpu_to_be16(0x1000));
	if (err < 0) {
		dev_err(&client->dev, "ina230 calibration failure status: 0x%x\n",
			err);
		goto exit;
	}

	for (i = 0; i < ARRAY_SIZE(ina230); i++) {
		err = device_create_file(&client->dev, &ina230[i].dev_attr);
		if (err) {
			dev_err(&client->dev, "device_create_file failed.\n");
			goto exit_remove;
		}
	}

	data->hwmon_dev = hwmon_device_register(&client->dev);
	if (IS_ERR(data->hwmon_dev)) {
		err = PTR_ERR(data->hwmon_dev);
		goto exit_remove;
	}

	this_dev = &client->dev;

	register_hotcpu_notifier(&(data->nb));

	evaluate_state(client);

	return 0;

exit_remove:
	for (i = 0; i < ARRAY_SIZE(ina230); i++)
		device_remove_file(&client->dev, &ina230[i].dev_attr);
exit:
	return err;
}