/*
 * Serial Attached SCSI (SAS) Port class
 *
 * Copyright (C) 2005 Adaptec, Inc.  All rights reserved.
 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
 *
 * This file is licensed under GPLv2.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * 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 St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "sas_internal.h"

#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_sas.h>
#include "../scsi_sas_internal.h"

/**
 * sas_form_port -- add this phy to a port
 * @phy: the phy of interest
 *
 * This function adds this phy to an existing port, thus creating a wide
 * port, or it creates a port and adds the phy to the port.
 */
static void sas_form_port(struct asd_sas_phy *phy)
{
	int i;
	struct sas_ha_struct *sas_ha = phy->ha;
	struct asd_sas_port *port = phy->port;
	struct sas_internal *si =
		to_sas_internal(sas_ha->core.shost->transportt);

	if (port) {
		if (memcmp(port->attached_sas_addr, phy->attached_sas_addr,
			   SAS_ADDR_SIZE) == 0)
			sas_deform_port(phy);
		else {
			SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n",
				    __FUNCTION__, phy->id, phy->port->id,
				    phy->port->num_phys);
			return;
		}
	}

	/* find a port */
	spin_lock(&sas_ha->phy_port_lock);
	for (i = 0; i < sas_ha->num_phys; i++) {
		port = sas_ha->sas_port[i];
		spin_lock(&port->phy_list_lock);
		if (*(u64 *) port->sas_addr &&
		    memcmp(port->attached_sas_addr,
			   phy->attached_sas_addr, SAS_ADDR_SIZE) == 0 &&
		    port->num_phys > 0) {
			/* wide port */
			SAS_DPRINTK("phy%d matched wide port%d\n", phy->id,
				    port->id);
			break;
		} else if (*(u64 *) port->sas_addr == 0 && port->num_phys==0) {
			memcpy(port->sas_addr, phy->sas_addr, SAS_ADDR_SIZE);
			break;
		}
		spin_unlock(&port->phy_list_lock);
	}

	if (i >= sas_ha->num_phys) {
		printk(KERN_NOTICE "%s: couldn't find a free port, bug?\n",
		       __FUNCTION__);
		spin_unlock(&sas_ha->phy_port_lock);
		return;
	}

	/* add the phy to the port */
	list_add_tail(&phy->port_phy_el, &port->phy_list);
	phy->port = port;
	port->num_phys++;
	port->phy_mask |= (1U << phy->id);

	if (!port->phy)
		port->phy = phy->phy;

	SAS_DPRINTK("phy%d added to port%d, phy_mask:0x%x\n", phy->id,
		    port->id, port->phy_mask);

	if (*(u64 *)port->attached_sas_addr == 0) {
		port->class = phy->class;
		memcpy(port->attached_sas_addr, phy->attached_sas_addr,
		       SAS_ADDR_SIZE);
		port->iproto = phy->iproto;
		port->tproto = phy->tproto;
		port->oob_mode = phy->oob_mode;
		port->linkrate = phy->linkrate;
	} else
		port->linkrate = max(port->linkrate, phy->linkrate);
	spin_unlock(&port->phy_list_lock);
	spin_unlock(&sas_ha->phy_port_lock);

	if (!port->port) {
		port->port = sas_port_alloc(phy->phy->dev.parent, port->id);
		BUG_ON(!port->port);
		sas_port_add(port->port);
	}
	sas_port_add_phy(port->port, phy->phy);

	if (port->port_dev)
		port->port_dev->pathways = port->num_phys;

	/* Tell the LLDD about this port formation. */
	if (si->dft->lldd_port_formed)
		si->dft->lldd_port_formed(phy);

	sas_discover_event(phy->port, DISCE_DISCOVER_DOMAIN);
}

/**
 * sas_deform_port -- remove this phy from the port it belongs to
 * @phy: the phy of interest
 *
 * This is called when the physical link to the other phy has been
 * lost (on this phy), in Event thread context. We cannot delay here.
 */
