/*
* Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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.
*
* Maintained at www.Open-FCoE.org
*/
/*
* RPORT GENERAL INFO
*
* This file contains all processing regarding fc_rports. It contains the
* rport state machine and does all rport interaction with the transport class.
* There should be no other places in libfc that interact directly with the
* transport class in regards to adding and deleting rports.
*
* fc_rport's represent N_Port's within the fabric.
*/
/*
* RPORT LOCKING
*
* The rport should never hold the rport mutex and then attempt to acquire
* either the lport or disc mutexes. The rport's mutex is considered lesser
* than both the lport's mutex and the disc mutex. Refer to fc_lport.c for
* more comments on the heirarchy.
*
* The locking strategy is similar to the lport's strategy. The lock protects
* the rport's states and is held and released by the entry points to the rport
* block. All _enter_* functions correspond to rport states and expect the rport
* mutex to be locked before calling them. This means that rports only handle
* one request or response at a time, since they're not critical for the I/O
* path this potential over-use of the mutex is acceptable.
*/
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/rcupdate.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <asm/unaligned.h>
#include <scsi/libfc.h>
#include <scsi/fc_encode.h>
static int fc_rport_debug;
#define FC_DEBUG_RPORT(fmt...) \
do { \
if (fc_rport_debug) \
FC_DBG(fmt); \
} while (0)
struct workqueue_struct *rport_event_queue;
static void fc_rport_enter_plogi(struct fc_rport *);
static void fc_rport_enter_prli(struct fc_rport *);
static void fc_rport_enter_rtv(struct fc_rport *);
static void fc_rport_enter_ready(struct fc_rport *);
static void fc_rport_enter_logo(struct fc_rport *);
static void fc_rport_recv_plogi_req(struct fc_rport *,
struct fc_seq *, struct fc_frame *);
static void fc_rport_recv_prli_req(struct fc_rport *,
struct fc_seq *, struct fc_frame *);
static void fc_rport_recv_prlo_req(struct fc_rport *,
struct fc_seq *, struct fc_frame *);
static void fc_rport_recv_logo_req(struct fc_rport *,
struct fc_seq *, struct fc_frame *);
static void fc_rport_timeout(struct work_struct *);
static void fc_rport_error(struct fc_rport *, struct fc_frame *);
static void fc_rport_e