/*
 * WiMedia Logical Link Control Protocol (WLP)
 *
 * Copyright (C) 2007 Intel Corporation
 * Reinette Chatre <reinette.chatre@intel.com>
 *
 * 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, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 *
 *
 * Implementation of the WLP association protocol.
 *
 * FIXME: Docs
 *
 * A UWB network interface will configure a WSS through wlp_wss_setup() after
 * the interface has been assigned a MAC address, typically after
 * "ifconfig" has been called. When the interface goes down it should call
 * wlp_wss_remove().
 *
 * When the WSS is ready for use the user interacts via sysfs to create,
 * discover, and activate WSS.
 *
 * wlp_wss_enroll_activate()
 *
 * wlp_wss_create_activate()
 * 	wlp_wss_set_wssid_hash()
 * 		wlp_wss_comp_wssid_hash()
 * 	wlp_wss_sel_bcast_addr()
 * 	wlp_wss_sysfs_add()
 *
 * Called when no more references to WSS exist:
 * 	wlp_wss_release()
 * 		wlp_wss_reset()
 */
#include <linux/etherdevice.h> /* for is_valid_ether_addr */
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/wlp.h>

#include "wlp-internal.h"

size_t wlp_wss_key_print(char *buf, size_t bufsize, u8 *key)
{
	size_t result;

	result = scnprintf(buf, bufsize,
			  "%02x %02x %02x %02x %02x %02x "
			  "%02x %02x %02x %02x %02x %02x "
			  "%02x %02x %02x %02x",
			  key[0], key[1], key[2], key[3],
			  key[4], key[5], key[6], key[7],
			  key[8], key[9], key[10], key[11],
			  key[12], key[13], key[14], key[15]);
	return result;
}

/**
 * Compute WSSID hash
 * WLP Draft 0.99 [7.2.1]
 *
 * The WSSID hash for a WSSID is the result of an octet-wise exclusive-OR
 * of all octets in the WSSID.
 */
static
u8 wlp_wss_comp_wssid_hash(struct wlp_uuid *wssid)
{
	return wssid->data[0]  ^ wssid->data[1]  ^ wssid->data[2]
	       ^ wssid->data[3]  ^ wssid->data[4]  ^ wssid->data[5]
	       ^ wssid->data[6]  ^ wssid->data[7]  ^ wssid->data[8]
	       ^ wssid->data[9]  ^ wssid->data[10] ^ wssid->data[11]
	       ^ wssid->data[12] ^ wssid->data[13] ^ wssid->data[14]
	       ^ wssid->data[15];
}

/**
 * Select a multicast EUI-48 for the WSS broadcast address.
 * WLP Draft 0.99 [7.2.1]
 *
 * Selected based on the WiMedia Alliance OUI, 00-13-88, within the WLP
 * range, [01-13-88-00-01-00, 01-13-88-00-01-FF] inclusive.
 *
 * This address is currently hardcoded.
 * FIXME?
 */
static
struct uwb_mac_addr wlp_wss_sel_bcast_addr(struct wlp_wss *wss)
{
	struct uwb_mac_addr bcast = {
		.data = { 0x01, 0x13, 0x88, 0x00, 0x01, 0x00 }
	};
	return bcast;
}

/**
 * Clear the contents of the WSS structure - all except kobj, mutex, virtual
 *
 * We do not want to reinitialize - the internal kobj should not change as
 * it still points to the parent received during setup. The mutex should
 * remain also. We thus just reset values individually.
 * The virutal address assigned to WSS will remain the same for the
 * lifetime of the WSS. We only reset the fields that can change during its
 * lifetime.
 */
void wlp_wss_reset(struct wlp_wss *wss)
{
	memset(&wss->wssid, 0, sizeof(wss->wssid));
	wss->hash = 0;
	memset(&wss->name[0], 0, sizeof(wss->name));
	memset(&wss->bcast, 0, sizeof(wss->bcast));
	wss->secure_status = WLP_WSS_UNSECURE;
	memset(&wss->master_key[0], 0, sizeof(wss->master_key));
	wss->tag = 0;
	wss->state = WLP_WSS_STATE_NONE;
}

/**
 * Create sysfs infrastructure for WSS
 *
 * The WSS is configured to have the interface as parent (see wlp_wss_setup())
 * a new sysfs directory that includes wssid as its name is created in the
 * interface's sysfs directory. The group of files interacting with WSS are
 * created also.
 */