void sas_deform_port(struct asd_sas_phy *phy)
{
	struct sas_ha_struct *sas_ha = phy->ha;
	struct asd_sas_port *port = phy->port;
	struct sas_internal *si =
		to_sas_internal(sas_ha->core.shost->transportt);

	if (!port)
		return;		  /* done by a phy event */

	if (port->port_dev)
		port->port_dev->pathways--;

	if (port->num_phys == 1) {
		sas_unregister_domain_devices(port);
		sas_port_delete(port->port);
		port->port = NULL;
	} else
		sas_port_delete_phy(port->port, phy->phy);


	if (si->dft->lldd_port_deformed)
		si->dft->lldd_port_deformed(phy);

	spin_lock(&sas_ha->phy_port_lock);
	spin_lock(&port->phy_list_lock);

	list_del_init(&phy->port_phy_el);
	phy->port = NULL;
	port->num_phys--;
	port->phy_mask &= ~(1U << phy->id);

	if (port->num_phys == 0) {
		INIT_LIST_HEAD(&port->phy_list);
		memset(port->sas_addr, 0, SAS_ADDR_SIZE);
		memset(port->attached_sas_addr, 0, SAS_ADDR_SIZE);
		port->class = 0;
		port->iproto = 0;
		port->tproto = 0;
		port->oob_mode = 0;
		port->phy_mask = 0;
	}
	spin_unlock(&port->phy_list_lock);
	spin_unlock(&sas_ha->phy_port_lock);

	return;
}

/* ---------- SAS port events ---------- */

void sas_porte_bytes_dmaed(void *data)
{
	struct asd_sas_phy *phy = data;

	sas_begin_event(PORTE_BYTES_DMAED, &phy->ha->event_lock,
			&phy->port_events_pending);

	sas_form_port(phy);
}

void sas_porte_broadcast_rcvd(void *data)
{
	unsigned long flags;
	u32 prim;
	struct asd_sas_phy *phy = data;

	sas_begin_event(PORTE_BROADCAST_RCVD, &phy->ha->event_lock,
			&phy->port_events_pending);

	spin_lock_irqsave(&phy->sas_prim_lock, flags);
	prim = phy->sas_prim;
	spin_unlock_irqrestore(&phy->sas_prim_lock, flags);

	SAS_DPRINTK("broadcast received: %d\n", prim);
	sas_discover_event(phy->port, DISCE_REVALIDATE_DOMAIN);
}

void sas_porte_link_reset_err(void *data)
{
	struct asd_sas_phy *phy = data;

	sas_begin_event(PORTE_LINK_RESET_ERR, &phy->ha->event_lock,
			&phy->port_events_pending);

	sas_deform_port(phy);
}

void sas_porte_timer_event(void *data)
{
	struct asd_sas_phy *phy = data;

	sas_begin_event(PORTE_TIMER_EVENT, &phy->ha->event_lock,
			&phy->port_events_pending);

	sas_deform_port(phy);
}

void sas_porte_hard_reset(void *data)
{
	struct asd_sas_phy *phy = data;

	sas_begin_event(PORTE_HARD_RESET, &phy->ha->event_lock,
			&phy->port_events_pending);

	sas_deform_port(phy);
}

/* ---------- SAS port registration ---------- */

static void sas_init_port(struct asd_sas_port *port,
			  struct sas_ha_struct *sas_ha, int i)
{
	port->id = i;
	INIT_LIST_HEAD(&port->dev_list);
	spin_lock_init(&port->phy_list_lock);
	INIT_LIST_HEAD(&port->phy_list);
	port->num_phys = 0;
	port->phy_mask = 0;
	port->ha = sas_ha;

	spin_lock_init(&port->dev_list_lock);
}

int sas_register_ports(struct sas_ha_struct *sas_ha)
{
	int i;

	/* initialize the ports and discovery */
	for (i = 0; i < sas_ha->num_phys; i++) {
		struct asd_sas_port *port = sas_ha->sas_port[i];

		sas_init_port(port, sas_ha, i);
		sas_init_disc(&port->disc, port);
	}
	return 0;
}

void sas_unregister_ports(struct sas_ha_struct *sas_ha)
{
	int i;

	for (i = 0; i < sas_ha->num_phys; i++)
		if (sas_ha->sas_phy[i]->port)
			sas_deform_port(sas_ha->sas_phy[i]);

}
