/*
* Copyright (c) 2005-2009 Brocade Communications Systems, Inc.
* All rights reserved
* www.brocade.com
*
* Linux driver for Brocade Fibre Channel Host Bus Adapter.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License (GPL) 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.
*/
#include <bfa.h>
#include <bfa_fcpim.h>
#include "bfa_fcpim_priv.h"
BFA_TRC_FILE(HAL, ITNIM);
#define BFA_ITNIM_FROM_TAG(_fcpim, _tag) \
((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1)))
#define bfa_fcpim_additn(__itnim) \
list_add_tail(&(__itnim)->qe, &(__itnim)->fcpim->itnim_q)
#define bfa_fcpim_delitn(__itnim) do { \
bfa_assert(bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim)); \
list_del(&(__itnim)->qe); \
bfa_assert(list_empty(&(__itnim)->io_q)); \
bfa_assert(list_empty(&(__itnim)->io_cleanup_q)); \
bfa_assert(list_empty(&(__itnim)->pending_q)); \
} while (0)
#define bfa_itnim_online_cb(__itnim) do { \
if ((__itnim)->bfa->fcs) \
bfa_cb_itnim_online((__itnim)->ditn); \
else { \
bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe, \
__bfa_cb_itnim_online, (__itnim)); \
} \
} while (0)
#define bfa_itnim_offline_cb(__itnim) do { \
if ((__itnim)->bfa->fcs) \
bfa_cb_itnim_offline((__itnim)->ditn); \
else { \
bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe, \
__bfa_cb_itnim_offline, (__itnim)); \
} \
} while (0)
#define bfa_itnim_sler_cb(__itnim) do { \
if ((__itnim)->bfa->fcs) \
bfa_cb_itnim_sler((__itnim)->ditn); \
else { \
bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe, \
__bfa_cb_itnim_sler, (__itnim)); \
} \
} while (0)
/*
* forward declarations
*/
static void bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim);
static bfa_boolean_t bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim);
static bfa_boolean_t bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim);
static void bfa_itnim_cleanp_comp(void *itnim_cbarg);
static void bfa_itnim_cleanup(struct bfa_itnim_s *itnim);
static void __bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete);
static void __bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete);
static void __bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete);
static void bfa_itnim_iotov_online(struct bfa_itnim_s *itnim);
static void bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim);
static void bfa_itnim_iotov(void *itnim_arg);
static void bfa_itnim_iotov_start(struct bfa_itnim_s *itnim);
static void bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim);
static void bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim);
/**
* bfa_itnim_sm BFA itnim state machine
*/
enum bfa_itnim_event {
BFA_ITNIM_SM_CREATE = 1, /* itnim is created */
BFA_ITNIM_SM_ONLINE = 2, /* itnim is online */
BFA_ITNIM_SM_OFFLINE = 3, /* itnim is offline */
BFA_ITNIM_SM_FWRSP = 4, /* firmware response */
BFA_ITNIM_SM_DELETE = 5, /* deleting an existing itnim */
BFA_ITNIM_SM_CLEANUP = 6, /* IO cleanup completion */
BFA_ITNIM_SM_SLER = 7, /* second level error recovery */
BFA_ITNIM_SM_HWFAIL = 8, /* IOC h/w failure event */
BFA_ITNIM_SM_QRESUME = 9, /* queue space available */
};
static void bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim,
enum bfa_itnim_event event);
static void bfa_itnim_sm_created(struct bfa_itnim_s *itnim,
enum bfa_itnim_event event);
static void bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim,
enum bfa_itnim_event event);
static void bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim,
enum bfa_itnim_event event);
static void bfa_itnim_sm_online(struct bfa_itnim_s *itnim,
enum bfa_itnim_event event);
static void bfa_itnim_sm_sler(struct bfa_itnim_s *itnim,
enum bfa_itnim_event event);
static void bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim,
enum bfa_itnim_event event);
static void bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim,
enum bfa_itnim_event event);
static void bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim,
enum bfa_itnim_event event);
static void bfa_itnim_sm_offline(struct bfa_itnim_s *itnim,
enum bfa_itnim_event event);
static void bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim,
enum bfa_itnim_event event);
static void bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim,
enum bfa_itnim_event event);
static void bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim,
enum bfa_itnim_event event);
static void bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim,
enum bfa_itnim_event event);
static voi