static
int wlp_wss_sysfs_add(struct wlp_wss *wss, char *wssid_str)
{
	struct wlp *wlp = container_of(wss, struct wlp, wss);
	struct device *dev = &wlp->rc->uwb_dev.dev;
	int result;

	result = kobject_set_name(&wss->kobj, "wss-%s", wssid_str);
	if (result < 0)
		return result;
	wss->kobj.ktype = &wss_ktype;
	result = kobject_init_and_add(&wss->kobj,
			&wss_ktype, wss->kobj.parent, "wlp");
	if (result < 0) {
		dev_err(dev, "WLP: Cannot register WSS kobject.\n");
		goto error_kobject_register;
	}
	result = sysfs_create_group(&wss->kobj, &wss_attr_group);
	if (result < 0) {
		dev_err(dev, "WLP: Cannot register WSS attributes: %d\n",
			result);
		goto error_sysfs_create_group;
	}
	return 0;
error_sysfs_create_group:

	kobject_put(&wss->kobj); /* will free name if needed */
	return result;
error_kobject_register:
	kfree(wss->kobj.name);
	wss->kobj.name = NULL;
	wss->kobj.ktype = NULL;
	return result;
}


/**
 * Release WSS
 *
 * No more references exist to this WSS. We should undo everything that was
 * done in wlp_wss_create_activate() except removing the group. The group
 * is not removed because an object can be unregistered before the group is
 * created. We also undo any additional operations on the WSS after this
 * (addition of members).
 *
 * If memory was allocated for the kobject's name then it will
 * be freed by the kobject system during this time.
 *
 * The EDA cache is removed and reinitilized when the WSS is removed. We
 * thus loose knowledge of members of this WSS at that time and need not do
 * it here.
 */
void wlp_wss_release(struct kobject *kobj)
{
	struct wlp_wss *wss = container_of(kobj, struct wlp_wss, kobj);

	wlp_wss_reset(wss);
}

/**
 * Enroll into a WSS using provided neighbor as registrar
 *
 * First search the neighborhood information to learn which neighbor is
 * referred to, next proceed with enrollment.
 *
 * &wss->mutex is held
 */
static
int wlp_wss_enroll_target(struct wlp_wss *wss, struct wlp_uuid *wssid,
			  struct uwb_dev_addr *dest)
{
	struct wlp *wlp = container_of(wss, struct wlp, wss);
	struct device *dev = &wlp->rc->uwb_dev.dev;
	struct wlp_neighbor_e *neighbor;
	int result = -ENXIO;
	struct uwb_dev_addr *dev_addr;

	mutex_lock(&wlp->nbmutex);
	list_for_each_entry(neighbor, &wlp->neighbors, node) {
		dev_addr = &neighbor->uwb_dev->dev_addr;
		if (!memcmp(dest, dev_addr, sizeof(*dest))) {
			result = wlp_enroll_neighbor(wlp, neighbor, wss, wssid);
			break;
		}
	}
	if (result == -ENXIO)
		dev_err(dev, "WLP: Cannot find neighbor %02x:%02x. \n",
			dest->data[1], dest->data[0]);
	mutex_unlock(&wlp->nbmutex);
	return result;
}

/**
 * Enroll into a WSS previously discovered
 *
 * User provides WSSID of WSS, search for neighbor that has this WSS
 * activated and attempt to enroll.
 *
 * &wss->mutex is held
 */
static
int wlp_wss_enroll_discovered(struct wlp_wss *wss, struct wlp_uuid *wssid)
{
	struct wlp *wlp = container_of(wss, struct wlp, wss);
	struct device *dev = &wlp->rc->uwb_dev.dev;
	struct wlp_neighbor_e *neighbor;
	struct wlp_wssid_e *wssid_e;
	char buf[WLP_WSS_UUID_STRSIZE];
	int result = -ENXIO;


	mutex_lock(&wlp->nbmutex);
	list_for_each_entry(neighbor, &wlp->neighbors, node) {
		list_for_each_entry(wssid_e, &neighbor->wssid, node) {
			if (!memcmp(wssid, &wssid_e->wssid, sizeof(*wssid))) {
				result = wlp_enroll_neighbor(wlp, neighbor,
							     wss, wssid);
				if (result == 0) /* enrollment success */
					goto out;
				break;
			}
		}
	}
out:
	if (result == -ENXIO) {
		wlp_wss_uuid_print(buf, sizeof(buf), wssid);
		dev_err(dev, "WLP: Cannot find WSSID %s in cache. \n", buf);
	}
	mutex_unlock(&wlp->nbmutex);
	return result;
}

