diff options
Diffstat (limited to 'drivers/net/bna/bna_ctrl.c')
-rw-r--r-- | drivers/net/bna/bna_ctrl.c | 3076 |
1 files changed, 0 insertions, 3076 deletions
diff --git a/drivers/net/bna/bna_ctrl.c b/drivers/net/bna/bna_ctrl.c deleted file mode 100644 index cb2594c564d..00000000000 --- a/drivers/net/bna/bna_ctrl.c +++ /dev/null @@ -1,3076 +0,0 @@ -/* - * Linux network driver for Brocade Converged Network 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. - */ -/* - * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. - * All rights reserved - * www.brocade.com - */ -#include "bna.h" -#include "bfa_cs.h" - -static void bna_device_cb_port_stopped(void *arg, enum bna_cb_status status); - -static void -bna_port_cb_link_up(struct bna_port *port, struct bfi_ll_aen *aen, - int status) -{ - int i; - u8 prio_map; - - port->llport.link_status = BNA_LINK_UP; - if (aen->cee_linkup) - port->llport.link_status = BNA_CEE_UP; - - /* Compute the priority */ - prio_map = aen->prio_map; - if (prio_map) { - for (i = 0; i < 8; i++) { - if ((prio_map >> i) & 0x1) - break; - } - port->priority = i; - } else - port->priority = 0; - - /* Dispatch events */ - bna_tx_mod_cee_link_status(&port->bna->tx_mod, aen->cee_linkup); - bna_tx_mod_prio_changed(&port->bna->tx_mod, port->priority); - port->link_cbfn(port->bna->bnad, port->llport.link_status); -} - -static void -bna_port_cb_link_down(struct bna_port *port, int status) -{ - port->llport.link_status = BNA_LINK_DOWN; - - /* Dispatch events */ - bna_tx_mod_cee_link_status(&port->bna->tx_mod, BNA_LINK_DOWN); - port->link_cbfn(port->bna->bnad, BNA_LINK_DOWN); -} - -static inline int -llport_can_be_up(struct bna_llport *llport) -{ - int ready = 0; - if (llport->type == BNA_PORT_T_REGULAR) - ready = ((llport->flags & BNA_LLPORT_F_ADMIN_UP) && - (llport->flags & BNA_LLPORT_F_RX_STARTED) && - (llport->flags & BNA_LLPORT_F_PORT_ENABLED)); - else - ready = ((llport->flags & BNA_LLPORT_F_ADMIN_UP) && - (llport->flags & BNA_LLPORT_F_RX_STARTED) && - !(llport->flags & BNA_LLPORT_F_PORT_ENABLED)); - return ready; -} - -#define llport_is_up llport_can_be_up - -enum bna_llport_event { - LLPORT_E_START = 1, - LLPORT_E_STOP = 2, - LLPORT_E_FAIL = 3, - LLPORT_E_UP = 4, - LLPORT_E_DOWN = 5, - LLPORT_E_FWRESP_UP_OK = 6, - LLPORT_E_FWRESP_UP_FAIL = 7, - LLPORT_E_FWRESP_DOWN = 8 -}; - -static void -bna_llport_cb_port_enabled(struct bna_llport *llport) -{ - llport->flags |= BNA_LLPORT_F_PORT_ENABLED; - - if (llport_can_be_up(llport)) - bfa_fsm_send_event(llport, LLPORT_E_UP); -} - -static void -bna_llport_cb_port_disabled(struct bna_llport *llport) -{ - int llport_up = llport_is_up(llport); - - llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED; - - if (llport_up) - bfa_fsm_send_event(llport, LLPORT_E_DOWN); -} - -/** - * MBOX - */ -static int -bna_is_aen(u8 msg_id) -{ - switch (msg_id) { - case BFI_LL_I2H_LINK_DOWN_AEN: - case BFI_LL_I2H_LINK_UP_AEN: - case BFI_LL_I2H_PORT_ENABLE_AEN: - case BFI_LL_I2H_PORT_DISABLE_AEN: - return 1; - - default: - return 0; - } -} - -static void -bna_mbox_aen_callback(struct bna *bna, struct bfi_mbmsg *msg) -{ - struct bfi_ll_aen *aen = (struct bfi_ll_aen *)(msg); - - switch (aen->mh.msg_id) { - case BFI_LL_I2H_LINK_UP_AEN: - bna_port_cb_link_up(&bna->port, aen, aen->reason); - break; - case BFI_LL_I2H_LINK_DOWN_AEN: - bna_port_cb_link_down(&bna->port, aen->reason); - break; - case BFI_LL_I2H_PORT_ENABLE_AEN: - bna_llport_cb_port_enabled(&bna->port.llport); - break; - case BFI_LL_I2H_PORT_DISABLE_AEN: - bna_llport_cb_port_disabled(&bna->port.llport); - break; - default: - break; - } -} - -static void -bna_ll_isr(void *llarg, struct bfi_mbmsg *msg) -{ - struct bna *bna = (struct bna *)(llarg); - struct bfi_ll_rsp *mb_rsp = (struct bfi_ll_rsp *)(msg); - struct bfi_mhdr *cmd_h, *rsp_h; - struct bna_mbox_qe *mb_qe = NULL; - int to_post = 0; - u8 aen = 0; - char message[BNA_MESSAGE_SIZE]; - - aen = bna_is_aen(mb_rsp->mh.msg_id); - - if (!aen) { - mb_qe = bfa_q_first(&bna->mbox_mod.posted_q); - cmd_h = (struct bfi_mhdr *)(&mb_qe->cmd.msg[0]); - rsp_h = (struct bfi_mhdr *)(&mb_rsp->mh); - - if ((BFA_I2HM(cmd_h->msg_id) == rsp_h->msg_id) && - (cmd_h->mtag.i2htok == rsp_h->mtag.i2htok)) { - /* Remove the request from posted_q, update state */ - list_del(&mb_qe->qe); - bna->mbox_mod.msg_pending--; - if (list_empty(&bna->mbox_mod.posted_q)) - bna->mbox_mod.state = BNA_MBOX_FREE; - else - to_post = 1; - - /* Dispatch the cbfn */ - if (mb_qe->cbfn) - mb_qe->cbfn(mb_qe->cbarg, mb_rsp->error); - - /* Post the next entry, if needed */ - if (to_post) { - mb_qe = bfa_q_first(&bna->mbox_mod.posted_q); - bfa_nw_ioc_mbox_queue(&bna->device.ioc, - &mb_qe->cmd); - } - } else { - snprintf(message, BNA_MESSAGE_SIZE, - "No matching rsp for [%d:%d:%d]\n", - mb_rsp->mh.msg_class, mb_rsp->mh.msg_id, - mb_rsp->mh.mtag.i2htok); - pr_info("%s", message); - } - - } else - bna_mbox_aen_callback(bna, msg); -} - -static void -bna_err_handler(struct bna *bna, u32 intr_status) -{ - u32 init_halt; - - if (intr_status & __HALT_STATUS_BITS) { - init_halt = readl(bna->device.ioc.ioc_regs.ll_halt); - init_halt &= ~__FW_INIT_HALT_P; - writel(init_halt, bna->device.ioc.ioc_regs.ll_halt); - } - - bfa_nw_ioc_error_isr(&bna->device.ioc); -} - -void -bna_mbox_handler(struct bna *bna, u32 intr_status) -{ - if (BNA_IS_ERR_INTR(intr_status)) { - bna_err_handler(bna, intr_status); - return; - } - if (BNA_IS_MBOX_INTR(intr_status)) - bfa_nw_ioc_mbox_isr(&bna->device.ioc); -} - -void -bna_mbox_send(struct bna *bna, struct bna_mbox_qe *mbox_qe) -{ - struct bfi_mhdr *mh; - - mh = (struct bfi_mhdr *)(&mbox_qe->cmd.msg[0]); - - mh->mtag.i2htok = htons(bna->mbox_mod.msg_ctr); - bna->mbox_mod.msg_ctr++; - bna->mbox_mod.msg_pending++; - if (bna->mbox_mod.state == BNA_MBOX_FREE) { - list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q); - bfa_nw_ioc_mbox_queue(&bna->device.ioc, &mbox_qe->cmd); - bna->mbox_mod.state = BNA_MBOX_POSTED; - } else { - list_add_tail(&mbox_qe->qe, &bna->mbox_mod.posted_q); - } -} - -static void -bna_mbox_flush_q(struct bna *bna, struct list_head *q) -{ - struct bna_mbox_qe *mb_qe = NULL; - struct list_head *mb_q; - void (*cbfn)(void *arg, int status); - void *cbarg; - - mb_q = &bna->mbox_mod.posted_q; - - while (!list_empty(mb_q)) { - bfa_q_deq(mb_q, &mb_qe); - cbfn = mb_qe->cbfn; - cbarg = mb_qe->cbarg; - bfa_q_qe_init(mb_qe); - bna->mbox_mod.msg_pending--; - - if (cbfn) - cbfn(cbarg, BNA_CB_NOT_EXEC); - } - - bna->mbox_mod.state = BNA_MBOX_FREE; -} - -static void -bna_mbox_mod_start(struct bna_mbox_mod *mbox_mod) -{ -} - -static void -bna_mbox_mod_stop(struct bna_mbox_mod *mbox_mod) -{ - bna_mbox_flush_q(mbox_mod->bna, &mbox_mod->posted_q); -} - -static void -bna_mbox_mod_init(struct bna_mbox_mod *mbox_mod, struct bna *bna) -{ - bfa_nw_ioc_mbox_regisr(&bna->device.ioc, BFI_MC_LL, bna_ll_isr, bna); - mbox_mod->state = BNA_MBOX_FREE; - mbox_mod->msg_ctr = mbox_mod->msg_pending = 0; - INIT_LIST_HEAD(&mbox_mod->posted_q); - mbox_mod->bna = bna; -} - -static void -bna_mbox_mod_uninit(struct bna_mbox_mod *mbox_mod) -{ - mbox_mod->bna = NULL; -} - -/** - * LLPORT - */ -#define call_llport_stop_cbfn(llport, status)\ -do {\ - if ((llport)->stop_cbfn)\ - (llport)->stop_cbfn(&(llport)->bna->port, status);\ - (llport)->stop_cbfn = NULL;\ -} while (0) - -static void bna_fw_llport_up(struct bna_llport *llport); -static void bna_fw_cb_llport_up(void *arg, int status); -static void bna_fw_llport_down(struct bna_llport *llport); -static void bna_fw_cb_llport_down(void *arg, int status); -static void bna_llport_start(struct bna_llport *llport); -static void bna_llport_stop(struct bna_llport *llport); -static void bna_llport_fail(struct bna_llport *llport); - -enum bna_llport_state { - BNA_LLPORT_STOPPED = 1, - BNA_LLPORT_DOWN = 2, - BNA_LLPORT_UP_RESP_WAIT = 3, - BNA_LLPORT_DOWN_RESP_WAIT = 4, - BNA_LLPORT_UP = 5, - BNA_LLPORT_LAST_RESP_WAIT = 6 -}; - -bfa_fsm_state_decl(bna_llport, stopped, struct bna_llport, - enum bna_llport_event); -bfa_fsm_state_decl(bna_llport, down, struct bna_llport, - enum bna_llport_event); -bfa_fsm_state_decl(bna_llport, up_resp_wait, struct bna_llport, - enum bna_llport_event); -bfa_fsm_state_decl(bna_llport, down_resp_wait, struct bna_llport, - enum bna_llport_event); -bfa_fsm_state_decl(bna_llport, up, struct bna_llport, - enum bna_llport_event); -bfa_fsm_state_decl(bna_llport, last_resp_wait, struct bna_llport, - enum bna_llport_event); - -static struct bfa_sm_table llport_sm_table[] = { - {BFA_SM(bna_llport_sm_stopped), BNA_LLPORT_STOPPED}, - {BFA_SM(bna_llport_sm_down), BNA_LLPORT_DOWN}, - {BFA_SM(bna_llport_sm_up_resp_wait), BNA_LLPORT_UP_RESP_WAIT}, - {BFA_SM(bna_llport_sm_down_resp_wait), BNA_LLPORT_DOWN_RESP_WAIT}, - {BFA_SM(bna_llport_sm_up), BNA_LLPORT_UP}, - {BFA_SM(bna_llport_sm_last_resp_wait), BNA_LLPORT_LAST_RESP_WAIT} -}; - -static void -bna_llport_sm_stopped_entry(struct bna_llport *llport) -{ - llport->bna->port.link_cbfn((llport)->bna->bnad, BNA_LINK_DOWN); - call_llport_stop_cbfn(llport, BNA_CB_SUCCESS); -} - -static void -bna_llport_sm_stopped(struct bna_llport *llport, - enum bna_llport_event event) -{ - switch (event) { - case LLPORT_E_START: - bfa_fsm_set_state(llport, bna_llport_sm_down); - break; - - case LLPORT_E_STOP: - call_llport_stop_cbfn(llport, BNA_CB_SUCCESS); - break; - - case LLPORT_E_FAIL: - break; - - case LLPORT_E_DOWN: - /* This event is received due to Rx objects failing */ - /* No-op */ - break; - - case LLPORT_E_FWRESP_UP_OK: - case LLPORT_E_FWRESP_DOWN: - /** - * These events are received due to flushing of mbox when - * device fails - */ - /* No-op */ - break; - - default: - bfa_sm_fault(event); - } -} - -static void -bna_llport_sm_down_entry(struct bna_llport *llport) -{ - bnad_cb_port_link_status((llport)->bna->bnad, BNA_LINK_DOWN); -} - -static void -bna_llport_sm_down(struct bna_llport *llport, - enum bna_llport_event event) -{ - switch (event) { - case LLPORT_E_STOP: - bfa_fsm_set_state(llport, bna_llport_sm_stopped); - break; - - case LLPORT_E_FAIL: - bfa_fsm_set_state(llport, bna_llport_sm_stopped); - break; - - case LLPORT_E_UP: - bfa_fsm_set_state(llport, bna_llport_sm_up_resp_wait); - bna_fw_llport_up(llport); - break; - - default: - bfa_sm_fault(event); - } -} - -static void -bna_llport_sm_up_resp_wait_entry(struct bna_llport *llport) -{ - BUG_ON(!llport_can_be_up(llport)); - /** - * NOTE: Do not call bna_fw_llport_up() here. That will over step - * mbox due to down_resp_wait -> up_resp_wait transition on event - * LLPORT_E_UP - */ -} - -static void -bna_llport_sm_up_resp_wait(struct bna_llport *llport, - enum bna_llport_event event) -{ - switch (event) { - case LLPORT_E_STOP: - bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait); - break; - - case LLPORT_E_FAIL: - bfa_fsm_set_state(llport, bna_llport_sm_stopped); - break; - - case LLPORT_E_DOWN: - bfa_fsm_set_state(llport, bna_llport_sm_down_resp_wait); - break; - - case LLPORT_E_FWRESP_UP_OK: - bfa_fsm_set_state(llport, bna_llport_sm_up); - break; - - case LLPORT_E_FWRESP_UP_FAIL: - bfa_fsm_set_state(llport, bna_llport_sm_down); - break; - - case LLPORT_E_FWRESP_DOWN: - /* down_resp_wait -> up_resp_wait transition on LLPORT_E_UP */ - bna_fw_llport_up(llport); - break; - - default: - bfa_sm_fault(event); - } -} - -static void -bna_llport_sm_down_resp_wait_entry(struct bna_llport *llport) -{ - /** - * NOTE: Do not call bna_fw_llport_down() here. That will over step - * mbox due to up_resp_wait -> down_resp_wait transition on event - * LLPORT_E_DOWN - */ -} - -static void -bna_llport_sm_down_resp_wait(struct bna_llport *llport, - enum bna_llport_event event) -{ - switch (event) { - case LLPORT_E_STOP: - bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait); - break; - - case LLPORT_E_FAIL: - bfa_fsm_set_state(llport, bna_llport_sm_stopped); - break; - - case LLPORT_E_UP: - bfa_fsm_set_state(llport, bna_llport_sm_up_resp_wait); - break; - - case LLPORT_E_FWRESP_UP_OK: - /* up_resp_wait->down_resp_wait transition on LLPORT_E_DOWN */ - bna_fw_llport_down(llport); - break; - - case LLPORT_E_FWRESP_UP_FAIL: - case LLPORT_E_FWRESP_DOWN: - bfa_fsm_set_state(llport, bna_llport_sm_down); - break; - - default: - bfa_sm_fault(event); - } -} - -static void -bna_llport_sm_up_entry(struct bna_llport *llport) -{ -} - -static void -bna_llport_sm_up(struct bna_llport *llport, - enum bna_llport_event event) -{ - switch (event) { - case LLPORT_E_STOP: - bfa_fsm_set_state(llport, bna_llport_sm_last_resp_wait); - bna_fw_llport_down(llport); - break; - - case LLPORT_E_FAIL: - bfa_fsm_set_state(llport, bna_llport_sm_stopped); - break; - - case LLPORT_E_DOWN: - bfa_fsm_set_state(llport, bna_llport_sm_down_resp_wait); - bna_fw_llport_down(llport); - break; - - default: - bfa_sm_fault(event); - } -} - -static void -bna_llport_sm_last_resp_wait_entry(struct bna_llport *llport) -{ -} - -static void -bna_llport_sm_last_resp_wait(struct bna_llport *llport, - enum bna_llport_event event) -{ - switch (event) { - case LLPORT_E_FAIL: - bfa_fsm_set_state(llport, bna_llport_sm_stopped); - break; - - case LLPORT_E_DOWN: - /** - * This event is received due to Rx objects stopping in - * parallel to llport - */ - /* No-op */ - break; - - case LLPORT_E_FWRESP_UP_OK: - /* up_resp_wait->last_resp_wait transition on LLPORT_T_STOP */ - bna_fw_llport_down(llport); - break; - - case LLPORT_E_FWRESP_UP_FAIL: - case LLPORT_E_FWRESP_DOWN: - bfa_fsm_set_state(llport, bna_llport_sm_stopped); - break; - - default: - bfa_sm_fault(event); - } -} - -static void -bna_fw_llport_admin_up(struct bna_llport *llport) -{ - struct bfi_ll_port_admin_req ll_req; - - memset(&ll_req, 0, sizeof(ll_req)); - ll_req.mh.msg_class = BFI_MC_LL; - ll_req.mh.msg_id = BFI_LL_H2I_PORT_ADMIN_REQ; - ll_req.mh.mtag.h2i.lpu_id = 0; - - ll_req.up = BNA_STATUS_T_ENABLED; - - bna_mbox_qe_fill(&llport->mbox_qe, &ll_req, sizeof(ll_req), - bna_fw_cb_llport_up, llport); - - bna_mbox_send(llport->bna, &llport->mbox_qe); -} - -static void -bna_fw_llport_up(struct bna_llport *llport) -{ - if (llport->type == BNA_PORT_T_REGULAR) - bna_fw_llport_admin_up(llport); -} - -static void -bna_fw_cb_llport_up(void *arg, int status) -{ - struct bna_llport *llport = (struct bna_llport *)arg; - - bfa_q_qe_init(&llport->mbox_qe.qe); - if (status == BFI_LL_CMD_FAIL) { - if (llport->type == BNA_PORT_T_REGULAR) - llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED; - else - llport->flags &= ~BNA_LLPORT_F_ADMIN_UP; - bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP_FAIL); - } else - bfa_fsm_send_event(llport, LLPORT_E_FWRESP_UP_OK); -} - -static void -bna_fw_llport_admin_down(struct bna_llport *llport) -{ - struct bfi_ll_port_admin_req ll_req; - - memset(&ll_req, 0, sizeof(ll_req)); - ll_req.mh.msg_class = BFI_MC_LL; - ll_req.mh.msg_id = BFI_LL_H2I_PORT_ADMIN_REQ; - ll_req.mh.mtag.h2i.lpu_id = 0; - - ll_req.up = BNA_STATUS_T_DISABLED; - - bna_mbox_qe_fill(&llport->mbox_qe, &ll_req, sizeof(ll_req), - bna_fw_cb_llport_down, llport); - - bna_mbox_send(llport->bna, &llport->mbox_qe); -} - -static void -bna_fw_llport_down(struct bna_llport *llport) -{ - if (llport->type == BNA_PORT_T_REGULAR) - bna_fw_llport_admin_down(llport); -} - -static void -bna_fw_cb_llport_down(void *arg, int status) -{ - struct bna_llport *llport = (struct bna_llport *)arg; - - bfa_q_qe_init(&llport->mbox_qe.qe); - bfa_fsm_send_event(llport, LLPORT_E_FWRESP_DOWN); -} - -static void -bna_port_cb_llport_stopped(struct bna_port *port, - enum bna_cb_status status) -{ - bfa_wc_down(&port->chld_stop_wc); -} - -static void -bna_llport_init(struct bna_llport *llport, struct bna *bna) -{ - llport->flags |= BNA_LLPORT_F_ADMIN_UP; - llport->flags |= BNA_LLPORT_F_PORT_ENABLED; - llport->type = BNA_PORT_T_REGULAR; - llport->bna = bna; - - llport->link_status = BNA_LINK_DOWN; - - llport->rx_started_count = 0; - - llport->stop_cbfn = NULL; - - bfa_q_qe_init(&llport->mbox_qe.qe); - - bfa_fsm_set_state(llport, bna_llport_sm_stopped); -} - -static void -bna_llport_uninit(struct bna_llport *llport) -{ - llport->flags &= ~BNA_LLPORT_F_ADMIN_UP; - llport->flags &= ~BNA_LLPORT_F_PORT_ENABLED; - - llport->bna = NULL; -} - -static void -bna_llport_start(struct bna_llport *llport) -{ - bfa_fsm_send_event(llport, LLPORT_E_START); -} - -static void -bna_llport_stop(struct bna_llport *llport) -{ - llport->stop_cbfn = bna_port_cb_llport_stopped; - - bfa_fsm_send_event(llport, LLPORT_E_STOP); -} - -static void -bna_llport_fail(struct bna_llport *llport) -{ - /* Reset the physical port status to enabled */ - llport->flags |= BNA_LLPORT_F_PORT_ENABLED; - bfa_fsm_send_event(llport, LLPORT_E_FAIL); -} - -static int -bna_llport_state_get(struct bna_llport *llport) -{ - return bfa_sm_to_state(llport_sm_table, llport->fsm); -} - -void -bna_llport_rx_started(struct bna_llport *llport) -{ - llport->rx_started_count++; - - if (llport->rx_started_count == 1) { - - llport->flags |= BNA_LLPORT_F_RX_STARTED; - - if (llport_can_be_up(llport)) - bfa_fsm_send_event(llport, LLPORT_E_UP); - } -} - -void -bna_llport_rx_stopped(struct bna_llport *llport) -{ - int llport_up = llport_is_up(llport); - - llport->rx_started_count--; - - if (llport->rx_started_count == 0) { - - llport->flags &= ~BNA_LLPORT_F_RX_STARTED; - - if (llport_up) - bfa_fsm_send_event(llport, LLPORT_E_DOWN); - } -} - -/** - * PORT - */ -#define bna_port_chld_start(port)\ -do {\ - enum bna_tx_type tx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\ - BNA_TX_T_REGULAR : BNA_TX_T_LOOPBACK;\ - enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\ - BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\ - bna_llport_start(&(port)->llport);\ - bna_tx_mod_start(&(port)->bna->tx_mod, tx_type);\ - bna_rx_mod_start(&(port)->bna->rx_mod, rx_type);\ -} while (0) - -#define bna_port_chld_stop(port)\ -do {\ - enum bna_tx_type tx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\ - BNA_TX_T_REGULAR : BNA_TX_T_LOOPBACK;\ - enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\ - BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\ - bfa_wc_up(&(port)->chld_stop_wc);\ - bfa_wc_up(&(port)->chld_stop_wc);\ - bfa_wc_up(&(port)->chld_stop_wc);\ - bna_llport_stop(&(port)->llport);\ - bna_tx_mod_stop(&(port)->bna->tx_mod, tx_type);\ - bna_rx_mod_stop(&(port)->bna->rx_mod, rx_type);\ -} while (0) - -#define bna_port_chld_fail(port)\ -do {\ - bna_llport_fail(&(port)->llport);\ - bna_tx_mod_fail(&(port)->bna->tx_mod);\ - bna_rx_mod_fail(&(port)->bna->rx_mod);\ -} while (0) - -#define bna_port_rx_start(port)\ -do {\ - enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\ - BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\ - bna_rx_mod_start(&(port)->bna->rx_mod, rx_type);\ -} while (0) - -#define bna_port_rx_stop(port)\ -do {\ - enum bna_rx_type rx_type = ((port)->type == BNA_PORT_T_REGULAR) ?\ - BNA_RX_T_REGULAR : BNA_RX_T_LOOPBACK;\ - bfa_wc_up(&(port)->chld_stop_wc);\ - bna_rx_mod_stop(&(port)->bna->rx_mod, rx_type);\ -} while (0) - -#define call_port_stop_cbfn(port, status)\ -do {\ - if ((port)->stop_cbfn)\ - (port)->stop_cbfn((port)->stop_cbarg, status);\ - (port)->stop_cbfn = NULL;\ - (port)->stop_cbarg = NULL;\ -} while (0) - -#define call_port_pause_cbfn(port, status)\ -do {\ - if ((port)->pause_cbfn)\ - (port)->pause_cbfn((port)->bna->bnad, status);\ - (port)->pause_cbfn = NULL;\ -} while (0) - -#define call_port_mtu_cbfn(port, status)\ -do {\ - if ((port)->mtu_cbfn)\ - (port)->mtu_cbfn((port)->bna->bnad, status);\ - (port)->mtu_cbfn = NULL;\ -} while (0) - -static void bna_fw_pause_set(struct bna_port *port); -static void bna_fw_cb_pause_set(void *arg, int status); -static void bna_fw_mtu_set(struct bna_port *port); -static void bna_fw_cb_mtu_set(void *arg, int status); - -enum bna_port_event { - PORT_E_START = 1, - PORT_E_STOP = 2, - PORT_E_FAIL = 3, - PORT_E_PAUSE_CFG = 4, - PORT_E_MTU_CFG = 5, - PORT_E_CHLD_STOPPED = 6, - PORT_E_FWRESP_PAUSE = 7, - PORT_E_FWRESP_MTU = 8 -}; - -enum bna_port_state { - BNA_PORT_STOPPED = 1, - BNA_PORT_MTU_INIT_WAIT = 2, - BNA_PORT_PAUSE_INIT_WAIT = 3, - BNA_PORT_LAST_RESP_WAIT = 4, - BNA_PORT_STARTED = 5, - BNA_PORT_PAUSE_CFG_WAIT = 6, - BNA_PORT_RX_STOP_WAIT = 7, - BNA_PORT_MTU_CFG_WAIT = 8, - BNA_PORT_CHLD_STOP_WAIT = 9 -}; - -bfa_fsm_state_decl(bna_port, stopped, struct bna_port, - enum bna_port_event); -bfa_fsm_state_decl(bna_port, mtu_init_wait, struct bna_port, - enum bna_port_event); -bfa_fsm_state_decl(bna_port, pause_init_wait, struct bna_port, - enum bna_port_event); -bfa_fsm_state_decl(bna_port, last_resp_wait, struct bna_port, - enum bna_port_event); -bfa_fsm_state_decl(bna_port, started, struct bna_port, - enum bna_port_event); -bfa_fsm_state_decl(bna_port, pause_cfg_wait, struct bna_port, - enum bna_port_event); -bfa_fsm_state_decl(bna_port, rx_stop_wait, struct bna_port, - enum bna_port_event); -bfa_fsm_state_decl(bna_port, mtu_cfg_wait, struct bna_port, - enum bna_port_event); -bfa_fsm_state_decl(bna_port, chld_stop_wait, struct bna_port, - enum bna_port_event); - -static struct bfa_sm_table port_sm_table[] = { - {BFA_SM(bna_port_sm_stopped), BNA_PORT_STOPPED}, - {BFA_SM(bna_port_sm_mtu_init_wait), BNA_PORT_MTU_INIT_WAIT}, - {BFA_SM(bna_port_sm_pause_init_wait), BNA_PORT_PAUSE_INIT_WAIT}, - {BFA_SM(bna_port_sm_last_resp_wait), BNA_PORT_LAST_RESP_WAIT}, - {BFA_SM(bna_port_sm_started), BNA_PORT_STARTED}, - {BFA_SM(bna_port_sm_pause_cfg_wait), BNA_PORT_PAUSE_CFG_WAIT}, - {BFA_SM(bna_port_sm_rx_stop_wait), BNA_PORT_RX_STOP_WAIT}, - {BFA_SM(bna_port_sm_mtu_cfg_wait), BNA_PORT_MTU_CFG_WAIT}, - {BFA_SM(bna_port_sm_chld_stop_wait), BNA_PORT_CHLD_STOP_WAIT} -}; - -static void -bna_port_sm_stopped_entry(struct bna_port *port) -{ - call_port_pause_cbfn(port, BNA_CB_SUCCESS); - call_port_mtu_cbfn(port, BNA_CB_SUCCESS); - call_port_stop_cbfn(port, BNA_CB_SUCCESS); -} - -static void -bna_port_sm_stopped(struct bna_port *port, enum bna_port_event event) -{ - switch (event) { - case PORT_E_START: - bfa_fsm_set_state(port, bna_port_sm_mtu_init_wait); - break; - - case PORT_E_STOP: - call_port_stop_cbfn(port, BNA_CB_SUCCESS); - break; - - case PORT_E_FAIL: - /* No-op */ - break; - - case PORT_E_PAUSE_CFG: - call_port_pause_cbfn(port, BNA_CB_SUCCESS); - break; - - case PORT_E_MTU_CFG: - call_port_mtu_cbfn(port, BNA_CB_SUCCESS); - break; - - case PORT_E_CHLD_STOPPED: - /** - * This event is received due to LLPort, Tx and Rx objects - * failing - */ - /* No-op */ - break; - - case PORT_E_FWRESP_PAUSE: - case PORT_E_FWRESP_MTU: - /** - * These events are received due to flushing of mbox when - * device fails - */ - /* No-op */ - break; - - default: - bfa_sm_fault(event); - } -} - -static void -bna_port_sm_mtu_init_wait_entry(struct bna_port *port) -{ - bna_fw_mtu_set(port); -} - -static void -bna_port_sm_mtu_init_wait(struct bna_port *port, enum bna_port_event event) -{ - switch (event) { - case PORT_E_STOP: - bfa_fsm_set_state(port, bna_port_sm_last_resp_wait); - break; - - case PORT_E_FAIL: - bfa_fsm_set_state(port, bna_port_sm_stopped); - break; - - case PORT_E_PAUSE_CFG: - /* No-op */ - break; - - case PORT_E_MTU_CFG: - port->flags |= BNA_PORT_F_MTU_CHANGED; - break; - - case PORT_E_FWRESP_MTU: - if (port->flags & BNA_PORT_F_MTU_CHANGED) { - port->flags &= ~BNA_PORT_F_MTU_CHANGED; - bna_fw_mtu_set(port); - } else { - bfa_fsm_set_state(port, bna_port_sm_pause_init_wait); - } - break; - - default: - bfa_sm_fault(event); - } -} - -static void -bna_port_sm_pause_init_wait_entry(struct bna_port *port) -{ - bna_fw_pause_set(port); -} - -static void -bna_port_sm_pause_init_wait(struct bna_port *port, - enum bna_port_event event) -{ - switch (event) { - case PORT_E_STOP: - bfa_fsm_set_state(port, bna_port_sm_last_resp_wait); - break; - - case PORT_E_FAIL: - bfa_fsm_set_state(port, bna_port_sm_stopped); - break; - - case PORT_E_PAUSE_CFG: - port->flags |= BNA_PORT_F_PAUSE_CHANGED; - break; - - case PORT_E_MTU_CFG: - port->flags |= BNA_PORT_F_MTU_CHANGED; - break; - - case PORT_E_FWRESP_PAUSE: - if (port->flags & BNA_PORT_F_PAUSE_CHANGED) { - port->flags &= ~BNA_PORT_F_PAUSE_CHANGED; - bna_fw_pause_set(port); - } else if (port->flags & BNA_PORT_F_MTU_CHANGED) { - port->flags &= ~BNA_PORT_F_MTU_CHANGED; - bfa_fsm_set_state(port, bna_port_sm_mtu_init_wait); - } else { - bfa_fsm_set_state(port, bna_port_sm_started); - bna_port_chld_start(port); - } - break; - - default: - bfa_sm_fault(event); - } -} - -static void -bna_port_sm_last_resp_wait_entry(struct bna_port *port) -{ -} - -static void -bna_port_sm_last_resp_wait(struct bna_port *port, - enum bna_port_event event) -{ - switch (event) { - case PORT_E_FAIL: - case PORT_E_FWRESP_PAUSE: - case PORT_E_FWRESP_MTU: - bfa_fsm_set_state(port, bna_port_sm_stopped); - break; - - default: - bfa_sm_fault(event); - } -} - -static void -bna_port_sm_started_entry(struct bna_port *port) -{ - /** - * NOTE: Do not call bna_port_chld_start() here, since it will be - * inadvertently called during pause_cfg_wait->started transition - * as well - */ - call_port_pause_cbfn(port, BNA_CB_SUCCESS); - call_port_mtu_cbfn(port, BNA_CB_SUCCESS); -} - -static void -bna_port_sm_started(struct bna_port *port, - enum bna_port_event event) -{ - switch (event) { - case PORT_E_STOP: - bfa_fsm_set_state(port, bna_port_sm_chld_stop_wait); - break; - - case PORT_E_FAIL: - bfa_fsm_set_state(port, bna_port_sm_stopped); - bna_port_chld_fail(port); - break; - - case PORT_E_PAUSE_CFG: - bfa_fsm_set_state(port, bna_port_sm_pause_cfg_wait); - break; - - case PORT_E_MTU_CFG: - bfa_fsm_set_state(port, bna_port_sm_rx_stop_wait); - break; - - default: - bfa_sm_fault(event); - } -} - -static void -bna_port_sm_pause_cfg_wait_entry(struct bna_port *port) -{ - bna_fw_pause_set(port); -} - -static void -bna_port_sm_pause_cfg_wait(struct bna_port *port, - enum bna_port_event event) -{ - switch (event) { - case PORT_E_FAIL: - bfa_fsm_set_state(port, bna_port_sm_stopped); - bna_port_chld_fail(port); - break; - - case PORT_E_FWRESP_PAUSE: - bfa_fsm_set_state(port, bna_port_sm_started); - break; - - default: - bfa_sm_fault(event); - } -} - -static void -bna_port_sm_rx_stop_wait_entry(struct bna_port *port) -{ - bna_port_rx_stop(port); -} - -static void -bna_port_sm_rx_stop_wait(struct bna_port *port, - enum bna_port_event event) -{ - switch (event) { - case PORT_E_FAIL: - bfa_fsm_set_state(port, bna_port_sm_stopped); - bna_port_chld_fail(port); - break; - - case PORT_E_CHLD_STOPPED: - bfa_fsm_set_state(port, bna_port_sm_mtu_cfg_wait); - break; - - default: - bfa_sm_fault(event); - } -} - -static void -bna_port_sm_mtu_cfg_wait_entry(struct bna_port *port) -{ - bna_fw_mtu_set(port); -} - -static void -bna_port_sm_mtu_cfg_wait(struct bna_port *port, enum bna_port_event event) -{ - switch (event) { - case PORT_E_FAIL: - bfa_fsm_set_state(port, bna_port_sm_stopped); - bna_port_chld_fail(port); - break; - - case PORT_E_FWRESP_MTU: - bfa_fsm_set_state(port, bna_port_sm_started); - bna_port_rx_start(port); - break; - - default: - bfa_sm_fault(event); - } -} - -static void -bna_port_sm_chld_stop_wait_entry(struct bna_port *port) -{ - bna_port_chld_stop(port); -} - -static void -bna_port_sm_chld_stop_wait(struct bna_port *port, - enum bna_port_event event) -{ - switch (event) { - case PORT_E_FAIL: - bfa_fsm_set_state(port, bna_port_sm_stopped); - bna_port_chld_fail(port); - break; - - case PORT_E_CHLD_STOPPED: - bfa_fsm_set_state(port, bna_port_sm_stopped); - break; - - default: - bfa_sm_fault(event); - } -} - -static void -bna_fw_pause_set(struct bna_port *port) -{ - struct bfi_ll_set_pause_req ll_req; - - memset(&ll_req, 0, sizeof(ll_req)); - ll_req.mh.msg_class = BFI_MC_LL; - ll_req.mh.msg_id = BFI_LL_H2I_SET_PAUSE_REQ; - ll_req.mh.mtag.h2i.lpu_id = 0; - - ll_req.tx_pause = port->pause_config.tx_pause; - ll_req.rx_pause = port->pause_config.rx_pause; - - bna_mbox_qe_fill(&port->mbox_qe, &ll_req, sizeof(ll_req), - bna_fw_cb_pause_set, port); - - bna_mbox_send(port->bna, &port->mbox_qe); -} - -static void -bna_fw_cb_pause_set(void *arg, int status) -{ - struct bna_port *port = (struct bna_port *)arg; - - bfa_q_qe_init(&port->mbox_qe.qe); - bfa_fsm_send_event(port, PORT_E_FWRESP_PAUSE); -} - -void -bna_fw_mtu_set(struct bna_port *port) -{ - struct bfi_ll_mtu_info_req ll_req; - - bfi_h2i_set(ll_req.mh, BFI_MC_LL, BFI_LL_H2I_MTU_INFO_REQ, 0); - ll_req.mtu = htons((u16)port->mtu); - - bna_mbox_qe_fill(&port->mbox_qe, &ll_req, sizeof(ll_req), - bna_fw_cb_mtu_set, port); - bna_mbox_send(port->bna, &port->mbox_qe); -} - -void -bna_fw_cb_mtu_set(void *arg, int status) -{ - struct bna_port *port = (struct bna_port *)arg; - - bfa_q_qe_init(&port->mbox_qe.qe); - bfa_fsm_send_event(port, PORT_E_FWRESP_MTU); -} - -static void -bna_port_cb_chld_stopped(void *arg) -{ - struct bna_port *port = (struct bna_port *)arg; - - bfa_fsm_send_event(port, PORT_E_CHLD_STOPPED); -} - -static void -bna_port_init(struct bna_port *port, struct bna *bna) -{ - port->bna = bna; - port->flags = 0; - port->mtu = 0; - port->type = BNA_PORT_T_REGULAR; - - port->link_cbfn = bnad_cb_port_link_status; - - port->chld_stop_wc.wc_resume = bna_port_cb_chld_stopped; - port->chld_stop_wc.wc_cbarg = port; - port->chld_stop_wc.wc_count = 0; - - port->stop_cbfn = NULL; - port->stop_cbarg = NULL; - - port->pause_cbfn = NULL; - - port->mtu_cbfn = NULL; - - bfa_q_qe_init(&port->mbox_qe.qe); - - bfa_fsm_set_state(port, bna_port_sm_stopped); - - bna_llport_init(&port->llport, bna); -} - -static void -bna_port_uninit(struct bna_port *port) -{ - bna_llport_uninit(&port->llport); - - port->flags = 0; - - port->bna = NULL; -} - -static int -bna_port_state_get(struct bna_port *port) -{ - return bfa_sm_to_state(port_sm_table, port->fsm); -} - -static void -bna_port_start(struct bna_port *port) -{ - port->flags |= BNA_PORT_F_DEVICE_READY; - if (port->flags & BNA_PORT_F_ENABLED) - bfa_fsm_send_event(port, PORT_E_START); -} |