/*
 * UWB radio (channel) management.
 *
 * Copyright (C) 2008 Cambridge Silicon Radio Ltd.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version
 * 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#include <linux/kernel.h>
#include <linux/uwb.h>

#include "uwb-internal.h"


static int uwb_radio_select_channel(struct uwb_rc *rc)
{
	/*
	 * Default to channel 9 (BG1, TFC1) unless the user has
	 * selected a specific channel or there are no active PALs.
	 */
	if (rc->active_pals == 0)
		return -1;
	if (rc->beaconing_forced)
		return rc->beaconing_forced;
	return 9;
}


/*
 * Notify all active PALs that the channel has changed.
 */
static void uwb_radio_channel_changed(struct uwb_rc *rc, int channel)
{
	struct uwb_pal *pal;

	list_for_each_entry(pal, &rc->pals, node) {
		if (pal->channel && channel != pal->channel) {
			pal->channel = channel;
			if (pal->channel_changed)
				pal->channel_changed(pal, pal->channel);
		}
	}
}

/*
 * Change to a new channel and notify any active PALs of the new
 * channel.
 *
 * When stopping the radio, PALs need to be notified first so they can
 * terminate any active reservations.
 */
static int uwb_radio_change_channel(struct uwb_rc *rc, int channel)
{
	int ret = 0;

	if (channel == -1)
		uwb_radio_channel_changed(rc, channel);

	if (channel != rc->beaconing) {
		if (rc->beaconing != -1 && channel != -1) {
			/*
			 * FIXME: should signal the channel change
			 * with a Channel Change IE.
			 */
			ret = uwb_radio_change_channel(rc, -1);
			if (ret < 0)
				return ret;
		}
		ret = uwb_rc_beacon(rc, channel, 0);
	}

	if (channel != -1)
		uwb_radio_channel_changed(rc, rc->beaconing);

	return ret;
}

/**
 * uwb_radio_start - request that the radio be started
 * @pal: the PAL making the request.
 *
 * If the radio is not already active, aa suitable channel is selected
 * and beacons are started.
 */
int uwb_radio_start(struct uwb_pal *pal)
{
	struct uwb_rc *rc = pal->rc;
	int ret = 0;

	mutex_lock(&rc->uwb_dev.mutex);

	if (!pal->channel) {
		pal->channel = -1;
		rc->active_pals++;
		ret = uwb_radio_change_channel(rc, uwb_radio_select_channel(rc));
	}

	mutex_unlock(&rc->uwb_dev.mutex);
	return ret;
}
EXPORT_SYMBOL_GPL(uwb_radio_start);

/**
 * uwb_radio_stop - request tha the radio be stopped.
 * @pal: the PAL making the request.
 *
 * Stops the radio if no other PAL is making use of it.
 */
void uwb_radio_stop(struct uwb_pal *pal)
{
	struct uwb_rc *rc = pal->rc;

	mutex_lock(&rc->uwb_dev.mutex);

	if (pal->channel) {
		rc->active_pals--;
		uwb_radio_change_channel(rc, uwb_radio_select_channel(rc));
		pal->channel = 0;
	}

	mutex_unlock(&rc->uwb_dev.mutex);
}
EXPORT_SYMBOL_GPL(uwb_radio_stop);

/*
 * uwb_radio_force_channel - force a specific channel to be used
 * @rc: the radio controller.
 * @channel: the channel to use; -1 to force the radio to stop; 0 to
 *   use the default channel selection algorithm.
 */
int uwb_radio_force_channel(struct uwb_rc *rc, int channel)
{
	int ret = 0;

	mutex_lock(&rc->uwb_dev.mutex);

	rc->beaconing_forced = channel;
	ret = uwb_radio_change_channel(rc, uwb_radio_select_channel(rc));

	mutex_unlock(&rc->uwb_dev.mutex);
	return ret;
}

/*
 * uwb_radio_setup - setup the radio manager
 * @rc: the radio controller.
 *
 * The radio controller is reset to ensure it's in a known state
 * before it's used.
 */
int uwb_radio_setup(struct uwb_rc *rc)
{
	return uwb_rc_reset(rc);
}

/*
 * uwb_radio_reset_state - reset any radio manager state
 * @rc: the radio controller.
 *
 * All internal radio manager state is reset to values corresponding
 * to a reset radio controller.
 */
void uwb_radio_reset_state(struct uwb_rc *rc)
{
	struct uwb_pal *pal;

	mutex_lock(&rc->uwb_dev.mutex);

	list_for_each_entry(pal, &rc->pals, node) {
		if (pal->channel) {
			pal->channel = -1;
			if (pal->channel_changed)
				pal->channel_changed(pal, -1);
		}
	}

	rc->beaconing = -1;
	rc->scanning = -1;

	mutex_unlock(&rc->uwb_dev.mutex);
}

/*
 * uwb_radio_shutdown - shutdown the radio manager
 * @rc: the radio controller.
 *
 * The radio controller is reset.
 */
void uwb_radio_shutdown(struct uwb_rc *rc)
{
	uwb_radio_reset_state(rc);
	uwb_rc_reset(rc);
}