/**
 * Enroll into WSS with provided WSSID, registrar may be provided
 *
 * @wss: out WSS that will be enrolled
 * @wssid: wssid of neighboring WSS that we want to enroll in
 * @devaddr: registrar can be specified, will be broadcast (ff:ff) if any
 *           neighbor can be used as registrar.
 *
 * &wss->mutex is held
 */
static
int wlp_wss_enroll(struct wlp_wss *wss, struct wlp_uuid *wssid,
		   struct uwb_dev_addr *devaddr)
{
	int result;
	struct wlp *wlp = container_of(wss, struct wlp, wss);
	struct device *dev = &wlp->rc->uwb_dev.dev;
	char buf[WLP_WSS_UUID_STRSIZE];
	struct uwb_dev_addr bcast = {.data = {0xff, 0xff} };

	wlp_wss_uuid_print(buf, sizeof(buf), wssid);

	if (wss->state != WLP_WSS_STATE_NONE) {
		dev_err(dev, "WLP: Already enrolled in WSS %s.\n", buf);
		result = -EEXIST;
		goto error;
	}
	if (!memcmp(&bcast, devaddr, sizeof(bcast)))
		result = wlp_wss_enroll_discovered(wss, wssid);
	else
		result = wlp_wss_enroll_target(wss, wssid, devaddr);
	if (result < 0) {
		dev_err(dev, "WLP: Unable to enroll into WSS %s, result %d \n",
			buf, result);
		goto error;
	}
	dev_dbg(dev, "Successfully enrolled into WSS %s \n", buf);
	result = wlp_wss_sysfs_add(wss, buf);
	if (result < 0) {
		dev_err(dev, "WLP: Unable to set up sysfs for WSS kobject.\n");
		wlp_wss_reset(wss);
	}
error:
	return result;

}

/**
 * Activate given WSS
 *
 * Prior to activation a WSS must be enrolled. To activate a WSS a device
 * includes the WSS hash in the WLP IE in its beacon in each superframe.
 * WLP 0.99 [7.2.5].
 *
 * The WSS tag is also computed at this time. We only support one activated
 * WSS so we can use the hash as a tag - there will never be a conflict.
 *
 * We currently only support one activated WSS so only one WSS hash is
 * included in the WLP IE.
 */
static
int wlp_wss_activate(struct wlp_wss *wss)
{
	struct wlp *wlp = container_of(wss, struct wlp, wss);
	struct device *dev = &wlp->rc->uwb_dev.dev;
	struct uwb_rc *uwb_rc = wlp->rc;
	int result;
	struct {
		struct wlp_ie wlp_ie;
		u8 hash; /* only include one hash */
	} ie_data;

	BUG_ON(wss->state != WLP_WSS_STATE_ENROLLED);
	wss->hash = wlp_wss_comp_wssid_hash(&wss->wssid);
	wss->tag = wss->hash;
	memset(&ie_data, 0, sizeof(ie_data));
	ie_data.wlp_ie.hdr.element_id = UWB_IE_WLP;
	ie_data.wlp_ie.hdr.length = sizeof(ie_data) - sizeof(struct uwb_ie_hdr);
	wlp_ie_set_hash_length(&ie_data.wlp_ie, sizeof(ie_data.hash));
	ie_data.hash = wss->hash;
	result = uwb_rc_ie_add(uwb_rc, &ie_data.wlp_ie.hdr,
			       sizeof(ie_data));
	if (result < 0) {
		dev_err(dev, "WLP: Unable to add WLP IE to beacon. "
			"result = %d.\n", result);
		goto error_wlp_ie;
	}
	wss->state = WLP_WSS_STATE_ACTIVE;
	result = 0;
error_wlp_ie:
	return result;
}

/**
 * Enroll in and activate WSS identified by provided WSSID
 *
 * The neighborhood cache should contain a list of all neighbors and the
 * WSS they have activated. Based on that cache we search which neighbor we
 * can perform the association process with. The user also has option to
 * specify which neighbor it prefers as registrar.
 * Successful enrollment is followed by activation.
 * Successful activation will create the sysfs directory containing
 * specific information regarding this WSS.
 */
int wlp_wss_enroll_activate(struct wlp_wss *wss, struct wlp_uuid *wssid,
			    struct uwb_dev_addr *devaddr)
{
	struct wlp *wlp = container_of(wss, struct wlp, wss);
	struct device *dev = &wlp->rc->uwb_dev.dev;
	int result = 0;
	char buf[WLP_WSS_UUID_STRSIZE];

	mutex_lock(&wss->mutex);
	result = wlp_wss_enroll(wss, wssid, devaddr);
	if (result < 0) {
		wlp_wss_uuid_print(buf, sizeof(buf), &wss->wssid);
		dev_err(dev, "WLP: Enrollment into WSS %s failed.\n", buf);
		goto error_enroll;
	}
	result = wlp_wss_activate(wss);
	if (result < 0) {
		dev_err(dev, "WLP: Unable to activate WSS. Undoing enrollment "
			"result = %d \n", result);
		/* Undo enrollment */
		wlp_wss_reset(wss);
		goto error_activate;
	}
error_activate:
error_enroll:
	mutex_unlock(&wss->mutex);
	return result;
}

/**
 * Create, enroll, and activate a new WSS
 *
 * @wssid: new wssid provided by user
 * @name:  WSS name requested by used.
 * @sec_status: security status requested by user
 *
 * A user requested the creation of a new WSS. All operations are done
 * locally. The new WSS will be stored locally, the hash will be included
 * in the WLP IE, and the sysfs infrastructure for this WSS will be
 * created.
 */
int wlp_wss_create_activate(struct wlp_wss *wss, struct wlp_uuid *wssid,
			    char *name, unsigned sec_status, unsigned accept)
{
	struct wlp *wlp = container_of(wss, struct wlp, wss);
	struct device *dev = &wlp->rc->uwb_dev.dev;
	int result = 0;
	char buf[WLP_WSS_UUID_STRSIZE];

	result = wlp_wss_uuid_print(buf, sizeof(buf), wssid);

	if (!mutex_trylock(&wss->mutex)) {
		dev_err(dev, "WLP: WLP association session in progress.\n");
		return -EBUSY;
	}
	if (wss->state != WLP_WSS_STATE_NONE) {
		dev_err(dev, "WLP: WSS already exists. Not creating new.\n");
		result = -EEXIST;
		goto out;
	}
	if (wss->kobj.parent == NULL) {
		dev_err(dev, "WLP: WSS parent not ready. Is network interface "
		       "up?\n");
		result = -ENXIO;
		goto out;
	}
	if (sec_status == WLP_WSS_SECURE) {
		dev_err(dev, "WLP: FIXME Creation of secure WSS not "
			"supported yet.\n");
		result = -EINVAL;
		goto out;
	}
	wss->wssid = *wssid;
	memcpy(wss->name, name, sizeof(wss->name));
	wss->bcast = wlp_wss_sel_bcast_addr(wss);
	wss->secure_status = sec_status;
	wss->accept_enroll = accept;
	/*wss->virtual_addr is initialized in call to wlp_wss_setup*/
	/* sysfs infrastructure */
	result = wlp_wss_sysfs_add(wss, buf);
	if (result < 0) {
		dev_err(dev, "Cannot set up sysfs for WSS kobject.\n");
		wlp_wss_reset(wss);
		goto out;
	} else
		result = 0;
	wss->state = WLP_WSS_STATE_ENROLLED;
	result = wlp_wss_activate(wss);
	if (result < 0) {
		dev_err(dev, "WLP: Unable to activate WSS. Undoing "
			"enrollment\n");
		wlp_wss_reset(wss);
		goto out;
	}
	result = 0;
out:
	mutex_unlock(&wss->mutex);
	return result;
}

/**
 * Determine if neighbor has WSS activated
 *
 * @returns: 1 if neighbor has WSS activated, zero otherwise
 *
 * This can be done in two ways:
 * - send a C1 frame, parse C2/F0 response
 * - examine the WLP IE sent by the neighbor
 *
 * The WLP IE is not fully supported in hardware so we use the C1/C2 frame
 * exchange to determine if a WSS is activated. Using the WLP IE should be
 * faster and should be used when it becomes possible.
 */
int wlp_wss_is_active(struct wlp *wlp, struct wlp_wss *wss,
		      struct uwb_dev_addr *dev_addr)
{
	int result = 0;
	struct device *dev = &wlp->rc->uwb_dev.dev;
	DECLARE_COMPLETION_ONSTACK(completion);
	struct wlp_session session;
	struct sk_buff  *skb;
	struct wlp_frame_assoc *resp;
	struct wlp_uuid wssid;

	mutex_lock(&wlp->mutex);
	/* Send C1 association frame */
	result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_C1);
	if (result < 0) {
		dev_err(dev, "Unable to send C1 frame to neighbor "
			"%02x:%02x (%d)\n", dev_addr->data[1],
			dev_addr->data[0], result);
		result = 0;
		goto out;
	}
	/* Create session, wait for response */
	session.exp_message = WLP_ASSOC_C2;
	session.cb = wlp_session_cb;
	session.cb_priv = &completion;
	session.neighbor_addr = *dev_addr;
	BUG_ON(wlp->session != NULL);
	wlp->session = &session;
	/* Wait for C2/F0 frame */
	result = wait_for_completion_interruptible_timeout(&completion,
						   WLP_PER_MSG_TIMEOUT * HZ);
	if (result == 0) {
		dev_err(dev, "Timeout while sending C1 to neighbor "
			     "%02x:%02x.\n", dev_addr->data[1],
			     dev_addr->data[0]);
		goto out;
	}
	if (result < 0) {
		dev_err(dev, "Unable to send C1 to neighbor %02x:%02x.\n",
			dev_addr->data[1], dev_addr->data[0]);
		result = 0;
		goto out;
	}
	/* Parse message in session->data: it will be either C2 or F0 */
	skb = session.data;
	resp = (void *) skb->data;
	if (resp->type == WLP_ASSOC_F0) {
		result = wlp_parse_f0(wlp, skb);
		if (result < 0)
			dev_err(dev, "WLP:  unable to parse incoming F0 "
				"frame from neighbor %02x:%02x.\n",
				dev_addr->data[1], dev_addr->data[0]);
		result = 0;
		goto error_resp_parse;
	}
	/* WLP version and message type fields have already been parsed */
	result = wlp_get_wssid(wlp, (void *)resp + sizeof(*resp), &wssid,
			       skb->len - sizeof(*resp));
	if (result < 0) {
		dev_err(dev, "WLP: unable to obtain WSSID from C2 frame.\n");
		result = 0;
		goto error_resp_parse;
	}
	if (!memcmp(&wssid, &wss->wssid, sizeof(wssid)))
		result = 1;
	else {
		dev_err(dev, "WLP: Received a C2 frame without matching "
			"WSSID.\n");
		result = 0;
	}
error_resp_parse:
	kfree_skb(skb);
out:
	wlp->session = NULL;
	mutex_unlock(&wlp->mutex);
	return result;
}

/**
 * Activate connection with neighbor by updating EDA cache
 *
 * @wss:       local WSS to which neighbor wants to connect
 * @dev_addr:  neighbor's address
 * @wssid:     neighbor's WSSID - must be same as our WSS's WSSID
 * @tag:       neighbor's WSS tag used to identify frames transmitted by it
 * @virt_addr: neighbor's virtual EUI-48
 */
static
int wlp_wss_activate_connection(struct wlp *wlp, struct wlp_wss *wss,
				struct uwb_dev_addr *dev_addr,
				struct wlp_uuid *wssid, u8 *tag,
				struct uwb_mac_addr *virt_addr)
{
	struct device *dev = &wlp->rc->uwb_dev.dev;
	int result = 0;

	if (!memcmp(wssid, &wss->wssid, sizeof(*wssid))) {
		/* Update EDA cache */
		result = wlp_eda_update_node(&wlp->eda, dev_addr, wss,
					     (void *) virt_addr->data, *tag,
					     WLP_WSS_CONNECTED);
		if (result < 0)
			dev_err(dev, "WLP: Unable to update EDA cache "
				"with new connected neighbor information.\n");
	} else {
		dev_err(dev, "WLP: Neighbor does not have matching WSSID.\n");
		result = -EINVAL;
	}
	return result;
}

/**
 * Connect to WSS neighbor
 *
 * Use C3/C4 exchange to determine if neighbor has WSS activated and
 * retrieve the WSS tag and virtual EUI-48 of the neighbor.
 */
static
int wlp_wss_connect_neighbor(struct wlp *wlp, struct wlp_wss *wss,
			     struct uwb_dev_addr *dev_addr)
{
	int result;
	struct device *dev = &wlp->rc->uwb_dev.dev;
	struct wlp_uuid wssid;
	u8 tag;
	struct uwb_mac_addr virt_addr;
	DECLARE_COMPLETION_ONSTACK(completion);
	struct wlp_session session;
	struct wlp_frame_assoc *resp;
	struct sk_buff *skb;

	mutex_lock(&wlp->mutex);
	/* Send C3 association frame */
	result = wlp_send_assoc_frame(wlp, wss, dev_addr, WLP_ASSOC_C3);
	if (result < 0) {
		dev_err(dev, "Unable to send C3 frame to neighbor "
			"%02x:%02x (%d)\n", dev_addr->data[1],
			dev_addr->data[0], result);
		goto out;
	}
	/* Create session, wait for response */
	session.exp_message = WLP_ASSOC_C4;
	session.cb = wlp_session_cb;
	session.cb_priv = &completion;
	session.neighbor_addr = *dev_addr;
	BUG_ON(wlp->session != NULL);
	wlp->session = &session;
	/* Wait for C4/F0 frame */
	result = wait_for_completion_interruptible_timeout(&completion,
						   WLP_PER_MSG_TIMEOUT * HZ);
	if (result == 0) {
		dev_err(dev, "Timeout while sending C3 to neighbor "
			     "%02x:%02x.\n", dev_addr->data[1],
			     dev_addr->data[0]);
		result = -ETIMEDOUT;
		goto out;
	}
	if (result < 0) {
		dev_err(dev, "Unable to send C3 to neighbor %02x:%02x.\n",
			dev_addr->data[1], dev_addr->data[0]);
		goto out;
	}
	/* Parse message in session->data: it will be either C4 or F0 */
	skb = session.data;
	resp = (void *) skb->data;
	if (resp->type == WLP_ASSOC_F0) {
		result = wlp_parse_f0(wlp, skb);
		if (result < 0)
			dev_err(dev, "WLP: unable to parse incoming F0 "
				"frame from neighbor %02x:%02x.\n",
				dev_addr->data[1], dev_addr->data[0]);
		result = -EINVAL;
		goto error_resp_parse;
	}
	result = wlp_parse_c3c4_frame(wlp, skb, &wssid, &tag, &virt_addr);
	if (result < 0) {
		dev_err(dev, "WLP: Unable to parse C4 frame from neighbor.\n");
		goto error_resp_parse;
	}
	result = wlp_wss_activate_connection(wlp, wss, dev_addr, &wssid, &tag,
					     &virt_addr);
	if (result < 0) {
		dev_err(dev, "WLP: Unable to activate connection to "
			"neighbor %02x:%02x.\n", dev_addr->data[1],
			dev_addr->data[0]);
		goto error_resp_parse;
	}
error_resp_parse:
	kfree_skb(skb);
out:
	/* Record that we unsuccessfully tried to connect to this neighbor */
	if (result < 0)
		wlp_eda_update_node_state(&wlp->eda, dev_addr,
					  WLP_WSS_CONNECT_FAILED);
	wlp->session = NULL;
	mutex_unlock(&wlp->mutex);
	return result;
}

/**
 * Connect to neighbor with common WSS, send pending frame
 *
 * This function is scheduled when a frame is destined to a neighbor with
 * which we do not have a connection. A copy of the EDA cache entry is
 * provided - not the actual cache entry (because it is protected by a
 * spinlock).
 *
 * First determine if neighbor has the same WSS activated, connect if it
 * does. The C3/C4 exchange is dual purpose to determine if neighbor has
 * WSS activated and proceed with the connection.
 *
 * The frame that triggered the connection setup is sent after connection
 * setup.
 *
 * network queue is stopped - we need to restart when done
 *
 */
static
void wlp_wss_connect_send(struct work_struct *ws)
{
	struct wlp_assoc_conn_ctx *conn_ctx = container_of(ws,
						  struct wlp_assoc_conn_ctx,
						  ws);
	struct wlp *wlp = conn_ctx->wlp;
	struct sk_buff *skb = conn_ctx->skb;
	struct wlp_eda_node *eda_entry = &conn_ctx->eda_entry;
	struct uwb_dev_addr *dev_addr = &eda_entry->dev_addr;
	struct wlp_wss *wss = &wlp->wss;
	int result;
	struct device *dev = &wlp->rc->uwb_dev.dev;

	mutex_lock(&wss->mutex);
	if (wss->state < WLP_WSS_STATE_ACTIVE) {
		if (printk_ratelimit())
			dev_err(dev, "WLP: Attempting to connect with "
				"WSS that is not active or connected.\n");
		dev_kfree_skb(skb);
		goto out;
	}
	/* Establish connection - send C3 rcv C4 */
	result = wlp_wss_connect_neighbor(wlp, wss, dev_addr);
	if (result < 0) {
		if (printk_ratelimit())
			dev_err(dev, "WLP: Unable to establish connection "
				"with neighbor %02x:%02x.\n",
				dev_addr->data[1], dev_addr->data[0]);
		dev_kfree_skb(skb);
		goto out;
	}
	/* EDA entry changed, update the local copy being used */
	result = wlp_copy_eda_node(&wlp->eda, dev_addr, eda_entry);
	if (result < 0) {
		if (printk_ratelimit())
			dev_err(dev, "WLP: Cannot find EDA entry for "
				"neighbor %02x:%02x \n",
				dev_addr->data[1], dev_addr->data[0]);
	}
	result = wlp_wss_prep_hdr(wlp, eda_entry, skb);
	if (result < 0) {
		if (printk_ratelimit())
			dev_err(dev, "WLP: Unable to prepare frame header for "
				"transmission (neighbor %02x:%02x). \n",
				dev_addr->data[1], dev_addr->data[0]);
		dev_kfree_skb(skb);
		goto out;
	}
	BUG_ON(wlp->xmit_frame == NULL);
	result = wlp->xmit_frame(wlp, skb, dev_addr);
	if (result < 0) {
		if (printk_ratelimit())
			dev_err(dev, "WLP: Unable to transmit frame: %d\n",
				result);
		if (result == -ENXIO)
			dev_err(dev, "WLP: Is network interface up? \n");
		/* We could try again ... */
		dev_kfree_skb(skb);/*we need to free if tx fails */
	}
out:
	kfree(conn_ctx);
	BUG_ON(wlp->start_queue == NULL);
	wlp->start_queue(wlp);
	mutex_unlock(&wss->mutex);
}

/**
 * Add WLP header to outgoing skb
 *
 * @eda_entry: pointer to neighbor's entry in the EDA cache
 * @_skb:      skb containing data destined to the neighbor
 */
int wlp_wss_prep_hdr(struct wlp *wlp, struct wlp_eda_node *eda_entry,
		     void *_skb)
{
	struct device *dev = &wlp->rc->uwb_dev.dev;
	int result = 0;
	unsigned char *eth_addr = eda_entry->eth_addr;
	struct uwb_dev_addr *dev_addr = &eda_entry->dev_addr;
	struct sk_buff *skb = _skb;
	struct wlp_frame_std_abbrv_hdr *std_hdr;

	if (eda_entry->state == WLP_WSS_CONNECTED) {
		/* Add WLP header */
		BUG_ON(skb_headroom(skb) < sizeof(*std_hdr));
		std_hdr = (void *) __skb_push(skb, sizeof(*std_hdr));
		std_hdr->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
		std_hdr->hdr.type = WLP_FRAME_STANDARD;
		std_hdr->tag = eda_entry->wss->tag;
	} else {
		if (printk_ratelimit())
			dev_err(dev, "WLP: Destination neighbor (Ethernet: "
				"%02x:%02x:%02x:%02x:%02x:%02x, Dev: "
				"%02x:%02x) is not connected. \n", eth_addr[0],
				eth_addr[1], eth_addr[2], eth_addr[3],
				eth_addr[4], eth_addr[5], dev_addr->data[1],
				dev_addr->data[0]);
		result = -EINVAL;
	}
	return result;
}


/**
 * Prepare skb for neighbor: connect if not already and prep WLP header
 *
 * This function is called in interrupt context, but it needs to sleep. We
 * temporarily stop the net queue to establish the WLP connection.
 * Setup of the WLP connection and restart of queue is scheduled
 * on the default work queue.
 *
 * run with eda->lock held (spinlock)
 */
int wlp_wss_connect_prep(struct wlp *wlp, struct wlp_eda_node *eda_entry,
			 void *_skb)
{
	int result = 0;
	struct device *dev = &wlp->rc->uwb_dev.dev;
	struct sk_buff *skb = _skb;
	struct wlp_assoc_conn_ctx *conn_ctx;

	if (eda_entry->state == WLP_WSS_UNCONNECTED) {
		/* We don't want any more packets while we set up connection */
		BUG_ON(wlp->stop_queue == NULL);
		wlp->stop_queue(wlp);
		conn_ctx = kmalloc(sizeof(*conn_ctx), GFP_ATOMIC);
		if (conn_ctx == NULL) {
			if (printk_ratelimit())
				dev_err(dev, "WLP: Unable to allocate memory "
					"for connection handling.\n");
			result = -ENOMEM;
			goto out;
		}
		conn_ctx->wlp = wlp;
		conn_ctx->skb = skb;
		conn_ctx->eda_entry = *eda_entry;
		INIT_WORK(&conn_ctx->ws, wlp_wss_connect_send);
		schedule_work(&conn_ctx->ws);
		result = 1;
	} else if (eda_entry->state == WLP_WSS_CONNECT_FAILED) {
		/* Previous connection attempts failed, don't retry - see
		 * conditions for connection in WLP 0.99 [7.6.2] */
		if (printk_ratelimit())
			dev_err(dev, "Could not connect to neighbor "
			 "previously. Not retrying. \n");
		result = -ENONET;
		goto out;
	} else /* eda_entry->state == WLP_WSS_CONNECTED */
		result = wlp_wss_prep_hdr(wlp, eda_entry, skb);
out:
	return result;
}

/**
 * Emulate broadcast: copy skb, send copy to neighbor (connect if not already)
 *
 * We need to copy skbs in the case where we emulate broadcast through
 * unicast. We copy instead of clone because we are modifying the data of
 * the frame after copying ... clones share data so we cannot emulate
 * broadcast using clones.
 *
 * run with eda->lock held (spinlock)
 */
int wlp_wss_send_copy(struct wlp *wlp, struct wlp_eda_node *eda_entry,
		      void *_skb)
{
	int result = -ENOMEM;
	struct device *dev = &wlp->rc->uwb_dev.dev;
	struct sk_buff *skb = _skb;
	struct sk_buff *copy;
	struct uwb_dev_addr *dev_addr = &eda_entry->dev_addr;

	copy = skb_copy(skb, GFP_ATOMIC);
	if (copy == NULL) {
		if (printk_ratelimit())
			dev_err(dev, "WLP: Unable to copy skb for "
				"transmission.\n");
		goto out;
	}
	result = wlp_wss_connect_prep(wlp, eda_entry, copy);
	if (result < 0) {
		if (printk_ratelimit())
			dev_err(dev, "WLP: Unable to connect/send skb "
				"to neighbor.\n");
		dev_kfree_skb_irq(copy);
		goto out;
	} else if (result == 1)
		/* Frame will be transmitted separately */
		goto out;
	BUG_ON(wlp->xmit_frame == NULL);
	result = wlp->xmit_frame(wlp, copy, dev_addr);
	if (result < 0) {
		if (printk_ratelimit())
			dev_err(dev, "WLP: Unable to transmit frame: %d\n",
				result);
		if ((result == -ENXIO) && printk_ratelimit())
			dev_err(dev, "WLP: Is network interface up? \n");
		/* We could try again ... */
		dev_kfree_skb_irq(copy);/*we need to free if tx fails */
	}
out:
	return result;
}


/**
 * Setup WSS
 *
 * Should be called by network driver after the interface has been given a
 * MAC address.
 */
int wlp_wss_setup(struct net_device *net_dev, struct wlp_wss *wss)
{
	struct wlp *wlp = container_of(wss, struct wlp, wss);
	struct device *dev = &wlp->rc->uwb_dev.dev;
	int result = 0;

	mutex_lock(&wss->mutex);
	wss->kobj.parent = &net_dev->dev.kobj;
	if (!is_valid_ether_addr(net_dev->dev_addr)) {
		dev_err(dev, "WLP: Invalid MAC address. Cannot use for"
		       "virtual.\n");
		result = -EINVAL;
		goto out;
	}
	memcpy(wss->virtual_addr.data, net_dev->dev_addr,
	       sizeof(wss->virtual_addr.data));
out:
	mutex_unlock(&wss->mutex);
	return result;
}
EXPORT_SYMBOL_GPL(wlp_wss_setup);

/**
 * Remove WSS
 *
 * Called by client that configured WSS through wlp_wss_setup(). This
 * function is called when client no longer needs WSS, eg. client shuts
 * down.
 *
 * We remove the WLP IE from the beacon before initiating local cleanup.
 */
void wlp_wss_remove(struct wlp_wss *wss)
{
	struct wlp *wlp = container_of(wss, struct wlp, wss);

	mutex_lock(&wss->mutex);
	if (wss->state == WLP_WSS_STATE_ACTIVE)
		uwb_rc_ie_rm(wlp->rc, UWB_IE_WLP);
	if (wss->state != WLP_WSS_STATE_NONE) {
		sysfs_remove_group(&wss->kobj, &wss_attr_group);
		kobject_put(&wss->kobj);
	}
	wss->kobj.parent = NULL;
	memset(&wss->virtual_addr, 0, sizeof(wss->virtual_addr));
	/* Cleanup EDA cache */
	wlp_eda_release(&wlp->eda);
	wlp_eda_init(&wlp->eda);
	mutex_unlock(&wss->mutex);
}
EXPORT_SYMBOL_GPL(wlp_wss_remove);
