diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/ethernet/brocade/bna/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/brocade/bna/bfa_defs.h | 25 | ||||
-rw-r--r-- | drivers/net/ethernet/brocade/bna/bfa_defs_mfg_comm.h | 20 | ||||
-rw-r--r-- | drivers/net/ethernet/brocade/bna/bfa_ioc.c | 389 | ||||
-rw-r--r-- | drivers/net/ethernet/brocade/bna/bfa_ioc.h | 36 | ||||
-rw-r--r-- | drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c | 41 | ||||
-rw-r--r-- | drivers/net/ethernet/brocade/bna/bfi.h | 74 | ||||
-rw-r--r-- | drivers/net/ethernet/brocade/bna/bna.h | 224 | ||||
-rw-r--r-- | drivers/net/ethernet/brocade/bna/bna_types.h | 494 | ||||
-rw-r--r-- | drivers/net/ethernet/brocade/bna/bnad.c | 643 | ||||
-rw-r--r-- | drivers/net/ethernet/brocade/bna/bnad.h | 36 | ||||
-rw-r--r-- | drivers/net/ethernet/brocade/bna/bnad_ethtool.c | 65 | ||||
-rw-r--r-- | drivers/net/ethernet/brocade/bna/cna.h | 31 |
13 files changed, 1337 insertions, 743 deletions
diff --git a/drivers/net/ethernet/brocade/bna/Makefile b/drivers/net/ethernet/brocade/bna/Makefile index d501f520b0bc..74d3abca1960 100644 --- a/drivers/net/ethernet/brocade/bna/Makefile +++ b/drivers/net/ethernet/brocade/bna/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_BNA) += bna.o -bna-objs := bnad.o bnad_ethtool.o bna_ctrl.o bna_txrx.o +bna-objs := bnad.o bnad_ethtool.o bna_enet.o bna_tx_rx.o bna-objs += bfa_msgq.o bfa_ioc.o bfa_ioc_ct.o bfa_cee.o bna-objs += cna_fwimg.o diff --git a/drivers/net/ethernet/brocade/bna/bfa_defs.h b/drivers/net/ethernet/brocade/bna/bfa_defs.h index b080b3698f48..205b92b3709c 100644 --- a/drivers/net/ethernet/brocade/bna/bfa_defs.h +++ b/drivers/net/ethernet/brocade/bna/bfa_defs.h @@ -124,6 +124,7 @@ enum bfa_ioc_state { BFA_IOC_DISABLED = 10, /*!< IOC is disabled */ BFA_IOC_FWMISMATCH = 11, /*!< IOC f/w different from drivers */ BFA_IOC_ENABLING = 12, /*!< IOC is being enabled */ + BFA_IOC_HWFAIL = 13, /*!< PCI mapping doesn't exist */ }; /** @@ -179,8 +180,19 @@ struct bfa_ioc_attr { struct bfa_adapter_attr adapter_attr; /*!< HBA attributes */ struct bfa_ioc_driver_attr driver_attr; /*!< driver attr */ struct bfa_ioc_pci_attr pci_attr; - u8 port_id; /*!< port number */ - u8 rsvd[7]; /*!< 64bit align */ + u8 port_id; /*!< port number */ + u8 port_mode; /*!< enum bfa_mode */ + u8 cap_bm; /*!< capability */ + u8 port_mode_cfg; /*!< enum bfa_mode */ + u8 rsvd[4]; /*!< 64bit align */ +}; + +/** + * Adapter capability mask definition + */ +enum { + BFA_CM_HBA = 0x01, + BFA_CM_CNA = 0x02, }; /** @@ -228,7 +240,7 @@ struct bfa_mfg_block { mac_t mfg_mac; /*!< mac address */ u8 num_mac; /*!< number of mac addresses */ u8 rsv2; - u32 mfg_type; /*!< card type */ + u32 card_type; /*!< card type */ u8 rsv3[108]; u8 md5_chksum[BFA_MFG_CHKSUM_SIZE]; /*!< md5 checksum */ }; @@ -242,5 +254,12 @@ struct bfa_mfg_block { #define bfa_asic_id_ct(devid) \ ((devid) == PCI_DEVICE_ID_BROCADE_CT || \ (devid) == PCI_DEVICE_ID_BROCADE_CT_FC) +#define bfa_asic_id_ctc(devid) (bfa_asic_id_ct(devid)) + +enum bfa_mode { + BFA_MODE_HBA = 1, + BFA_MODE_CNA = 2, + BFA_MODE_NIC = 3 +}; #endif /* __BFA_DEFS_H__ */ diff --git a/drivers/net/ethernet/brocade/bna/bfa_defs_mfg_comm.h b/drivers/net/ethernet/brocade/bna/bfa_defs_mfg_comm.h index 885ef3afdd4e..f84d8f674812 100644 --- a/drivers/net/ethernet/brocade/bna/bfa_defs_mfg_comm.h +++ b/drivers/net/ethernet/brocade/bna/bfa_defs_mfg_comm.h @@ -19,11 +19,12 @@ #define __BFA_DEFS_MFG_COMM_H__ #include "cna.h" +#include "bfa_defs.h" /** * Manufacturing block version */ -#define BFA_MFG_VERSION 2 +#define BFA_MFG_VERSION 3 #define BFA_MFG_VERSION_UNINIT 0xFF /** @@ -95,27 +96,14 @@ enum { (type) == BFA_MFG_TYPE_CNA10P1 || \ bfa_mfg_is_mezz(type))) -#define bfa_mfg_adapter_prop_init_flash(card_type, prop) \ +#define bfa_mfg_adapter_prop_init_flash_ct(mfgblk, prop) \ do { \ - switch ((card_type)) { \ - case BFA_MFG_TYPE_FC8P2: \ + switch ((mfgblk)->card_type) { \ case BFA_MFG_TYPE_JAYHAWK: \ case BFA_MFG_TYPE_ASTRA: \ (prop) = BFI_ADAPTER_SETP(NPORTS, 2) | \ BFI_ADAPTER_SETP(SPEED, 8); \ break; \ - case BFA_MFG_TYPE_FC8P1: \ - (prop) = BFI_ADAPTER_SETP(NPORTS, 1) | \ - BFI_ADAPTER_SETP(SPEED, 8); \ - break; \ - case BFA_MFG_TYPE_FC4P2: \ - (prop) = BFI_ADAPTER_SETP(NPORTS, 2) | \ - BFI_ADAPTER_SETP(SPEED, 4); \ - break; \ - case BFA_MFG_TYPE_FC4P1: \ - (prop) = BFI_ADAPTER_SETP(NPORTS, 1) | \ - BFI_ADAPTER_SETP(SPEED, 4); \ - break; \ case BFA_MFG_TYPE_CNA10P2: \ case BFA_MFG_TYPE_WANCHESE: \ case BFA_MFG_TYPE_LIGHTNING_P0: \ diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.c b/drivers/net/ethernet/brocade/bna/bfa_ioc.c index 2d5c4fd778ee..029fb527e80d 100644 --- a/drivers/net/ethernet/brocade/bna/bfa_ioc.c +++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.c @@ -62,6 +62,7 @@ static void bfa_ioc_hw_sem_init(struct bfa_ioc *ioc); static void bfa_ioc_hw_sem_get(struct bfa_ioc *ioc); static void bfa_ioc_hw_sem_get_cancel(struct bfa_ioc *ioc); static void bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force); +static void bfa_ioc_poll_fwinit(struct bfa_ioc *ioc); static void bfa_ioc_send_enable(struct bfa_ioc *ioc); static void bfa_ioc_send_disable(struct bfa_ioc *ioc); static void bfa_ioc_send_getattr(struct bfa_ioc *ioc); @@ -78,8 +79,8 @@ static void bfa_ioc_lpu_stop(struct bfa_ioc *ioc); static void bfa_ioc_fail_notify(struct bfa_ioc *ioc); static void bfa_ioc_pf_enabled(struct bfa_ioc *ioc); static void bfa_ioc_pf_disabled(struct bfa_ioc *ioc); -static void bfa_ioc_pf_initfailed(struct bfa_ioc *ioc); static void bfa_ioc_pf_failed(struct bfa_ioc *ioc); +static void bfa_ioc_pf_hwfailed(struct bfa_ioc *ioc); static void bfa_ioc_pf_fwmismatch(struct bfa_ioc *ioc); static void bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_param); @@ -108,11 +109,11 @@ enum ioc_event { IOC_E_ENABLED = 5, /*!< f/w enabled */ IOC_E_FWRSP_GETATTR = 6, /*!< IOC get attribute response */ IOC_E_DISABLED = 7, /*!< f/w disabled */ - IOC_E_INITFAILED = 8, /*!< failure notice by iocpf sm */ - IOC_E_PFFAILED = 9, /*!< failure notice by iocpf sm */ - IOC_E_HBFAIL = 10, /*!< heartbeat failure */ - IOC_E_HWERROR = 11, /*!< hardware error interrupt */ - IOC_E_TIMEOUT = 12, /*!< timeout */ + IOC_E_PFFAILED = 8, /*!< failure notice by iocpf sm */ + IOC_E_HBFAIL = 9, /*!< heartbeat failure */ + IOC_E_HWERROR = 10, /*!< hardware error interrupt */ + IOC_E_TIMEOUT = 11, /*!< timeout */ + IOC_E_HWFAILED = 12, /*!< PCI mapping failure notice */ }; bfa_fsm_state_decl(bfa_ioc, uninit, struct bfa_ioc, enum ioc_event); @@ -124,6 +125,7 @@ bfa_fsm_state_decl(bfa_ioc, fail_retry, struct bfa_ioc, enum ioc_event); bfa_fsm_state_decl(bfa_ioc, fail, struct bfa_ioc, enum ioc_event); bfa_fsm_state_decl(bfa_ioc, disabling, struct bfa_ioc, enum ioc_event); bfa_fsm_state_decl(bfa_ioc, disabled, struct bfa_ioc, enum ioc_event); +bfa_fsm_state_decl(bfa_ioc, hwfail, struct bfa_ioc, enum ioc_event); static struct bfa_sm_table ioc_sm_table[] = { {BFA_SM(bfa_ioc_sm_uninit), BFA_IOC_UNINIT}, @@ -135,6 +137,7 @@ static struct bfa_sm_table ioc_sm_table[] = { {BFA_SM(bfa_ioc_sm_fail), BFA_IOC_FAIL}, {BFA_SM(bfa_ioc_sm_disabling), BFA_IOC_DISABLING}, {BFA_SM(bfa_ioc_sm_disabled), BFA_IOC_DISABLED}, + {BFA_SM(bfa_ioc_sm_hwfail), BFA_IOC_HWFAIL}, }; /** @@ -166,6 +169,7 @@ enum iocpf_event { IOCPF_E_GETATTRFAIL = 9, /*!< init fail notice by ioc sm */ IOCPF_E_SEMLOCKED = 10, /*!< h/w semaphore is locked */ IOCPF_E_TIMEOUT = 11, /*!< f/w response timeout */ + IOCPF_E_SEM_ERROR = 12, /*!< h/w sem mapping error */ }; /** @@ -300,11 +304,16 @@ bfa_ioc_sm_enabling(struct bfa_ioc *ioc, enum ioc_event event) /* !!! fall through !!! */ case IOC_E_HWERROR: ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); - bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry); + bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); if (event != IOC_E_PFFAILED) bfa_iocpf_initfail(ioc); break; + case IOC_E_HWFAILED: + ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); + bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail); + break; + case IOC_E_DISABLE: bfa_fsm_set_state(ioc, bfa_ioc_sm_disabling); break; @@ -343,6 +352,7 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event) case IOC_E_FWRSP_GETATTR: del_timer(&ioc->ioc_timer); bfa_ioc_check_attr_wwns(ioc); + bfa_ioc_hb_monitor(ioc); bfa_fsm_set_state(ioc, bfa_ioc_sm_op); break; @@ -352,7 +362,7 @@ bfa_ioc_sm_getattr(struct bfa_ioc *ioc, enum ioc_event event) /* fall through */ case IOC_E_TIMEOUT: ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); - bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry); + bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); if (event != IOC_E_PFFAILED) bfa_iocpf_getattrfail(ioc); break; @@ -374,7 +384,7 @@ static void bfa_ioc_sm_op_entry(struct bfa_ioc *ioc) { ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK); - bfa_ioc_hb_monitor(ioc); + bfa_ioc_event_notify(ioc, BFA_IOC_E_ENABLED); } static void @@ -394,12 +404,13 @@ bfa_ioc_sm_op(struct bfa_ioc *ioc, enum ioc_event event) bfa_ioc_hb_stop(ioc); /* !!! fall through !!! */ case IOC_E_HBFAIL: - bfa_ioc_fail_notify(ioc); if (ioc->iocpf.auto_recover) bfa_fsm_set_state(ioc, bfa_ioc_sm_fail_retry); else bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); + bfa_ioc_fail_notify(ioc); + if (event != IOC_E_PFFAILED) bfa_iocpf_fail(ioc); break; @@ -435,6 +446,11 @@ bfa_ioc_sm_disabling(struct bfa_ioc *ioc, enum ioc_event event) bfa_iocpf_fail(ioc); break; + case IOC_E_HWFAILED: + bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail); + bfa_ioc_disable_comp(ioc); + break; + default: bfa_sm_fault(event); } @@ -493,12 +509,14 @@ bfa_ioc_sm_fail_retry(struct bfa_ioc *ioc, enum ioc_event event) * Initialization retry failed. */ ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); + bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); if (event != IOC_E_PFFAILED) bfa_iocpf_initfail(ioc); break; - case IOC_E_INITFAILED: - bfa_fsm_set_state(ioc, bfa_ioc_sm_fail); + case IOC_E_HWFAILED: + ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); + bfa_fsm_set_state(ioc, bfa_ioc_sm_hwfail); break; case IOC_E_ENABLE: @@ -552,6 +570,36 @@ bfa_ioc_sm_fail(struct bfa_ioc *ioc, enum ioc_event event) } } +static void +bfa_ioc_sm_hwfail_entry(struct bfa_ioc *ioc) +{ +} + +/** + * IOC failure. + */ +static void +bfa_ioc_sm_hwfail(struct bfa_ioc *ioc, enum ioc_event event) +{ + switch (event) { + + case IOC_E_ENABLE: + ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE); + break; + + case IOC_E_DISABLE: + ioc->cbfn->disable_cbfn(ioc->bfa); + break; + + case IOC_E_DETACH: + bfa_fsm_set_state(ioc, bfa_ioc_sm_uninit); + break; + + default: + bfa_sm_fault(event); + } +} + /** * IOCPF State Machine */ @@ -562,7 +610,7 @@ bfa_ioc_sm_fail(struct bfa_ioc *ioc, enum ioc_event event) static void bfa_iocpf_sm_reset_entry(struct bfa_iocpf *iocpf) { - iocpf->retry_count = 0; + iocpf->fw_mismatch_notified = false; iocpf->auto_recover = bfa_nw_auto_recover; } @@ -607,7 +655,6 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event) case IOCPF_E_SEMLOCKED: if (bfa_ioc_firmware_lock(ioc)) { if (bfa_ioc_sync_start(ioc)) { - iocpf->retry_count = 0; bfa_ioc_sync_join(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); } else { @@ -622,6 +669,11 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event) } break; + case IOCPF_E_SEM_ERROR: + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); + bfa_ioc_pf_hwfailed(ioc); + break; + case IOCPF_E_DISABLE: bfa_ioc_hw_sem_get_cancel(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_reset); @@ -645,10 +697,10 @@ static void bfa_iocpf_sm_mismatch_entry(struct bfa_iocpf *iocpf) { /* Call only the first time sm enters fwmismatch state. */ - if (iocpf->retry_count == 0) + if (iocpf->fw_mismatch_notified == false) bfa_ioc_pf_fwmismatch(iocpf->ioc); - iocpf->retry_count++; + iocpf->fw_mismatch_notified = true; mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies + msecs_to_jiffies(BFA_IOC_TOV)); } @@ -711,6 +763,11 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf *iocpf, enum iocpf_event event) } break; + case IOCPF_E_SEM_ERROR: + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); + bfa_ioc_pf_hwfailed(ioc); + break; + case IOCPF_E_DISABLE: bfa_ioc_hw_sem_get_cancel(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); @@ -724,8 +781,7 @@ bfa_iocpf_sm_semwait(struct bfa_iocpf *iocpf, enum iocpf_event event) static void bfa_iocpf_sm_hwinit_entry(struct bfa_iocpf *iocpf) { - mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies + - msecs_to_jiffies(BFA_IOC_TOV)); + iocpf->poll_time = 0; bfa_ioc_reset(iocpf->ioc, 0); } @@ -740,19 +796,11 @@ bfa_iocpf_sm_hwinit(struct bfa_iocpf *iocpf, enum iocpf_event event) switch (event) { case IOCPF_E_FWREADY: - del_timer(&ioc->iocpf_timer); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_enabling); break; - case IOCPF_E_INITFAIL: - del_timer(&ioc->iocpf_timer); - /* - * !!! fall through !!! - */ - case IOCPF_E_TIMEOUT: bfa_nw_ioc_hw_sem_release(ioc); - if (event == IOCPF_E_TIMEOUT) bfa_ioc_pf_failed(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync); break; @@ -774,6 +822,10 @@ bfa_iocpf_sm_enabling_entry(struct bfa_iocpf *iocpf) { mod_timer(&(iocpf->ioc)->iocpf_timer, jiffies + msecs_to_jiffies(BFA_IOC_TOV)); + /** + * Enable Interrupts before sending fw IOC ENABLE cmd. + */ + iocpf->ioc->cbfn->reset_cbfn(iocpf->ioc->bfa); bfa_ioc_send_enable(iocpf->ioc); } @@ -811,21 +863,11 @@ bfa_iocpf_sm_enabling(struct bfa_iocpf *iocpf, enum iocpf_event event) bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling); break; - case IOCPF_E_FWREADY: - bfa_ioc_send_enable(ioc); - break; - default: bfa_sm_fault(event); } } -static bool -bfa_nw_ioc_is_operational(struct bfa_ioc *ioc) -{ - return bfa_fsm_cmp_state(ioc, bfa_ioc_sm_op); -} - static void bfa_iocpf_sm_ready_entry(struct bfa_iocpf *iocpf) { @@ -835,8 +877,6 @@ bfa_iocpf_sm_ready_entry(struct bfa_iocpf *iocpf) static void bfa_iocpf_sm_ready(struct bfa_iocpf *iocpf, enum iocpf_event event) { - struct bfa_ioc *ioc = iocpf->ioc; - switch (event) { case IOCPF_E_DISABLE: bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling); @@ -850,14 +890,6 @@ bfa_iocpf_sm_ready(struct bfa_iocpf *iocpf, enum iocpf_event event) bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync); break; - case IOCPF_E_FWREADY: - bfa_ioc_pf_failed(ioc); - if (bfa_nw_ioc_is_operational(ioc)) - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail_sync); - else - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail_sync); - break; - default: bfa_sm_fault(event); } @@ -881,7 +913,6 @@ bfa_iocpf_sm_disabling(struct bfa_iocpf *iocpf, enum iocpf_event event) switch (event) { case IOCPF_E_FWRSP_DISABLE: - case IOCPF_E_FWREADY: del_timer(&ioc->iocpf_timer); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); break; @@ -926,6 +957,11 @@ bfa_iocpf_sm_disabling_sync(struct bfa_iocpf *iocpf, enum iocpf_event event) bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabled); break; + case IOCPF_E_SEM_ERROR: + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); + bfa_ioc_pf_hwfailed(ioc); + break; + case IOCPF_E_FAIL: break; @@ -951,7 +987,6 @@ bfa_iocpf_sm_disabled(struct bfa_iocpf *iocpf, enum iocpf_event event) switch (event) { case IOCPF_E_ENABLE: - iocpf->retry_count = 0; bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait); break; @@ -982,20 +1017,15 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event) switch (event) { case IOCPF_E_SEMLOCKED: bfa_ioc_notify_fail(ioc); - bfa_ioc_sync_ack(ioc); - iocpf->retry_count++; - if (iocpf->retry_count >= BFA_IOC_HWINIT_MAX) { - bfa_ioc_sync_leave(ioc); - bfa_nw_ioc_hw_sem_release(ioc); - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); - } else { - if (bfa_ioc_sync_complete(ioc)) - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit); - else { - bfa_nw_ioc_hw_sem_release(ioc); - bfa_fsm_set_state(iocpf, bfa_iocpf_sm_semwait); - } - } + bfa_ioc_sync_leave(ioc); + writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); + bfa_nw_ioc_hw_sem_release(ioc); + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_initfail); + break; + + case IOCPF_E_SEM_ERROR: + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); + bfa_ioc_pf_hwfailed(ioc); break; case IOCPF_E_DISABLE: @@ -1020,7 +1050,6 @@ bfa_iocpf_sm_initfail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event) static void bfa_iocpf_sm_initfail_entry(struct bfa_iocpf *iocpf) { - bfa_ioc_pf_initfailed(iocpf->ioc); } /** @@ -1071,11 +1100,11 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event) switch (event) { case IOCPF_E_SEMLOCKED: - iocpf->retry_count = 0; bfa_ioc_sync_ack(ioc); bfa_ioc_notify_fail(ioc); if (!iocpf->auto_recover) { bfa_ioc_sync_leave(ioc); + writel(BFI_IOC_FAIL, ioc->ioc_regs.ioc_fwstate); bfa_nw_ioc_hw_sem_release(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); } else { @@ -1088,6 +1117,11 @@ bfa_iocpf_sm_fail_sync(struct bfa_iocpf *iocpf, enum iocpf_event event) } break; + case IOCPF_E_SEM_ERROR: + bfa_fsm_set_state(iocpf, bfa_iocpf_sm_fail); + bfa_ioc_pf_hwfailed(ioc); + break; + case IOCPF_E_DISABLE: bfa_ioc_hw_sem_get_cancel(ioc); bfa_fsm_set_state(iocpf, bfa_iocpf_sm_disabling_sync); @@ -1158,13 +1192,13 @@ bfa_nw_ioc_sem_get(void __iomem *sem_reg) r32 = readl(sem_reg); - while (r32 && (cnt < BFA_SEM_SPINCNT)) { + while ((r32 & 1) && (cnt < BFA_SEM_SPINCNT)) { cnt++; udelay(2); r32 = readl(sem_reg); } - if (r32 == 0) + if (!(r32 & 1)) return true; BUG_ON(!(cnt < BFA_SEM_SPINCNT)); @@ -1210,7 +1244,11 @@ bfa_ioc_hw_sem_get(struct bfa_ioc *ioc) * will return 1. Semaphore is released by writing 1 to the register */ r32 = readl(ioc->ioc_regs.ioc_sem_reg); - if (r32 == 0) { + if (r32 == ~0) { + bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEM_ERROR); + return; + } + if (!(r32 & 1)) { bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_SEMLOCKED); return; } @@ -1331,7 +1369,7 @@ bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr) int i; drv_fwhdr = (struct bfi_ioc_image_hdr *) - bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0); + bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0); for (i = 0; i < BFI_IOC_MD5SUM_SZ; i++) { if (fwhdr->md5sum[i] != drv_fwhdr->md5sum[i]) @@ -1352,12 +1390,12 @@ bfa_ioc_fwver_valid(struct bfa_ioc *ioc, u32 boot_env) bfa_nw_ioc_fwver_get(ioc, &fwhdr); drv_fwhdr = (struct bfi_ioc_image_hdr *) - bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), 0); + bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), 0); if (fwhdr.signature != drv_fwhdr->signature) return false; - if (swab32(fwhdr.param) != boot_env) + if (swab32(fwhdr.bootenv) != boot_env) return false; return bfa_nw_ioc_fwver_cmp(ioc, &fwhdr); @@ -1388,11 +1426,11 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force) ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate); - boot_env = BFI_BOOT_LOADER_OS; - if (force) ioc_fwstate = BFI_IOC_UNINIT; + boot_env = BFI_FWBOOT_ENV_OS; + /** * check if firmware is valid */ @@ -1400,7 +1438,8 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force) false : bfa_ioc_fwver_valid(ioc, boot_env); if (!fwvalid) { - bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, boot_env); + bfa_ioc_boot(ioc, BFI_FWBOOT_TYPE_NORMAL, boot_env); + bfa_ioc_poll_fwinit(ioc); return; } @@ -1409,7 +1448,7 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force) * just wait for an initialization completion interrupt. */ if (ioc_fwstate == BFI_IOC_INITING) { - ioc->cbfn->reset_cbfn(ioc->bfa); + bfa_ioc_poll_fwinit(ioc); return; } @@ -1423,7 +1462,6 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force) * be flushed. Otherwise MSI-X interrupts are not delivered. */ bfa_ioc_msgflush(ioc); - ioc->cbfn->reset_cbfn(ioc->bfa); bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY); return; } @@ -1431,7 +1469,8 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force) /** * Initialize the h/w for any other states. */ - bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, boot_env); + bfa_ioc_boot(ioc, BFI_FWBOOT_TYPE_NORMAL, boot_env); + bfa_ioc_poll_fwinit(ioc); } void @@ -1475,7 +1514,7 @@ bfa_ioc_send_enable(struct bfa_ioc *ioc) bfi_h2i_set(enable_req.mh, BFI_MC_IOC, BFI_IOC_H2I_ENABLE_REQ, bfa_ioc_portid(ioc)); - enable_req.ioc_class = ioc->ioc_mc; + enable_req.clscode = htons(ioc->clscode); do_gettimeofday(&tv); enable_req.tv_sec = ntohl(tv.tv_sec); bfa_ioc_mbox_send(ioc, &enable_req, sizeof(struct bfi_ioc_ctrl_req)); @@ -1548,22 +1587,23 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type, u32 loff = 0; u32 chunkno = 0; u32 i; + u32 asicmode; /** * Initialize LMEM first before code download */ bfa_ioc_lmem_init(ioc); - fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), chunkno); + fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), chunkno); pgnum = bfa_ioc_smem_pgnum(ioc, loff); writel(pgnum, ioc->ioc_regs.host_page_num_fn); - for (i = 0; i < bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)); i++) { + for (i = 0; i < bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)); i++) { if (BFA_IOC_FLASH_CHUNK_NO(i) != chunkno) { chunkno = BFA_IOC_FLASH_CHUNK_NO(i); - fwimg = bfa_cb_image_get_chunk(BFA_IOC_FWIMG_TYPE(ioc), + fwimg = bfa_cb_image_get_chunk(bfa_ioc_asic_gen(ioc), BFA_IOC_FLASH_CHUNK_ADDR(chunkno)); } @@ -1590,12 +1630,16 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type, ioc->ioc_regs.host_page_num_fn); /* - * Set boot type and boot param at the end. + * Set boot type, env and device mode at the end. */ + asicmode = BFI_FWBOOT_DEVMODE(ioc->asic_gen, ioc->asic_mode, + ioc->port0_mode, ioc->port1_mode); + writel(asicmode, ((ioc->ioc_regs.smem_page_start) + + BFI_FWBOOT_DEVMODE_OFF)); writel(boot_type, ((ioc->ioc_regs.smem_page_start) - + (BFI_BOOT_TYPE_OFF))); + + (BFI_FWBOOT_TYPE_OFF))); writel(boot_env, ((ioc->ioc_regs.smem_page_start) - + (BFI_BOOT_LOADER_OFF))); + + (BFI_FWBOOT_ENV_OFF))); } static void @@ -1605,6 +1649,20 @@ bfa_ioc_reset(struct bfa_ioc *ioc, bool force) } /** + * BFA ioc enable reply by firmware + */ +static void +bfa_ioc_enable_reply(struct bfa_ioc *ioc, enum bfa_mode port_mode, + u8 cap_bm) +{ + struct bfa_iocpf *iocpf = &ioc->iocpf; + + ioc->port_mode = ioc->port_mode_cfg = port_mode; + ioc->ad_cap_bm = cap_bm; + bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE); +} + +/** * @brief * Update BFA configuration from firmware configuration. */ @@ -1644,7 +1702,9 @@ bfa_ioc_mbox_poll(struct bfa_ioc *ioc) { struct bfa_ioc_mbox_mod *mod = &ioc->mbox_mod; struct bfa_mbox_cmd *cmd; - u32 stat; + bfa_mbox_cmd_cbfn_t cbfn; + void *cbarg; + u32 stat; /** * If no command pending, do nothing @@ -1664,6 +1724,16 @@ bfa_ioc_mbox_poll(struct bfa_ioc *ioc) */ bfa_q_deq(&mod->cmd_q, &cmd); bfa_ioc_mbox_send(ioc, cmd->msg, sizeof(cmd->msg)); + + /** + * Give a callback to the client, indicating that the command is sent + */ + if (cmd->cbfn) { + cbfn = cmd->cbfn; + cbarg = cmd->cbarg; + cmd->cbfn = NULL; + cbfn(cbarg); + } } /** @@ -1702,15 +1772,15 @@ bfa_ioc_pf_disabled(struct bfa_ioc *ioc) } static void -bfa_ioc_pf_initfailed(struct bfa_ioc *ioc) +bfa_ioc_pf_failed(struct bfa_ioc *ioc) { - bfa_fsm_send_event(ioc, IOC_E_INITFAILED); + bfa_fsm_send_event(ioc, IOC_E_PFFAILED); } static void -bfa_ioc_pf_failed(struct bfa_ioc *ioc) +bfa_ioc_pf_hwfailed(struct bfa_ioc *ioc) { - bfa_fsm_send_event(ioc, IOC_E_PFFAILED); + bfa_fsm_send_event(ioc, IOC_E_HWFAILED); } static void @@ -1749,10 +1819,9 @@ bfa_ioc_pll_init(struct bfa_ioc *ioc) * as the entry vector. */ static void -bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_env) +bfa_ioc_boot(struct bfa_ioc *ioc, enum bfi_fwboot_type boot_type, + u32 boot_env) { - void __iomem *rb; - bfa_ioc_stats(ioc, ioc_boots); if (bfa_ioc_pll_init(ioc) != BFA_STATUS_OK) @@ -1761,22 +1830,16 @@ bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_env) /** * Initialize IOC state of all functions on a chip reset. */ - rb = ioc->pcidev.pci_bar_kva; - if (boot_type == BFI_BOOT_TYPE_MEMTEST) { - writel(BFI_IOC_MEMTEST, (rb + BFA_IOC0_STATE_REG)); - writel(BFI_IOC_MEMTEST, (rb + BFA_IOC1_STATE_REG)); + if (boot_type == BFI_FWBOOT_TYPE_MEMTEST) { + writel(BFI_IOC_MEMTEST, ioc->ioc_regs.ioc_fwstate); + writel(BFI_IOC_MEMTEST, ioc->ioc_regs.alt_ioc_fwstate); } else { - writel(BFI_IOC_INITING, (rb + BFA_IOC0_STATE_REG)); - writel(BFI_IOC_INITING, (rb + BFA_IOC1_STATE_REG)); + writel(BFI_IOC_INITING, ioc->ioc_regs.ioc_fwstate); + writel(BFI_IOC_INITING, ioc->ioc_regs.alt_ioc_fwstate); } bfa_ioc_msgflush(ioc); bfa_ioc_download_fw(ioc, boot_type, boot_env); - - /** - * Enable interrupts just before starting LPU - */ - ioc->cbfn->reset_cbfn(ioc->bfa); bfa_ioc_lpu_start(ioc); } @@ -1789,13 +1852,17 @@ bfa_nw_ioc_auto_recover(bool auto_recover) bfa_nw_auto_recover = auto_recover; } -static void +static bool bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg) { u32 *msgp = mbmsg; u32 r32; int i; + r32 = readl(ioc->ioc_regs.lpu_mbox_cmd); + if ((r32 & 1) == 0) + return false; + /** * read the MBOX msg */ @@ -1811,6 +1878,8 @@ bfa_ioc_msgget(struct bfa_ioc *ioc, void *mbmsg) */ writel(1, ioc->ioc_regs.lpu_mbox_cmd); readl(ioc->ioc_regs.lpu_mbox_cmd); + + return true; } static void @@ -1827,12 +1896,10 @@ bfa_ioc_isr(struct bfa_ioc *ioc, struct bfi_mbmsg *m) case BFI_IOC_I2H_HBEAT: break; - case BFI_IOC_I2H_READY_EVENT: - bfa_fsm_send_event(iocpf, IOCPF_E_FWREADY); - break; - case BFI_IOC_I2H_ENABLE_REPLY: - bfa_fsm_send_event(iocpf, IOCPF_E_FWRSP_ENABLE); + bfa_ioc_enable_reply(ioc, + (enum bfa_mode)msg->fw_event.port_mode, + msg->fw_event.cap_bm); break; case BFI_IOC_I2H_DISABLE_REPLY: @@ -1878,6 +1945,9 @@ void bfa_nw_ioc_detach(struct bfa_ioc *ioc) { bfa_fsm_send_event(ioc, IOC_E_DETACH); + + /* Done with detach, empty the notify_q. */ + INIT_LIST_HEAD(&ioc->notify_q); } /** @@ -1887,12 +1957,29 @@ bfa_nw_ioc_detach(struct bfa_ioc *ioc) */ void bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev, - enum bfi_mclass mc) + enum bfi_pcifn_class clscode) { - ioc->ioc_mc = mc; + ioc->clscode = clscode; ioc->pcidev = *pcidev; - ioc->ctdev = bfa_asic_id_ct(ioc->pcidev.device_id); - ioc->cna = ioc->ctdev && !ioc->fcmode; + + /** + * Initialize IOC and device personality + */ + ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_FC; + ioc->asic_mode = BFI_ASIC_MODE_FC; + + switch (pcidev->device_id) { + case PCI_DEVICE_ID_BROCADE_CT: + ioc->asic_gen = BFI_ASIC_GEN_CT; + ioc->port0_mode = ioc->port1_mode = BFI_PORT_MODE_ETH; + ioc->asic_mode = BFI_ASIC_MODE_ETH; + ioc->port_mode = ioc->port_mode_cfg = BFA_MODE_CNA; + ioc->ad_cap_bm = BFA_CM_CNA; + break; + + default: + BUG_ON(1); + } bfa_nw_ioc_set_ct_hwif(ioc); @@ -2013,21 +2100,28 @@ bfa_nw_ioc_mbox_isr(struct bfa_ioc *ioc) struct bfi_mbmsg m; int mc; - bfa_ioc_msgget(ioc, &m); + if (bfa_ioc_msgget(ioc, &m)) { + /** + * Treat IOC message class as special. + */ + mc = m.mh.msg_class; + if (mc == BFI_MC_IOC) { + bfa_ioc_isr(ioc, &m); + return; + } - /** - * Treat IOC message class as special. - */ - mc = m.mh.msg_class; - if (mc == BFI_MC_IOC) { - bfa_ioc_isr(ioc, &m); - return; + if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL)) + return; + + mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m); } - if ((mc >= BFI_MC_MAX) || (mod->mbhdlr[mc].cbfn == NULL)) - return; + bfa_ioc_lpu_read_stat(ioc); - mod->mbhdlr[mc].cbfn(mod->mbhdlr[mc].cbarg, &m); + /** + * Try to send pending mailbox commands + */ + bfa_ioc_mbox_poll(ioc); } void @@ -2099,24 +2193,18 @@ bfa_ioc_get_adapter_attr(struct bfa_ioc *ioc, ad_attr->asic_rev = ioc_attr->asic_rev; bfa_ioc_get_pci_chip_rev(ioc, ad_attr->hw_ver); - - ad_attr->cna_capable = ioc->cna; - ad_attr->trunk_capable = (ad_attr->nports > 1) && !ioc->cna; } static enum bfa_ioc_type bfa_ioc_get_type(struct bfa_ioc *ioc) { - if (!ioc->ctdev || ioc->fcmode) - return BFA_IOC_TYPE_FC; - else if (ioc->ioc_mc == BFI_MC_IOCFC) - return BFA_IOC_TYPE_FCoE; - else if (ioc->ioc_mc == BFI_MC_LL) - return BFA_IOC_TYPE_LL; - else { - BUG_ON(!(ioc->ioc_mc == BFI_MC_LL)); + if (ioc->clscode == BFI_PCIFN_CLASS_ETH) return BFA_IOC_TYPE_LL; - } + + BUG_ON(!(ioc->clscode == BFI_PCIFN_CLASS_FC)); + + return (ioc->attr->port_mode == BFI_PORT_MODE_FC) + ? BFA_IOC_TYPE_FC : BFA_IOC_TYPE_FCoE; } static void @@ -2228,6 +2316,10 @@ bfa_nw_ioc_get_attr(struct bfa_ioc *ioc, struct bfa_ioc_attr *ioc_attr) ioc_attr->state = bfa_ioc_get_state(ioc); ioc_attr->port_id = ioc->port_id; + ioc_attr->port_mode = ioc->port_mode; + + ioc_attr->port_mode_cfg = ioc->port_mode_cfg; + ioc_attr->cap_bm = ioc->ad_cap_bm; ioc_attr->ioc_type = bfa_ioc_get_type(ioc); @@ -2317,8 +2409,14 @@ void bfa_nw_iocpf_timeout(void *ioc_arg) { struct bfa_ioc *ioc = (struct bfa_ioc *) ioc_arg; + enum bfa_iocpf_state iocpf_st; + + iocpf_st = bfa_sm_to_state(iocpf_sm_table, ioc->iocpf.fsm); - bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT); + if (iocpf_st == BFA_IOCPF_HWINIT) + bfa_ioc_poll_fwinit(ioc); + else + bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_TIMEOUT); } void @@ -2328,3 +2426,22 @@ bfa_nw_iocpf_sem_timeout(void *ioc_arg) bfa_ioc_hw_sem_get(ioc); } + +static void +bfa_ioc_poll_fwinit(struct bfa_ioc *ioc) +{ + u32 fwstate = readl(ioc->ioc_regs.ioc_fwstate); + + if (fwstate == BFI_IOC_DISABLED) { + bfa_fsm_send_event(&ioc->iocpf, IOCPF_E_FWREADY); + return; + } + + if (ioc->iocpf.poll_time >= BFA_IOC_TOV) { + bfa_nw_iocpf_timeout(ioc); + } else { + ioc->iocpf.poll_time += BFA_IOC_POLL_TOV; + mod_timer(&ioc->iocpf_timer, jiffies + + msecs_to_jiffies(BFA_IOC_POLL_TOV)); + } +} diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc.h b/drivers/net/ethernet/brocade/bna/bfa_ioc.h index 33ba5f40ca37..7514c722ebc3 100644 --- a/drivers/net/ethernet/brocade/bna/bfa_ioc.h +++ b/drivers/net/ethernet/brocade/bna/bfa_ioc.h @@ -27,6 +27,7 @@ #define BFA_IOC_HWSEM_TOV 500 /* msecs */ #define BFA_IOC_HB_TOV 500 /* msecs */ #define BFA_IOC_HWINIT_MAX 5 +#define BFA_IOC_POLL_TOV 200 /* msecs */ /** * PCI device information required by IOC @@ -169,8 +170,9 @@ struct bfa_ioc_hbfail_notify { struct bfa_iocpf { bfa_fsm_t fsm; struct bfa_ioc *ioc; - u32 retry_count; + bool fw_mismatch_notified; bool auto_recover; + u32 poll_time; }; struct bfa_ioc { @@ -186,12 +188,10 @@ struct bfa_ioc { void *dbg_fwsave; int dbg_fwsave_len; bool dbg_fwsave_once; - enum bfi_mclass ioc_mc; + enum bfi_pcifn_class clscode; struct bfa_ioc_regs ioc_regs; struct bfa_ioc_drv_stats stats; bool fcmode; - bool ctdev; - bool cna; bool pllinit; bool stats_busy; /*!< outstanding stats */ u8 port_id; @@ -202,10 +202,18 @@ struct bfa_ioc { struct bfa_ioc_mbox_mod mbox_mod; struct bfa_ioc_hwif *ioc_hwif; struct bfa_iocpf iocpf; + enum bfi_asic_gen asic_gen; + enum bfi_asic_mode asic_mode; + enum bfi_port_mode port0_mode; + enum bfi_port_mode port1_mode; + enum bfa_mode port_mode; + u8 ad_cap_bm; /*!< adapter cap bit mask */ + u8 port_mode_cfg; /*!< config port mode */ }; struct bfa_ioc_hwif { - enum bfa_status (*ioc_pll_init) (void __iomem *rb, bool fcmode); + enum bfa_status (*ioc_pll_init) (void __iomem *rb, + enum bfi_asic_mode m); bool (*ioc_firmware_lock) (struct bfa_ioc *ioc); void (*ioc_firmware_unlock) (struct bfa_ioc *ioc); void (*ioc_reg_init) (struct bfa_ioc *ioc); @@ -219,12 +227,14 @@ struct bfa_ioc_hwif { void (*ioc_sync_leave) (struct bfa_ioc *ioc); void (*ioc_sync_ack) (struct bfa_ioc *ioc); bool (*ioc_sync_complete) (struct bfa_ioc *ioc); + bool (*ioc_lpu_read_stat) (struct bfa_ioc *ioc); }; #define bfa_ioc_pcifn(__ioc) ((__ioc)->pcidev.pci_func) #define bfa_ioc_devid(__ioc) ((__ioc)->pcidev.device_id) #define bfa_ioc_bar0(__ioc) ((__ioc)->pcidev.pci_bar_kva) #define bfa_ioc_portid(__ioc) ((__ioc)->port_id) +#define bfa_ioc_asic_gen(__ioc) ((__ioc)->asic_gen) #define bfa_ioc_fetch_stats(__ioc, __stats) \ (((__stats)->drv_stats) = (__ioc)->stats) #define bfa_ioc_clr_stats(__ioc) \ @@ -245,7 +255,8 @@ struct bfa_ioc_hwif { (((__ioc)->fcmode) ? BFI_IMAGE_CT_FC : BFI_IMAGE_CT_CNA) : \ BFI_IMAGE_CB_FC) #define BFA_IOC_FW_SMEM_SIZE(__ioc) \ - (((__ioc)->ctdev) ? BFI_SMEM_CT_SIZE : BFI_SMEM_CB_SIZE) + ((bfa_ioc_asic_gen(__ioc) == BFI_ASIC_GEN_CB) \ + ? BFI_SMEM_CB_SIZE : BFI_SMEM_CT_SIZE) #define BFA_IOC_FLASH_CHUNK_NO(off) (off / BFI_FLASH_CHUNK_SZ_WORDS) #define BFA_IOC_FLASH_OFFSET_IN_CHUNK(off) (off % BFI_FLASH_CHUNK_SZ_WORDS) #define BFA_IOC_FLASH_CHUNK_ADDR(chunkno) (chunkno * BFI_FLASH_CHUNK_SZ_WORDS) @@ -266,13 +277,18 @@ void bfa_nw_ioc_mbox_regisr(struct bfa_ioc *ioc, enum bfi_mclass mc, #define bfa_ioc_pll_init_asic(__ioc) \ ((__ioc)->ioc_hwif->ioc_pll_init((__ioc)->pcidev.pci_bar_kva, \ - (__ioc)->fcmode)) + (__ioc)->asic_mode)) #define bfa_ioc_isr_mode_set(__ioc, __msix) \ ((__ioc)->ioc_hwif->ioc_isr_mode_set(__ioc, __msix)) #define bfa_ioc_ownership_reset(__ioc) \ ((__ioc)->ioc_hwif->ioc_ownership_reset(__ioc)) +#define bfa_ioc_lpu_read_stat(__ioc) do { \ + if ((__ioc)->ioc_hwif->ioc_lpu_read_stat) \ + ((__ioc)->ioc_hwif->ioc_lpu_read_stat(__ioc)); \ +} while (0) + void bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc); void bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa, @@ -280,7 +296,7 @@ void bfa_nw_ioc_attach(struct bfa_ioc *ioc, void *bfa, void bfa_nw_ioc_auto_recover(bool auto_recover); void bfa_nw_ioc_detach(struct bfa_ioc *ioc); void bfa_nw_ioc_pci_init(struct bfa_ioc *ioc, struct bfa_pcidev *pcidev, - enum bfi_mclass mc); + enum bfi_pcifn_class clscode); u32 bfa_nw_ioc_meminfo(void); void bfa_nw_ioc_mem_claim(struct bfa_ioc *ioc, u8 *dm_kva, u64 dm_pa); void bfa_nw_ioc_enable(struct bfa_ioc *ioc); @@ -311,7 +327,7 @@ void bfa_nw_iocpf_sem_timeout(void *ioc); /* * F/W Image Size & Chunk */ -u32 *bfa_cb_image_get_chunk(int type, u32 off); -u32 bfa_cb_image_get_size(int type); +u32 *bfa_cb_image_get_chunk(enum bfi_asic_gen asic_gen, u32 off); +u32 bfa_cb_image_get_size(enum bfi_asic_gen asic_gen); #endif /* __BFA_IOC_H__ */ diff --git a/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c b/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c index 209f1f320343..b4429bc67c34 100644 --- a/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c +++ b/drivers/net/ethernet/brocade/bna/bfa_ioc_ct.c @@ -46,7 +46,8 @@ static void bfa_ioc_ct_sync_join(struct bfa_ioc *ioc); static void bfa_ioc_ct_sync_leave(struct bfa_ioc *ioc); static void bfa_ioc_ct_sync_ack(struct bfa_ioc *ioc); static bool bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc); -static enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode); +static enum bfa_status bfa_ioc_ct_pll_init(void __iomem *rb, + enum bfi_asic_mode asic_mode); static struct bfa_ioc_hwif nw_hwif_ct; @@ -92,7 +93,7 @@ bfa_ioc_ct_firmware_lock(struct bfa_ioc *ioc) /** * If bios boot (flash based) -- do not increment usage count */ - if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < + if (bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)) < BFA_IOC_FWIMG_MINSZ) return true; @@ -142,7 +143,7 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc) /** * If bios boot (flash based) -- do not decrement usage count */ - if (bfa_cb_image_get_size(BFA_IOC_FWIMG_TYPE(ioc)) < + if (bfa_cb_image_get_size(bfa_ioc_asic_gen(ioc)) < BFA_IOC_FWIMG_MINSZ) return; @@ -165,22 +166,17 @@ bfa_ioc_ct_firmware_unlock(struct bfa_ioc *ioc) static void bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc) { - if (ioc->cna) { - writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt); - writel(__FW_INIT_HALT_P, ioc->ioc_regs.alt_ll_halt); - /* Wait for halt to take effect */ - readl(ioc->ioc_regs.ll_halt); - readl(ioc->ioc_regs.alt_ll_halt); - } else { - writel(~0U, ioc->ioc_regs.err_set); - readl(ioc->ioc_regs.err_set); - } + writel(__FW_INIT_HALT_P, ioc->ioc_regs.ll_halt); + writel(__FW_INIT_HALT_P, ioc->ioc_regs.alt_ll_halt); + /* Wait for halt to take effect */ + readl(ioc->ioc_regs.ll_halt); + readl(ioc->ioc_regs.alt_ll_halt); } /** * Host to LPU mailbox message addresses */ -static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } iocreg_fnreg[] = { +static struct { u32 hfn_mbox, lpu_mbox, hfn_pgn; } ct_fnreg[] = { { HOSTFN0_LPU_MBOX0_0, LPU_HOSTFN0_MBOX0_0, HOST_PAGE_NUM_FN0 }, { HOSTFN1_LPU_MBOX0_8, LPU_HOSTFN1_MBOX0_8, HOST_PAGE_NUM_FN1 }, { HOSTFN2_LPU_MBOX0_0, LPU_HOSTFN2_MBOX0_0, HOST_PAGE_NUM_FN2 }, @@ -215,9 +211,9 @@ bfa_ioc_ct_reg_init(struct bfa_ioc *ioc) rb = bfa_ioc_bar0(ioc); - ioc->ioc_regs.hfn_mbox = rb + iocreg_fnreg[pcifn].hfn_mbox; - ioc->ioc_regs.lpu_mbox = rb + iocreg_fnreg[pcifn].lpu_mbox; - ioc->ioc_regs.host_page_num_fn = rb + iocreg_fnreg[pcifn].hfn_pgn; + ioc->ioc_regs.hfn_mbox = rb + ct_fnreg[pcifn].hfn_mbox; + ioc->ioc_regs.lpu_mbox = rb + ct_fnreg[pcifn].lpu_mbox; + ioc->ioc_regs.host_page_num_fn = rb + ct_fnreg[pcifn].hfn_pgn; if (ioc->port_id == 0) { ioc->ioc_regs.heartbeat = rb + BFA_IOC0_HBEAT_REG; @@ -323,11 +319,9 @@ bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix) static void bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc) { - if (ioc->cna) { - bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); - writel(0, ioc->ioc_regs.ioc_usage_reg); - bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); - } + bfa_nw_ioc_sem_get(ioc->ioc_regs.ioc_usage_sem_reg); + writel(0, ioc->ioc_regs.ioc_usage_reg); + bfa_nw_ioc_sem_release(ioc->ioc_regs.ioc_usage_sem_reg); /* * Read the hw sem reg to make sure that it is locked @@ -436,9 +430,10 @@ bfa_ioc_ct_sync_complete(struct bfa_ioc *ioc) } static enum bfa_status -bfa_ioc_ct_pll_init(void __iomem *rb, bool fcmode) +bfa_ioc_ct_pll_init(void __iomem *rb, enum bfi_asic_mode asic_mode) { u32 pll_sclk, pll_fclk, r32; + bool fcmode = (asic_mode == BFI_ASIC_MODE_FC); pll_sclk = __APP_PLL_SCLK_LRESETN | __APP_PLL_SCLK_ENARST | __APP_PLL_SCLK_RSEL200500 | __APP_PLL_SCLK_P0_1(3U) | diff --git a/drivers/net/ethernet/brocade/bna/bfi.h b/drivers/net/ethernet/brocade/bna/bfi.h index 6a53183e411e..978e1bc12dc1 100644 --- a/drivers/net/ethernet/brocade/bna/bfi.h +++ b/drivers/net/ethernet/brocade/bna/bfi.h @@ -43,17 +43,21 @@ struct bfi_mhdr { u8 msg_id; /*!< msg opcode with in the class */ union { struct { - u8 rsvd; - u8 lpu_id; /*!< msg destination */ + u8 qid; + u8 fn_lpu; /*!< msg destination */ } h2i; u16 i2htok; /*!< token in msgs to host */ } mtag; }; -#define bfi_h2i_set(_mh, _mc, _op, _lpuid) do { \ +#define bfi_fn_lpu(__fn, __lpu) ((__fn) << 1 | (__lpu)) +#define bfi_mhdr_2_fn(_mh) ((_mh)->mtag.h2i.fn_lpu >> 1) +#define bfi_mhdr_2_qid(_mh) ((_mh)->mtag.h2i.qid) + +#define bfi_h2i_set(_mh, _mc, _op, _fn_lpu) do { \ (_mh).msg_class = (_mc); \ (_mh).msg_id = (_op); \ - (_mh).mtag.h2i.lpu_id = (_lpuid); \ + (_mh).mtag.h2i.fn_lpu = (_fn_lpu); \ } while (0) #define bfi_i2h_set(_mh, _mc, _op, _i2htok) do { \ @@ -149,6 +153,14 @@ struct bfi_mbmsg { }; /** + * Supported PCI function class codes (personality) + */ +enum bfi_pcifn_class { + BFI_PCIFN_CLASS_FC = 0x0c04, + BFI_PCIFN_CLASS_ETH = 0x0200, +}; + +/** * Message Classes */ enum bfi_mclass { @@ -203,6 +215,21 @@ enum bfi_mclass { *---------------------------------------------------------------------- */ +/** + * Different asic generations + */ +enum bfi_asic_gen { + BFI_ASIC_GEN_CB = 1, + BFI_ASIC_GEN_CT = 2, +}; + +enum bfi_asic_mode { + BFI_ASIC_MODE_FC = 1, /* FC upto 8G speed */ + BFI_ASIC_MODE_FC16 = 2, /* FC upto 16G speed */ + BFI_ASIC_MODE_ETH = 3, /* Ethernet ports */ + BFI_ASIC_MODE_COMBO = 4, /* FC 16G and Ethernet 10G port */ +}; + enum bfi_ioc_h2i_msgs { BFI_IOC_H2I_ENABLE_REQ = 1, BFI_IOC_H2I_DISABLE_REQ = 2, @@ -215,8 +242,7 @@ enum bfi_ioc_i2h_msgs { BFI_IOC_I2H_ENABLE_REPLY = BFA_I2HM(1), BFI_IOC_I2H_DISABLE_REPLY = BFA_I2HM(2), BFI_IOC_I2H_GETATTR_REPLY = BFA_I2HM(3), - BFI_IOC_I2H_READY_EVENT = BFA_I2HM(4), - BFI_IOC_I2H_HBEAT = BFA_I2HM(5), + BFI_IOC_I2H_HBEAT = BFA_I2HM(4), }; /** @@ -231,7 +257,8 @@ struct bfi_ioc_attr { u64 mfg_pwwn; /*!< Mfg port wwn */ u64 mfg_nwwn; /*!< Mfg node wwn */ mac_t mfg_mac; /*!< Mfg mac */ - u16 rsvd_a; + u8 port_mode; /* enum bfi_port_mode */ + u8 rsvd_a; u64 pwwn; u64 nwwn; mac_t mac; /*!< PBC or Mfg mac */ @@ -284,19 +311,36 @@ struct bfi_ioc_getattr_reply { #define BFI_IOC_MD5SUM_SZ 4 struct bfi_ioc_image_hdr { u32 signature; /*!< constant signature */ - u32 rsvd_a; + u8 asic_gen; /*!< asic generation */ + u8 asic_mode; + u8 port0_mode; /*!< device mode for port 0 */ + u8 port1_mode; /*!< device mode for port 1 */ u32 exec; /*!< exec vector */ - u32 param; /*!< parameters */ + u32 bootenv; /*!< firmware boot env */ u32 rsvd_b[4]; u32 md5sum[BFI_IOC_MD5SUM_SZ]; }; +#define BFI_FWBOOT_DEVMODE_OFF 4 +#define BFI_FWBOOT_TYPE_OFF 8 +#define BFI_FWBOOT_ENV_OFF 12 +#define BFI_FWBOOT_DEVMODE(__asic_gen, __asic_mode, __p0_mode, __p1_mode) \ + (((u32)(__asic_gen)) << 24 | \ + ((u32)(__asic_mode)) << 16 | \ + ((u32)(__p0_mode)) << 8 | \ + ((u32)(__p1_mode))) + enum bfi_fwboot_type { BFI_FWBOOT_TYPE_NORMAL = 0, BFI_FWBOOT_TYPE_FLASH = 1, BFI_FWBOOT_TYPE_MEMTEST = 2, }; +enum bfi_port_mode { + BFI_PORT_MODE_FC = 1, + BFI_PORT_MODE_ETH = 2, +}; + /** * BFI_IOC_I2H_READY_EVENT message */ @@ -362,8 +406,8 @@ enum { */ struct bfi_ioc_ctrl_req { struct bfi_mhdr mh; - u8 ioc_class; - u8 rsvd[3]; + u16 clscode; + u16 rsvd; u32 tv_sec; }; @@ -371,9 +415,11 @@ struct bfi_ioc_ctrl_req { * BFI_IOC_I2H_ENABLE_REPLY & BFI_IOC_I2H_DISABLE_REPLY messages */ struct bfi_ioc_ctrl_reply { - struct bfi_mhdr mh; /*!< Common msg header */ + struct bfi_mhdr mh; /*!< Common msg header */ u8 status; /*!< enable/disable status */ - u8 rsvd[3]; + u8 port_mode; /*!< enum bfa_mode */ + u8 cap_bm; /*!< capability bit mask */ + u8 rsvd; }; #define BFI_IOC_MSGSZ 8 @@ -393,7 +439,7 @@ union bfi_ioc_h2i_msg_u { */ union bfi_ioc_i2h_msg_u { struct bfi_mhdr mh; - struct bfi_ioc_rdy_event rdy_event; + struct bfi_ioc_ctrl_reply fw_event; u32 mboxmsg[BFI_IOC_MSGSZ]; }; diff --git a/drivers/net/ethernet/brocade/bna/bna.h b/drivers/net/ethernet/brocade/bna/bna.h index 21e9155d6e56..f9781a3d559b 100644 --- a/drivers/net/ethernet/brocade/bna/bna.h +++ b/drivers/net/ethernet/brocade/bna/bna.h @@ -40,7 +40,7 @@ do { \ (_qe)->cbarg = (_cbarg); \ } while (0) -#define bna_is_small_rxq(rcb) ((rcb)->id == 1) +#define bna_is_small_rxq(_id) ((_id) & 0x1) #define BNA_MAC_IS_EQUAL(_mac1, _mac2) \ (!memcmp((_mac1), (_mac2), sizeof(mac_t))) @@ -214,38 +214,59 @@ do { \ } \ } while (0) -#define call_rxf_stop_cbfn(rxf, status) \ +#define call_rxf_stop_cbfn(rxf) \ +do { \ if ((rxf)->stop_cbfn) { \ - (*(rxf)->stop_cbfn)((rxf)->stop_cbarg, (status)); \ + void (*cbfn)(struct bna_rx *); \ + struct bna_rx *cbarg; \ + cbfn = (rxf)->stop_cbfn; \ + cbarg = (rxf)->stop_cbarg; \ (rxf)->stop_cbfn = NULL; \ (rxf)->stop_cbarg = NULL; \ - } + cbfn(cbarg); \ + } \ +} while (0) -#define call_rxf_start_cbfn(rxf, status) \ +#define call_rxf_start_cbfn(rxf) \ +do { \ if ((rxf)->start_cbfn) { \ - (*(rxf)->start_cbfn)((rxf)->start_cbarg, (status)); \ + void (*cbfn)(struct bna_rx *); \ + struct bna_rx *cbarg; \ + cbfn = (rxf)->start_cbfn; \ + cbarg = (rxf)->start_cbarg; \ (rxf)->start_cbfn = NULL; \ (rxf)->start_cbarg = NULL; \ - } + cbfn(cbarg); \ + } \ +} while (0) -#define call_rxf_cam_fltr_cbfn(rxf, status) \ +#define call_rxf_cam_fltr_cbfn(rxf) \ +do { \ if ((rxf)->cam_fltr_cbfn) { \ - (*(rxf)->cam_fltr_cbfn)((rxf)->cam_fltr_cbarg, rxf->rx, \ - (status)); \ + void (*cbfn)(struct bnad *, struct bna_rx *); \ + struct bnad *cbarg; \ + cbfn = (rxf)->cam_fltr_cbfn; \ + cbarg = (rxf)->cam_fltr_cbarg; \ (rxf)->cam_fltr_cbfn = NULL; \ (rxf)->cam_fltr_cbarg = NULL; \ - } + cbfn(cbarg, rxf->rx); \ + } \ +} while (0) -#define call_rxf_pause_cbfn(rxf, status) \ +#define call_rxf_pause_cbfn(rxf) \ +do { \ if ((rxf)->oper_state_cbfn) { \ - (*(rxf)->oper_state_cbfn)((rxf)->oper_state_cbarg, rxf->rx,\ - (status)); \ - (rxf)->rxf_flags &= ~BNA_RXF_FL_OPERSTATE_CHANGED; \ + void (*cbfn)(struct bnad *, struct bna_rx *); \ + struct bnad *cbarg; \ + cbfn = (rxf)->oper_state_cbfn; \ + cbarg = (rxf)->oper_state_cbarg; \ (rxf)->oper_state_cbfn = NULL; \ (rxf)->oper_state_cbarg = NULL; \ - } + cbfn(cbarg, rxf->rx); \ + } \ +} while (0) -#define call_rxf_resume_cbfn(rxf, status) call_rxf_pause_cbfn(rxf, status) +#define call_rxf_resume_cbfn(rxf) call_rxf_pause_cbfn(rxf) #define is_xxx_enable(mode, bitmask, xxx) ((bitmask & xxx) && (mode & xxx)) @@ -331,6 +352,61 @@ do { \ } \ } while (0) +#define bna_tx_rid_mask(_bna) ((_bna)->tx_mod.rid_mask) + +#define bna_rx_rid_mask(_bna) ((_bna)->rx_mod.rid_mask) + +#define bna_tx_from_rid(_bna, _rid, _tx) \ +do { \ + struct bna_tx_mod *__tx_mod = &(_bna)->tx_mod; \ + struct bna_tx *__tx; \ + struct list_head *qe; \ + _tx = NULL; \ + list_for_each(qe, &__tx_mod->tx_active_q) { \ + __tx = (struct bna_tx *)qe; \ + if (__tx->rid == (_rid)) { \ + (_tx) = __tx; \ + break; \ + } \ + } \ +} while (0) + +#define bna_rx_from_rid(_bna, _rid, _rx) \ +do { \ + struct bna_rx_mod *__rx_mod = &(_bna)->rx_mod; \ + struct bna_rx *__rx; \ + struct list_head *qe; \ + _rx = NULL; \ + list_for_each(qe, &__rx_mod->rx_active_q) { \ + __rx = (struct bna_rx *)qe; \ + if (__rx->rid == (_rid)) { \ + (_rx) = __rx; \ + break; \ + } \ + } \ +} while (0) + +/** + * + * Inline functions + * + */ + +static inline struct bna_mac *bna_mac_find(struct list_head *q, u8 *addr) +{ + struct bna_mac *mac = NULL; + struct list_head *qe; + list_for_each(qe, q) { + if (BNA_MAC_IS_EQUAL(((struct bna_mac *)qe)->addr, addr)) { + mac = (struct bna_mac *)qe; + break; + } + } + return mac; +} + +#define bna_attr(_bna) (&(_bna)->ioceth.attr) + /** * * Function prototypes @@ -341,14 +417,22 @@ do { \ * BNA */ +/* FW response handlers */ +void bna_bfi_stats_clr_rsp(struct bna *bna, struct bfi_msgq_mhdr *msghdr); + /* APIs for BNAD */ void bna_res_req(struct bna_res_info *res_info); +void bna_mod_res_req(struct bna *bna, struct bna_res_info *res_info); void bna_init(struct bna *bna, struct bnad *bnad, struct bfa_pcidev *pcidev, struct bna_res_info *res_info); +void bna_mod_init(struct bna *bna, struct bna_res_info *res_info); void bna_uninit(struct bna *bna); +int bna_num_txq_set(struct bna *bna, int num_txq); +int bna_num_rxp_set(struct bna *bna, int num_rxp); void bna_stats_get(struct bna *bna); void bna_get_perm_mac(struct bna *bna, u8 *mac); +void bna_hw_stats_get(struct bna *bna); /* APIs for Rx */ int bna_rit_mod_can_satisfy(struct bna_rit_mod *rit_mod, int seg_size); @@ -360,6 +444,9 @@ void bna_ucam_mod_mac_put(struct bna_ucam_mod *ucam_mod, struct bna_mac *bna_mcam_mod_mac_get(struct bna_mcam_mod *mcam_mod); void bna_mcam_mod_mac_put(struct bna_mcam_mod *mcam_mod, struct bna_mac *mac); +struct bna_mcam_handle *bna_mcam_mod_handle_get(struct bna_mcam_mod *mod); +void bna_mcam_mod_handle_put(struct bna_mcam_mod *mcam_mod, + struct bna_mcam_handle *handle); struct bna_rit_segment * bna_rit_mod_seg_get(struct bna_rit_mod *rit_mod, int seg_size); void bna_rit_mod_seg_put(struct bna_rit_mod *rit_mod, @@ -409,6 +496,14 @@ void bna_port_cb_rx_stopped(struct bna_port *port, enum bna_cb_status status); /** + * ETHPORT + */ + +/* Callbacks for RX */ +void bna_ethport_cb_rx_started(struct bna_ethport *ethport); +void bna_ethport_cb_rx_stopped(struct bna_ethport *ethport); + +/** * IB */ @@ -420,6 +515,12 @@ void bna_ib_mod_uninit(struct bna_ib_mod *ib_mod); /** * TX MODULE AND TX */ +/* FW response handelrs */ +void bna_bfi_tx_enet_start_rsp(struct bna_tx *tx, + struct bfi_msgq_mhdr *msghdr); +void bna_bfi_tx_enet_stop_rsp(struct bna_tx *tx, + struct bfi_msgq_mhdr *msghdr); +void bna_bfi_bw_update_aen(struct bna_tx_mod *tx_mod); /* APIs for BNA */ void bna_tx_mod_init(struct bna_tx_mod *tx_mod, struct bna *bna, @@ -427,7 +528,7 @@ void bna_tx_mod_init(struct bna_tx_mod *tx_mod, struct bna *bna, void bna_tx_mod_uninit(struct bna_tx_mod *tx_mod); int bna_tx_state_get(struct bna_tx *tx); -/* APIs for PORT */ +/* APIs for ENET */ void bna_tx_mod_start(struct bna_tx_mod *tx_mod, enum bna_tx_type type); void bna_tx_mod_stop(struct bna_tx_mod *tx_mod, enum bna_tx_type type); void bna_tx_mod_fail(struct bna_tx_mod *tx_mod); @@ -444,8 +545,8 @@ struct bna_tx *bna_tx_create(struct bna *bna, struct bnad *bnad, void bna_tx_destroy(struct bna_tx *tx); void bna_tx_enable(struct bna_tx *tx); void bna_tx_disable(struct bna_tx *tx, enum bna_cleanup_type type, - void (*cbfn)(void *, struct bna_tx *, - enum bna_cb_status)); + void (*cbfn)(void *, struct bna_tx *)); +void bna_tx_cleanup_complete(struct bna_tx *tx); void bna_tx_coalescing_timeo_set(struct bna_tx *tx, int coalescing_timeo); /** @@ -473,6 +574,15 @@ void rxf_reset_packet_filter_promisc(struct bna_rxf *rxf); void rxf_reset_packet_filter_default(struct bna_rxf *rxf); void rxf_reset_packet_filter_allmulti(struct bna_rxf *rxf); +/* FW response handlers */ +void bna_bfi_rx_enet_start_rsp(struct bna_rx *rx, + struct bfi_msgq_mhdr *msghdr); +void bna_bfi_rx_enet_stop_rsp(struct bna_rx *rx, + struct bfi_msgq_mhdr *msghdr); +void bna_bfi_rxf_cfg_rsp(struct bna_rxf *rxf, struct bfi_msgq_mhdr *msghdr); +void bna_bfi_rxf_mcast_add_rsp(struct bna_rxf *rxf, + struct bfi_msgq_mhdr *msghdr); + /* APIs for BNA */ void bna_rx_mod_init(struct bna_rx_mod *rx_mod, struct bna *bna, struct bna_res_info *res_info); @@ -480,7 +590,7 @@ void bna_rx_mod_uninit(struct bna_rx_mod *rx_mod); int bna_rx_state_get(struct bna_rx *rx); int bna_rxf_state_get(struct bna_rxf *rxf); -/* APIs for PORT */ +/* APIs for ENET */ void bna_rx_mod_start(struct bna_rx_mod *rx_mod, enum bna_rx_type type); void bna_rx_mod_stop(struct bna_rx_mod *rx_mod, enum bna_rx_type type); void bna_rx_mod_fail(struct bna_rx_mod *rx_mod); @@ -495,42 +605,84 @@ struct bna_rx *bna_rx_create(struct bna *bna, struct bnad *bnad, void bna_rx_destroy(struct bna_rx *rx); void bna_rx_enable(struct bna_rx *rx); void bna_rx_disable(struct bna_rx *rx, enum bna_cleanup_type type, - void (*cbfn)(void *, struct bna_rx *, - enum bna_cb_status)); + void (*cbfn)(void *, struct bna_rx *)); +void bna_rx_cleanup_complete(struct bna_rx *rx); void bna_rx_coalescing_timeo_set(struct bna_rx *rx, int coalescing_timeo); void bna_rx_dim_reconfig(struct bna *bna, const u32 vector[][BNA_BIAS_T_MAX]); void bna_rx_dim_update(struct bna_ccb *ccb); enum bna_cb_status bna_rx_ucast_set(struct bna_rx *rx, u8 *ucmac, - void (*cbfn)(struct bnad *, struct bna_rx *, - enum bna_cb_status)); + void (*cbfn)(struct bnad *, struct bna_rx *)); +enum bna_cb_status +bna_rx_ucast_add(struct bna_rx *rx, u8* ucmac, + void (*cbfn)(struct bnad *, struct bna_rx *)); +enum bna_cb_status +bna_rx_ucast_del(struct bna_rx *rx, u8 *ucmac, + void (*cbfn)(struct bnad *, struct bna_rx *)); enum bna_cb_status bna_rx_mcast_add(struct bna_rx *rx, u8 *mcmac, - void (*cbfn)(struct bnad *, struct bna_rx *, - enum bna_cb_status)); + void (*cbfn)(struct bnad *, struct bna_rx *)); enum bna_cb_status bna_rx_mcast_listset(struct bna_rx *rx, int count, u8 *mcmac, - void (*cbfn)(struct bnad *, struct bna_rx *, - enum bna_cb_status)); + void (*cbfn)(struct bnad *, struct bna_rx *)); enum bna_cb_status bna_rx_mode_set(struct bna_rx *rx, enum bna_rxmode rxmode, enum bna_rxmode bitmask, - void (*cbfn)(struct bnad *, struct bna_rx *, - enum bna_cb_status)); + void (*cbfn)(struct bnad *, struct bna_rx *)); void bna_rx_vlan_add(struct bna_rx *rx, int vlan_id); void bna_rx_vlan_del(struct bna_rx *rx, int vlan_id); void bna_rx_vlanfilter_enable(struct bna_rx *rx); -void bna_rx_hds_enable(struct bna_rx *rx, struct bna_rxf_hds *hds_config, - void (*cbfn)(struct bnad *, struct bna_rx *, - enum bna_cb_status)); +void bna_rx_hds_enable(struct bna_rx *rx, struct bna_hds_config *hds_config, + void (*cbfn)(struct bnad *, struct bna_rx *)); void bna_rx_hds_disable(struct bna_rx *rx, - void (*cbfn)(struct bnad *, struct bna_rx *, - enum bna_cb_status)); + void (*cbfn)(struct bnad *, struct bna_rx *)); + +/** + * ENET + */ + +/* API for RX */ +int bna_enet_mtu_get(struct bna_enet *enet); + +/* Callbacks for TX, RX */ +void bna_enet_cb_tx_stopped(struct bna_enet *enet); +void bna_enet_cb_rx_stopped(struct bna_enet *enet); + +/* API for BNAD */ +void bna_enet_enable(struct bna_enet *enet); +void bna_enet_disable(struct bna_enet *enet, enum bna_cleanup_type type, + void (*cbfn)(void *)); +void bna_enet_pause_config(struct bna_enet *enet, + struct bna_pause_config *pause_config, + void (*cbfn)(struct bnad *)); +void bna_enet_mtu_set(struct bna_enet *enet, int mtu, + void (*cbfn)(struct bnad *)); +void bna_enet_perm_mac_get(struct bna_enet *enet, mac_t *mac); + +/** + * IOCETH + */ + +/* APIs for BNAD */ +void bna_ioceth_enable(struct bna_ioceth *ioceth); +void bna_ioceth_disable(struct bna_ioceth *ioceth, + enum bna_cleanup_type type); /** * BNAD */ +/* Callbacks for ENET */ +void bnad_cb_ethport_link_status(struct bnad *bnad, + enum bna_link_status status); + +/* Callbacks for IOCETH */ +void bnad_cb_ioceth_ready(struct bnad *bnad); +void bnad_cb_ioceth_failed(struct bnad *bnad); +void bnad_cb_ioceth_disabled(struct bnad *bnad); +void bnad_cb_mbox_intr_enable(struct bnad *bnad); +void bnad_cb_mbox_intr_disable(struct bnad *bnad); + /* Callbacks for BNA */ void bnad_cb_stats_get(struct bnad *bnad, enum bna_cb_status status, struct bna_stats *stats); diff --git a/drivers/net/ethernet/brocade/bna/bna_types.h b/drivers/net/ethernet/brocade/bna/bna_types.h index 2f89cb235248..655eb140bf94 100644 --- a/drivers/net/ethernet/brocade/bna/bna_types.h +++ b/drivers/net/ethernet/brocade/bna/bna_types.h @@ -19,8 +19,10 @@ #define __BNA_TYPES_H__ #include "cna.h" -#include "bna_hw.h" +#include "bna_hw_defs.h" #include "bfa_cee.h" +#include "bfi_enet.h" +#include "bfa_msgq.h" /** * @@ -28,6 +30,7 @@ * */ +struct bna_mcam_handle; struct bna_txq; struct bna_tx; struct bna_rxq; @@ -35,6 +38,7 @@ struct bna_cq; struct bna_rx; struct bna_rxf; struct bna_port; +struct bna_enet; struct bna; struct bnad; @@ -104,13 +108,26 @@ enum bna_res_req_type { BNA_RES_T_MAX }; +enum bna_mod_res_req_type { + BNA_MOD_RES_MEM_T_TX_ARRAY = 0, + BNA_MOD_RES_MEM_T_TXQ_ARRAY = 1, + BNA_MOD_RES_MEM_T_RX_ARRAY = 2, + BNA_MOD_RES_MEM_T_RXP_ARRAY = 3, + BNA_MOD_RES_MEM_T_RXQ_ARRAY = 4, + BNA_MOD_RES_MEM_T_UCMAC_ARRAY = 5, + BNA_MOD_RES_MEM_T_MCMAC_ARRAY = 6, + BNA_MOD_RES_MEM_T_MCHANDLE_ARRAY = 7, + BNA_MOD_RES_T_MAX +}; + enum bna_tx_res_req_type { BNA_TX_RES_MEM_T_TCB = 0, BNA_TX_RES_MEM_T_UNMAPQ = 1, BNA_TX_RES_MEM_T_QPT = 2, BNA_TX_RES_MEM_T_SWQPT = 3, BNA_TX_RES_MEM_T_PAGE = 4, - BNA_TX_RES_INTR_T_TXCMPL = 5, + BNA_TX_RES_MEM_T_IBIDX = 5, + BNA_TX_RES_INTR_T_TXCMPL = 6, BNA_TX_RES_T_MAX, }; @@ -127,8 +144,10 @@ enum bna_rx_mem_type { BNA_RX_RES_MEM_T_DSWQPT = 9, /* RX s/w QPT */ BNA_RX_RES_MEM_T_DPAGE = 10, /* RX s/w QPT */ BNA_RX_RES_MEM_T_HPAGE = 11, /* RX s/w QPT */ - BNA_RX_RES_T_INTR = 12, /* Rx interrupts */ - BNA_RX_RES_T_MAX = 13 + BNA_RX_RES_MEM_T_IBIDX = 12, + BNA_RX_RES_MEM_T_RIT = 13, + BNA_RX_RES_T_INTR = 14, /* Rx interrupts */ + BNA_RX_RES_T_MAX = 15 }; enum bna_mbox_state { @@ -142,14 +161,15 @@ enum bna_tx_type { }; enum bna_tx_flags { - BNA_TX_F_PORT_STARTED = 1, + BNA_TX_F_ENET_STARTED = 1, BNA_TX_F_ENABLED = 2, - BNA_TX_F_PRIO_LOCK = 4, + BNA_TX_F_PRIO_CHANGED = 4, + BNA_TX_F_BW_UPDATED = 8, }; enum bna_tx_mod_flags { - BNA_TX_MOD_F_PORT_STARTED = 1, - BNA_TX_MOD_F_PORT_LOOPBACK = 2, + BNA_TX_MOD_F_ENET_STARTED = 1, + BNA_TX_MOD_F_ENET_LOOPBACK = 2, }; enum bna_rx_type { @@ -165,16 +185,19 @@ enum bna_rxp_type { enum bna_rxmode { BNA_RXMODE_PROMISC = 1, - BNA_RXMODE_ALLMULTI = 2 + BNA_RXMODE_DEFAULT = 2, + BNA_RXMODE_ALLMULTI = 4 }; enum bna_rx_event { RX_E_START = 1, RX_E_STOP = 2, RX_E_FAIL = 3, - RX_E_RXF_STARTED = 4, - RX_E_RXF_STOPPED = 5, - RX_E_RXQ_STOPPED = 6, + RX_E_STARTED = 4, + RX_E_STOPPED = 5, + RX_E_RXF_STARTED = 6, + RX_E_RXF_STOPPED = 7, + RX_E_CLEANUP_DONE = 8, }; enum bna_rx_state { @@ -186,14 +209,13 @@ enum bna_rx_state { }; enum bna_rx_flags { - BNA_RX_F_ENABLE = 0x01, /* bnad enabled rxf */ - BNA_RX_F_PORT_ENABLED = 0x02, /* Port object is enabled */ - BNA_RX_F_PORT_FAILED = 0x04, /* Port in failed state */ + BNA_RX_F_ENET_STARTED = 1, + BNA_RX_F_ENABLED = 2, }; enum bna_rx_mod_flags { - BNA_RX_MOD_F_PORT_STARTED = 1, - BNA_RX_MOD_F_PORT_LOOPBACK = 2, + BNA_RX_MOD_F_ENET_STARTED = 1, + BNA_RX_MOD_F_ENET_LOOPBACK = 2, }; enum bna_rxf_oper_state { @@ -202,25 +224,17 @@ enum bna_rxf_oper_state { }; enum bna_rxf_flags { - BNA_RXF_FL_STOP_PENDING = 0x01, - BNA_RXF_FL_FAILED = 0x02, - BNA_RXF_FL_RSS_CONFIG_PENDING = 0x04, - BNA_RXF_FL_OPERSTATE_CHANGED = 0x08, - BNA_RXF_FL_RXF_ENABLED = 0x10, - BNA_RXF_FL_VLAN_CONFIG_PENDING = 0x20, + BNA_RXF_F_PAUSED = 1, }; enum bna_rxf_event { RXF_E_START = 1, RXF_E_STOP = 2, RXF_E_FAIL = 3, - RXF_E_CAM_FLTR_MOD = 4, - RXF_E_STARTED = 5, - RXF_E_STOPPED = 6, - RXF_E_CAM_FLTR_RESP = 7, - RXF_E_PAUSE = 8, - RXF_E_RESUME = 9, - RXF_E_STAT_CLEARED = 10, + RXF_E_CONFIG = 4, + RXF_E_PAUSE = 5, + RXF_E_RESUME = 6, + RXF_E_FW_RESP = 7, }; enum bna_rxf_state { @@ -241,6 +255,12 @@ enum bna_port_type { BNA_PORT_T_LOOPBACK_EXTERNAL = 2, }; +enum bna_enet_type { + BNA_ENET_T_REGULAR = 0, + BNA_ENET_T_LOOPBACK_INTERNAL = 1, + BNA_ENET_T_LOOPBACK_EXTERNAL = 2, +}; + enum bna_link_status { BNA_LINK_DOWN = 0, BNA_LINK_UP = 1, @@ -253,6 +273,12 @@ enum bna_llport_flags { BNA_LLPORT_F_RX_STARTED = 4 }; +enum bna_ethport_flags { + BNA_ETHPORT_F_ADMIN_UP = 1, + BNA_ETHPORT_F_PORT_ENABLED = 2, + BNA_ETHPORT_F_RX_STARTED = 4, +}; + enum bna_port_flags { BNA_PORT_F_DEVICE_READY = 1, BNA_PORT_F_ENABLED = 2, @@ -260,6 +286,23 @@ enum bna_port_flags { BNA_PORT_F_MTU_CHANGED = 8 }; +enum bna_enet_flags { + BNA_ENET_F_IOCETH_READY = 1, + BNA_ENET_F_ENABLED = 2, + BNA_ENET_F_PAUSE_CHANGED = 4, + BNA_ENET_F_MTU_CHANGED = 8 +}; + +enum bna_rss_flags { + BNA_RSS_F_RIT_PENDING = 1, + BNA_RSS_F_CFG_PENDING = 2, + BNA_RSS_F_STATUS_PENDING = 4, +}; + +enum bna_mod_flags { + BNA_MOD_F_INIT_DONE = 1, +}; + enum bna_pkt_rates { BNA_PKT_RATE_10K = 10000, BNA_PKT_RATE_20K = 20000, @@ -289,10 +332,17 @@ enum bna_dim_bias_types { BNA_BIAS_T_MAX = 2 }; +#define BNA_MAX_NAME_SIZE 64 +struct bna_ident { + int id; + char name[BNA_MAX_NAME_SIZE]; +}; + struct bna_mac { /* This should be the first one */ struct list_head qe; u8 addr[ETH_ALEN]; + struct bna_mcam_handle *handle; }; struct bna_mem_descr { @@ -338,23 +388,29 @@ struct bna_qpt { u32 page_size; }; +struct bna_attr { + int num_txq; + int num_rxp; + int num_ucmac; + int num_mcmac; + int max_rit_size; +}; + /** * - * Device + * IOCEth * */ -struct bna_device { +struct bna_ioceth { bfa_fsm_t fsm; struct bfa_ioc ioc; - enum bna_intr_type intr_type; - int vector; + struct bna_attr attr; + struct bfa_msgq_cmd_entry msgq_cmd; + struct bfi_enet_attr_req attr_req; - void (*ready_cbfn)(struct bnad *bnad, enum bna_cb_status status); - struct bnad *ready_cbarg; - - void (*stop_cbfn)(struct bnad *bnad, enum bna_cb_status status); + void (*stop_cbfn)(struct bnad *bnad); struct bnad *stop_cbarg; struct bna *bna; @@ -447,6 +503,68 @@ struct bna_port { /** * + * Enet + * + */ + +struct bna_enet { + bfa_fsm_t fsm; + enum bna_enet_flags flags; + + enum bna_enet_type type; + + struct bna_pause_config pause_config; + int mtu; + + /* Callback for bna_enet_disable(), enet_stop() */ + void (*stop_cbfn)(void *); + void *stop_cbarg; + + /* Callback for bna_enet_pause_config() */ + void (*pause_cbfn)(struct bnad *); + + /* Callback for bna_enet_mtu_set() */ + void (*mtu_cbfn)(struct bnad *); + + struct bfa_wc chld_stop_wc; + + struct bfa_msgq_cmd_entry msgq_cmd; + struct bfi_enet_set_pause_req pause_req; + + struct bna *bna; +}; + +/** + * + * Ethport + * + */ + +struct bna_ethport { + bfa_fsm_t fsm; + enum bna_ethport_flags flags; + + enum bna_link_status link_status; + + int rx_started_count; + + void (*stop_cbfn)(struct bna_enet *); + + void (*adminup_cbfn)(struct bnad *, enum bna_cb_status); + + void (*link_cbfn)(struct bnad *, enum bna_link_status); + + struct bfa_msgq_cmd_entry msgq_cmd; + union { + struct bfi_enet_enable_req admin_req; + struct bfi_enet_diag_lb_req lpbk_req; + } bfi_enet_cmd; + + struct bna *bna; +}; + +/** + * * Interrupt Block * */ @@ -478,55 +596,20 @@ struct bna_ib_dbell { u32 doorbell_ack; }; -/* Interrupt timer configuration */ -struct bna_ib_config { - u8 coalescing_timeo; /* Unit is 5usec. */ - - int interpkt_count; - int interpkt_timeo; - - enum ib_flags ctrl_flags; -}; - /* IB structure */ struct bna_ib { - /* This should be the first one */ - struct list_head qe; - - int ib_id; - - int ref_count; - int start_count; - struct bna_dma_addr ib_seg_host_addr; void *ib_seg_host_addr_kva; - u32 idx_mask; /* Size >= BNA_IBIDX_MAX_SEGSIZE */ - - struct bna_ibidx_seg *idx_seg; struct bna_ib_dbell door_bell; - struct bna_intr *intr; - - struct bna_ib_config ib_config; - - struct bna *bna; -}; - -/* IB module - keeps track of IBs and interrupts */ -struct bna_ib_mod { - struct bna_ib *ib; /* BFI_MAX_IB entries */ - struct bna_intr *intr; /* BFI_MAX_IB entries */ - struct bna_ibidx_seg *idx_seg; /* BNA_IBIDX_TOTAL_SEGS */ - - struct list_head ib_free_q; - - struct list_head ibidx_seg_pool[BFI_IBIDX_TOTAL_POOLS]; + enum bna_intr_type intr_type; + int intr_vector; - struct list_head intr_free_q; - struct list_head intr_active_q; + u8 coalescing_timeo; /* Unit is 5usec. */ - struct bna *bna; + int interpkt_count; + int interpkt_timeo; }; /** @@ -552,6 +635,7 @@ struct bna_tcb { /* Control path */ struct bna_txq *txq; struct bnad *bnad; + void *priv; /* BNAD's cookie */ enum bna_intr_type intr_type; int intr_vector; u8 priority; /* Current priority */ @@ -565,68 +649,66 @@ struct bna_txq { /* This should be the first one */ struct list_head qe; - int txq_id; - u8 priority; struct bna_qpt qpt; struct bna_tcb *tcb; - struct bna_ib *ib; - int ib_seg_offset; + struct bna_ib ib; struct bna_tx *tx; + int hw_id; + u64 tx_packets; u64 tx_bytes; }; -/* TxF structure (hardware Tx Function) */ -struct bna_txf { - int txf_id; - enum txf_flags ctrl_flags; - u16 vlan; -}; - /* Tx object */ struct bna_tx { /* This should be the first one */ struct list_head qe; + int rid; + int hw_id; bfa_fsm_t fsm; enum bna_tx_flags flags; enum bna_tx_type type; + int num_txq; struct list_head txq_q; - struct bna_txf txf; + u16 txf_vlan_id; /* Tx event handlers */ void (*tcb_setup_cbfn)(struct bnad *, struct bna_tcb *); void (*tcb_destroy_cbfn)(struct bnad *, struct bna_tcb *); - void (*tx_stall_cbfn)(struct bnad *, struct bna_tcb *); - void (*tx_resume_cbfn)(struct bnad *, struct bna_tcb *); - void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tcb *); + void (*tx_stall_cbfn)(struct bnad *, struct bna_tx *); + void (*tx_resume_cbfn)(struct bnad *, struct bna_tx *); + void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tx *); /* callback for bna_tx_disable(), bna_tx_stop() */ - void (*stop_cbfn)(void *arg, struct bna_tx *tx, - enum bna_cb_status status); + void (*stop_cbfn)(void *arg, struct bna_tx *tx); void *stop_cbarg; /* callback for bna_tx_prio_set() */ - void (*prio_change_cbfn)(struct bnad *bnad, struct bna_tx *tx, - enum bna_cb_status status); + void (*prio_change_cbfn)(struct bnad *bnad, struct bna_tx *tx); - struct bfa_wc txq_stop_wc; - - struct bna_mbox_qe mbox_qe; + struct bfa_msgq_cmd_entry msgq_cmd; + union { + struct bfi_enet_tx_cfg_req cfg_req; + struct bfi_enet_req req; + struct bfi_enet_tx_cfg_rsp cfg_rsp; + } bfi_enet_cmd; struct bna *bna; void *priv; /* bnad's cookie */ }; +/* Tx object configuration used during creation */ struct bna_tx_config { int num_txq; int txq_depth; + int coalescing_timeo; enum bna_tx_type tx_type; }; @@ -635,9 +717,9 @@ struct bna_tx_event_cbfn { void (*tcb_setup_cbfn)(struct bnad *, struct bna_tcb *); void (*tcb_destroy_cbfn)(struct bnad *, struct bna_tcb *); /* Mandatory */ - void (*tx_stall_cbfn)(struct bnad *, struct bna_tcb *); - void (*tx_resume_cbfn)(struct bnad *, struct bna_tcb *); - void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tcb *); + void (*tx_stall_cbfn)(struct bnad *, struct bna_tx *); + void (*tx_resume_cbfn)(struct bnad *, struct bna_tx *); + void (*tx_cleanup_cbfn)(struct bnad *, struct bna_tx *); }; /* Tx module - keeps track of free, active tx objects */ @@ -651,17 +733,19 @@ struct bna_tx_mod { struct list_head txq_free_q; /* callback for bna_tx_mod_stop() */ - void (*stop_cbfn)(struct bna_port *port, - enum bna_cb_status status); + void (*stop_cbfn)(struct bna_enet *enet); struct bfa_wc tx_stop_wc; enum bna_tx_mod_flags flags; - int priority; - int cee_link; + u8 prio_map; + int default_prio; + int iscsi_over_cee; + int iscsi_prio; + int prio_reconfigured; - u32 txf_bmap[2]; + u32 rid_mask; struct bna *bna; }; @@ -693,13 +777,6 @@ struct bna_rit_segment { struct bna_rit_entry *rit; }; -struct bna_rit_mod { - struct bna_rit_entry *rit; - struct bna_rit_segment *rit_segment; - - struct list_head rit_seg_pool[BFI_RIT_SEG_TOTAL_POOLS]; -}; - /** * * Rx object @@ -719,8 +796,9 @@ struct bna_rcb { int page_count; /* Control path */ struct bna_rxq *rxq; - struct bna_cq *cq; + struct bna_ccb *ccb; struct bnad *bnad; + void *priv; /* BNAD's cookie */ unsigned long flags; int id; }; @@ -728,7 +806,6 @@ struct bna_rcb { /* RxQ structure - QPT, configuration */ struct bna_rxq { struct list_head qe; - int rxq_id; int buffer_size; int q_depth; @@ -739,6 +816,8 @@ struct bna_rxq { struct bna_rxp *rxp; struct bna_rx *rx; + int hw_id; + u64 rx_packets; u64 rx_bytes; u64 rx_packets_with_error; @@ -784,6 +863,7 @@ struct bna_ccb { /* Control path */ struct bna_cq *cq; struct bnad *bnad; + void *priv; /* BNAD's cookie */ enum bna_intr_type intr_type; int intr_vector; u8 rx_coalescing_timeo; /* For NAPI */ @@ -793,46 +873,43 @@ struct bna_ccb { /* CQ QPT, configuration */ struct bna_cq { - int cq_id; - struct bna_qpt qpt; struct bna_ccb *ccb; - struct bna_ib *ib; - u8 ib_seg_offset; + struct bna_ib ib; struct bna_rx *rx; }; struct bna_rss_config { - enum rss_hash_type hash_type; + enum bfi_enet_rss_type hash_type; u8 hash_mask; - u32 toeplitz_hash_key[BFI_RSS_HASH_KEY_LEN]; + u32 toeplitz_hash_key[BFI_ENET_RSS_KEY_LEN]; }; struct bna_hds_config { - enum hds_header_type hdr_type; - int header_size; + enum bfi_enet_hds_type hdr_type; + int forced_offset; }; -/* This structure is used during RX creation */ +/* Rx object configuration used during creation */ struct bna_rx_config { enum bna_rx_type rx_type; int num_paths; enum bna_rxp_type rxp_type; int paused; int q_depth; + int coalescing_timeo; /* * Small/Large (or Header/Data) buffer size to be configured * for SLR and HDS queue type. Large buffer size comes from - * port->mtu. + * enet->mtu. */ int small_buff_size; enum bna_status rss_status; struct bna_rss_config rss_config; - enum bna_status hds_status; struct bna_hds_config hds_config; enum bna_status vlan_strip_status; @@ -851,51 +928,35 @@ struct bna_rxp { /* MSI-x vector number for configuring RSS */ int vector; - - struct bna_mbox_qe mbox_qe; -}; - -/* HDS configuration structure */ -struct bna_rxf_hds { - enum hds_header_type hdr_type; - int header_size; -}; - -/* RSS configuration structure */ -struct bna_rxf_rss { - enum rss_hash_type hash_type; - u8 hash_mask; - u32 toeplitz_hash_key[BFI_RSS_HASH_KEY_LEN]; + int hw_id; }; /* RxF structure (hardware Rx Function) */ struct bna_rxf { bfa_fsm_t fsm; - int rxf_id; - enum rxf_flags ctrl_flags; - u16 default_vlan_tag; - enum bna_rxf_oper_state rxf_oper_state; - enum bna_status hds_status; - struct bna_rxf_hds hds_cfg; - enum bna_status rss_status; - struct bna_rxf_rss rss_cfg; - struct bna_rit_segment *rit_segment; - struct bna_rx *rx; - u32 forced_offset; - struct bna_mbox_qe mbox_qe; - int mcast_rxq_id; + enum bna_rxf_flags flags; + + struct bfa_msgq_cmd_entry msgq_cmd; + union { + struct bfi_enet_enable_req req; + struct bfi_enet_rss_cfg_req rss_req; + struct bfi_enet_rit_req rit_req; + struct bfi_enet_rx_vlan_req vlan_req; + struct bfi_enet_mcast_add_req mcast_add_req; + struct bfi_enet_mcast_del_req mcast_del_req; + struct bfi_enet_ucast_req ucast_req; + } bfi_enet_cmd; /* callback for bna_rxf_start() */ - void (*start_cbfn) (struct bna_rx *rx, enum bna_cb_status status); + void (*start_cbfn) (struct bna_rx *rx); struct bna_rx *start_cbarg; /* callback for bna_rxf_stop() */ - void (*stop_cbfn) (struct bna_rx *rx, enum bna_cb_status status); + void (*stop_cbfn) (struct bna_rx *rx); struct bna_rx *stop_cbarg; - /* callback for bna_rxf_receive_enable() / bna_rxf_receive_disable() */ - void (*oper_state_cbfn) (struct bnad *bnad, struct bna_rx *rx, - enum bna_cb_status status); + /* callback for bna_rx_receive_pause() / bna_rx_receive_resume() */ + void (*oper_state_cbfn) (struct bnad *bnad, struct bna_rx *rx); struct bnad *oper_state_cbarg; /** @@ -905,25 +966,25 @@ struct bna_rxf { * bna_rxf_{ucast/mcast}_del(), * bna_rxf_mode_set() */ - void (*cam_fltr_cbfn)(struct bnad *bnad, struct bna_rx *rx, - enum bna_cb_status status); + void (*cam_fltr_cbfn)(struct bnad *bnad, struct bna_rx *rx); struct bnad *cam_fltr_cbarg; - enum bna_rxf_flags rxf_flags; - /* List of unicast addresses yet to be applied to h/w */ struct list_head ucast_pending_add_q; struct list_head ucast_pending_del_q; + struct bna_mac *ucast_pending_mac; int ucast_pending_set; /* ucast addresses applied to the h/w */ struct list_head ucast_active_q; - struct bna_mac *ucast_active_mac; + struct bna_mac ucast_active_mac; + int ucast_active_set; /* List of multicast addresses yet to be applied to h/w */ struct list_head mcast_pending_add_q; struct list_head mcast_pending_del_q; /* multicast addresses applied to the h/w */ struct list_head mcast_active_q; + struct list_head mcast_handle_q; /* Rx modes yet to be applied to h/w */ enum bna_rxmode rxmode_pending; @@ -931,41 +992,58 @@ struct bna_rxf { /* Rx modes applied to h/w */ enum bna_rxmode rxmode_active; + u8 vlan_pending_bitmask; enum bna_status vlan_filter_status; - u32 vlan_filter_table[(BFI_MAX_VLAN + 1) / 32]; + u32 vlan_filter_table[(BFI_ENET_VLAN_ID_MAX) / 32]; + bool vlan_strip_pending; + enum bna_status vlan_strip_status; + + enum bna_rss_flags rss_pending; + enum bna_status rss_status; + struct bna_rss_config rss_cfg; + u8 *rit; + int rit_size; + + struct bna_rx *rx; }; /* Rx object */ struct bna_rx { /* This should be the first one */ struct list_head qe; + int rid; + int hw_id; bfa_fsm_t fsm; enum bna_rx_type type; - /* list-head for RX path objects */ + int num_paths; struct list_head rxp_q; + struct bna_hds_config hds_cfg; + struct bna_rxf rxf; enum bna_rx_flags rx_flags; - struct bna_mbox_qe mbox_qe; - - struct bfa_wc rxq_stop_wc; + struct bfa_msgq_cmd_entry msgq_cmd; + union { + struct bfi_enet_rx_cfg_req cfg_req; + struct bfi_enet_req req; + struct bfi_enet_rx_cfg_rsp cfg_rsp; + } bfi_enet_cmd; /* Rx event handlers */ void (*rcb_setup_cbfn)(struct bnad *, struct bna_rcb *); void (*rcb_destroy_cbfn)(struct bnad *, struct bna_rcb *); void (*ccb_setup_cbfn)(struct bnad *, struct bna_ccb *); void (*ccb_destroy_cbfn)(struct bnad *, struct bna_ccb *); - void (*rx_cleanup_cbfn)(struct bnad *, struct bna_ccb *); - void (*rx_post_cbfn)(struct bnad *, struct bna_rcb *); + void (*rx_cleanup_cbfn)(struct bnad *, struct bna_rx *); + void (*rx_post_cbfn)(struct bnad *, struct bna_rx *); /* callback for bna_rx_disable(), bna_rx_stop() */ - void (*stop_cbfn)(void *arg, struct bna_rx *rx, - enum bna_cb_status status); + void (*stop_cbfn)(void *arg, struct bna_rx *rx); void *stop_cbarg; struct bna *bna; @@ -979,8 +1057,8 @@ struct bna_rx_event_cbfn { void (*ccb_setup_cbfn)(struct bnad *, struct bna_ccb *); void (*ccb_destroy_cbfn)(struct bnad *, struct bna_ccb *); /* Mandatory */ - void (*rx_cleanup_cbfn)(struct bnad *, struct bna_ccb *); - void (*rx_post_cbfn)(struct bnad *, struct bna_rcb *); + void (*rx_cleanup_cbfn)(struct bnad *, struct bna_rx *); + void (*rx_post_cbfn)(struct bnad *, struct bna_rx *); }; /* Rx module - keeps track of free, active rx objects */ @@ -1003,12 +1081,11 @@ struct bna_rx_mod { enum bna_rx_mod_flags flags; /* callback for bna_rx_mod_stop() */ - void (*stop_cbfn)(struct bna_port *port, - enum bna_cb_status status); + void (*stop_cbfn)(struct bna_enet *enet); struct bfa_wc rx_stop_wc; u32 dim_vector[BNA_LOAD_T_MAX][BNA_BIAS_T_MAX]; - u32 rxf_bmap[2]; + u32 rid_mask; }; /** @@ -1024,9 +1101,18 @@ struct bna_ucam_mod { struct bna *bna; }; +struct bna_mcam_handle { + /* This should be the first one */ + struct list_head qe; + int handle; + int refcnt; +}; + struct bna_mcam_mod { struct bna_mac *mcmac; /* BFI_MAX_MCMAC entries */ + struct bna_mcam_handle *mchandle; /* BFI_MAX_MCMAC entries */ struct list_head free_q; + struct list_head free_handle_q; struct bna *bna; }; @@ -1059,7 +1145,6 @@ struct bna_rx_stats { int num_active_mcast; int rxmode_active; int vlan_filter_status; - u32 vlan_filter_table[(BFI_MAX_VLAN + 1) / 32]; int rss_status; int hds_status; }; @@ -1072,15 +1157,22 @@ struct bna_sw_stats { int priority; int num_active_tx; int num_active_rx; - struct bna_tx_stats tx_stats[BFI_MAX_TXQ]; - struct bna_rx_stats rx_stats[BFI_MAX_RXQ]; }; struct bna_stats { - u32 txf_bmap[2]; - u32 rxf_bmap[2]; - struct bfi_ll_stats *hw_stats; - struct bna_sw_stats *sw_stats; + struct bna_dma_addr hw_stats_dma; + struct bfi_enet_stats *hw_stats_kva; + struct bfi_enet_stats hw_stats; +}; + +struct bna_stats_mod { + bool ioc_ready; + bool stats_get_busy; + bool stats_clr_busy; + struct bfa_msgq_cmd_entry stats_get_cmd; + struct bfa_msgq_cmd_entry stats_clr_cmd; + struct bfi_enet_stats_req stats_get; + struct bfi_enet_stats_req stats_clr; }; /** @@ -1090,38 +1182,32 @@ struct bna_stats { */ struct bna { + struct bna_ident ident; struct bfa_pcidev pcidev; - int port_num; + struct bna_reg regs; + struct bna_bit_defn bits; - struct bna_chip_regs regs; - - struct bna_dma_addr hw_stats_dma; struct bna_stats stats; - struct bna_device device; + struct bna_ioceth ioceth; struct bfa_cee cee; + struct bfa_msgq msgq; - struct bna_mbox_mod mbox_mod; - - struct bna_port port; + struct bna_ethport ethport; + struct bna_enet enet; + struct bna_stats_mod stats_mod; struct bna_tx_mod tx_mod; - struct bna_rx_mod rx_mod; - - struct bna_ib_mod ib_mod; - struct bna_ucam_mod ucam_mod; struct bna_mcam_mod mcam_mod; - struct bna_rit_mod rit_mod; - - int rxf_promisc_id; + enum bna_mod_flags mod_flags; - struct bna_mbox_qe mbox_qe; + int default_mode_rid; + int promisc_rid; struct bnad *bnad; }; - #endif /* __BNA_TYPES_H__ */ diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c index 8e35b2596f93..5ad07eab7bec 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.c +++ b/drivers/net/ethernet/brocade/bna/bnad.c @@ -441,11 +441,15 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget) struct bnad_skb_unmap *unmap_array; struct sk_buff *skb; u32 flags, unmap_cons; - u32 qid0 = ccb->rcb[0]->rxq->rxq_id; struct bna_pkt_rate *pkt_rt = &ccb->pkt_rate; + struct bnad_rx_ctrl *rx_ctrl = (struct bnad_rx_ctrl *)(ccb->ctrl); + + set_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags); - if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)) + if (!test_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags)) { + clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags); return 0; + } prefetch(bnad->netdev); BNA_CQ_QPGE_PTR_GET(ccb->producer_index, ccb->sw_qpt, cmpl, @@ -455,10 +459,10 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget) packets++; BNA_UPDATE_PKT_CNT(pkt_rt, ntohs(cmpl->length)); - if (qid0 == cmpl->rxq_id) - rcb = ccb->rcb[0]; - else + if (bna_is_small_rxq(cmpl->rxq_id)) rcb = ccb->rcb[1]; + else + rcb = ccb->rcb[0]; unmap_q = rcb->unmap_q; unmap_array = unmap_q->unmap_array; @@ -518,12 +522,9 @@ bnad_poll_cq(struct bnad *bnad, struct bna_ccb *ccb, int budget) if (flags & BNA_CQ_EF_VLAN) __vlan_hwaccel_put_tag(skb, ntohs(cmpl->vlan_tag)); - if (skb->ip_summed == CHECKSUM_UNNECESSARY) { - struct bnad_rx_ctrl *rx_ctrl; - - rx_ctrl = (struct bnad_rx_ctrl *) ccb->ctrl; + if (skb->ip_summed == CHECKSUM_UNNECESSARY) napi_gro_receive(&rx_ctrl->napi, skb); - } else { + else { netif_receive_skb(skb); } @@ -545,6 +546,8 @@ next: bna_ib_ack(ccb->i_dbell, 0); } + clear_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags); + return packets; } @@ -611,7 +614,7 @@ bnad_msix_mbox_handler(int irq, void *data) bna_intr_status_get(&bnad->bna, intr_status); - if (BNA_IS_MBOX_ERR_INTR(intr_status)) + if (BNA_IS_MBOX_ERR_INTR(&bnad->bna, intr_status)) bna_mbox_handler(&bnad->bna, intr_status); spin_unlock_irqrestore(&bnad->bna_lock, flags); @@ -628,6 +631,7 @@ bnad_isr(int irq, void *data) struct bnad *bnad = (struct bnad *)data; struct bnad_rx_info *rx_info; struct bnad_rx_ctrl *rx_ctrl; + struct bna_tcb *tcb = NULL; if (unlikely(test_bit(BNAD_RF_MBOX_IRQ_DISABLED, &bnad->run_flags))) return IRQ_NONE; @@ -639,7 +643,7 @@ bnad_isr(int irq, void *data) spin_lock_irqsave(&bnad->bna_lock, flags); - if (BNA_IS_MBOX_ERR_INTR(intr_status)) + if (BNA_IS_MBOX_ERR_INTR(&bnad->bna, intr_status)) bna_mbox_handler(&bnad->bna, intr_status); spin_unlock_irqrestore(&bnad->bna_lock, flags); @@ -650,8 +654,11 @@ bnad_isr(int irq, void *data) /* Process data interrupts */ /* Tx processing */ for (i = 0; i < bnad->num_tx; i++) { - for (j = 0; j < bnad->num_txq_per_tx; j++) - bnad_tx(bnad, bnad->tx_info[i].tcb[j]); + for (j = 0; j < bnad->num_txq_per_tx; j++) { + tcb = bnad->tx_info[i].tcb[j]; + if (tcb && test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)) + bnad_tx(bnad, bnad->tx_info[i].tcb[j]); + } } /* Rx processing */ for (i = 0; i < bnad->num_rx; i++) { @@ -706,43 +713,49 @@ bnad_set_netdev_perm_addr(struct bnad *bnad) /* Callbacks */ void -bnad_cb_device_enable_mbox_intr(struct bnad *bnad) +bnad_cb_mbox_intr_enable(struct bnad *bnad) { bnad_enable_mbox_irq(bnad); } void -bnad_cb_device_disable_mbox_intr(struct bnad *bnad) +bnad_cb_mbox_intr_disable(struct bnad *bnad) { bnad_disable_mbox_irq(bnad); } void -bnad_cb_device_enabled(struct bnad *bnad, enum bna_cb_status status) +bnad_cb_ioceth_ready(struct bnad *bnad) +{ + bnad->bnad_completions.ioc_comp_status = BNA_CB_SUCCESS; + complete(&bnad->bnad_completions.ioc_comp); +} + +void +bnad_cb_ioceth_failed(struct bnad *bnad) { + bnad->bnad_completions.ioc_comp_status = BNA_CB_FAIL; complete(&bnad->bnad_completions.ioc_comp); - bnad->bnad_completions.ioc_comp_status = status; } void -bnad_cb_device_disabled(struct bnad *bnad, enum bna_cb_status status) +bnad_cb_ioceth_disabled(struct bnad *bnad) { + bnad->bnad_completions.ioc_comp_status = BNA_CB_SUCCESS; complete(&bnad->bnad_completions.ioc_comp); - bnad->bnad_completions.ioc_comp_status = status; } static void -bnad_cb_port_disabled(void *arg, enum bna_cb_status status) +bnad_cb_enet_disabled(void *arg) { struct bnad *bnad = (struct bnad *)arg; - complete(&bnad->bnad_completions.port_comp); - netif_carrier_off(bnad->netdev); + complete(&bnad->bnad_completions.enet_comp); } void -bnad_cb_port_link_status(struct bnad *bnad, +bnad_cb_ethport_link_status(struct bnad *bnad, enum bna_link_status link_status) { bool link_up = 0; @@ -750,34 +763,60 @@ bnad_cb_port_link_status(struct bnad *bnad, link_up = (link_status == BNA_LINK_UP) || (link_status == BNA_CEE_UP); if (link_status == BNA_CEE_UP) { + if (!test_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags)) + BNAD_UPDATE_CTR(bnad, cee_toggle); set_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags); - BNAD_UPDATE_CTR(bnad, cee_up); - } else + } else { + if (test_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags)) + BNAD_UPDATE_CTR(bnad, cee_toggle); clear_bit(BNAD_RF_CEE_RUNNING, &bnad->run_flags); + } if (link_up) { if (!netif_carrier_ok(bnad->netdev)) { - struct bna_tcb *tcb = bnad->tx_info[0].tcb[0]; - if (!tcb) - return; - pr_warn("bna: %s link up\n", + uint tx_id, tcb_id; + printk(KERN_WARNING "bna: %s link up\n", bnad->netdev->name); netif_carrier_on(bnad->netdev); BNAD_UPDATE_CTR(bnad, link_toggle); - if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)) { - /* Force an immediate Transmit Schedule */ - pr_info("bna: %s TX_STARTED\n", - bnad->netdev->name); - netif_wake_queue(bnad->netdev); - BNAD_UPDATE_CTR(bnad, netif_queue_wakeup); - } else { - netif_stop_queue(bnad->netdev); - BNAD_UPDATE_CTR(bnad, netif_queue_stop); + for (tx_id = 0; tx_id < bnad->num_tx; tx_id++) { + for (tcb_id = 0; tcb_id < bnad->num_txq_per_tx; + tcb_id++) { + struct bna_tcb *tcb = + bnad->tx_info[tx_id].tcb[tcb_id]; + u32 txq_id; + if (!tcb) + continue; + + txq_id = tcb->id; + + if (test_bit(BNAD_TXQ_TX_STARTED, + &tcb->flags)) { + /* + * Force an immediate + * Transmit Schedule */ + printk(KERN_INFO "bna: %s %d " + "TXQ_STARTED\n", + bnad->netdev->name, + txq_id); + netif_wake_subqueue( + bnad->netdev, + txq_id); + BNAD_UPDATE_CTR(bnad, + netif_queue_wakeup); + } else { + netif_stop_subqueue( + bnad->netdev, + txq_id); + BNAD_UPDATE_CTR(bnad, + netif_queue_stop); + } + } } } } else { if (netif_carrier_ok(bnad->netdev)) { - pr_warn("bna: %s link down\n", + printk(KERN_WARNING "bna: %s link down\n", bnad->netdev->name); netif_carrier_off(bnad->netdev); BNAD_UPDATE_CTR(bnad, link_toggle); @@ -786,8 +825,7 @@ bnad_cb_port_link_status(struct bnad *bnad, } static void -bnad_cb_tx_disabled(void *arg, struct bna_tx *tx, - enum bna_cb_status status) +bnad_cb_tx_disabled(void *arg, struct bna_tx *tx) { struct bnad *bnad = (struct bnad *)arg; @@ -864,108 +902,166 @@ bnad_cb_ccb_destroy(struct bnad *bnad, struct bna_ccb *ccb) } static void -bnad_cb_tx_stall(struct bnad *bnad, struct bna_tcb *tcb) +bnad_cb_tx_stall(struct bnad *bnad, struct bna_tx *tx) { struct bnad_tx_info *tx_info = - (struct bnad_tx_info *)tcb->txq->tx->priv; - - if (tx_info != &bnad->tx_info[0]) - return; + (struct bnad_tx_info *)tx->priv; + struct bna_tcb *tcb; + u32 txq_id; + int i; - clear_bit(BNAD_TXQ_TX_STARTED, &tcb->flags); - netif_stop_queue(bnad->netdev); - pr_info("bna: %s TX_STOPPED\n", bnad->netdev->name); + for (i = 0; i < BNAD_MAX_TXQ_PER_TX; i++) { + tcb = tx_info->tcb[i]; + if (!tcb) + continue; + txq_id = tcb->id; + clear_bit(BNAD_TXQ_TX_STARTED, &tcb->flags); + netif_stop_subqueue(bnad->netdev, txq_id); + printk(KERN_INFO "bna: %s %d TXQ_STOPPED\n", + bnad->netdev->name, txq_id); + } } static void -bnad_cb_tx_resume(struct bnad *bnad, struct bna_tcb *tcb) +bnad_cb_tx_resume(struct bnad *bnad, struct bna_tx *tx) { - struct bnad_unmap_q *unmap_q = tcb->unmap_q; + struct bnad_tx_info *tx_info = (struct bnad_tx_info *)tx->priv; + struct bna_tcb *tcb; + struct bnad_unmap_q *unmap_q; + u32 txq_id; + int i; - if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)) - return; + for (i = 0; i < BNAD_MAX_TXQ_PER_TX; i++) { + tcb = tx_info->tcb[i]; + if (!tcb) + continue; + txq_id = tcb->id; - clear_bit(BNAD_RF_TX_SHUTDOWN_DELAYED, &bnad->run_flags); + unmap_q = tcb->unmap_q; - while (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) - cpu_relax(); + if (test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags)) + continue; - bnad_free_all_txbufs(bnad, tcb); + while (test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) + cpu_relax(); - unmap_q->producer_index = 0; - unmap_q->consumer_index = 0; + bnad_free_all_txbufs(bnad, tcb); - smp_mb__before_clear_bit(); - clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags); + unmap_q->producer_index = 0; + unmap_q->consumer_index = 0; + + smp_mb__before_clear_bit(); + clear_bit(BNAD_TXQ_FREE_SENT, &tcb->flags); + + set_bit(BNAD_TXQ_TX_STARTED, &tcb->flags); + + if (netif_carrier_ok(bnad->netdev)) { + printk(KERN_INFO "bna: %s %d TXQ_STARTED\n", + bnad->netdev->name, txq_id); + netif_wake_subqueue(bnad->netdev, txq_id); + BNAD_UPDATE_CTR(bnad, netif_queue_wakeup); + } + } /* - * Workaround for first device enable failure & we + * Workaround for first ioceth enable failure & we * get a 0 MAC address. We try to get the MAC address * again here. */ if (is_zero_ether_addr(&bnad->perm_addr.mac[0])) { - bna_port_mac_get(&bnad->bna.port, &bnad->perm_addr); + bna_enet_perm_mac_get(&bnad->bna.enet, &bnad->perm_addr); bnad_set_netdev_perm_addr(bnad); } - - set_bit(BNAD_TXQ_TX_STARTED, &tcb->flags); - - if (netif_carrier_ok(bnad->netdev)) { - pr_info("bna: %s TX_STARTED\n", bnad->netdev->name); - netif_wake_queue(bnad->netdev); - BNAD_UPDATE_CTR(bnad, netif_queue_wakeup); - } } static void -bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tcb *tcb) +bnad_cb_tx_cleanup(struct bnad *bnad, struct bna_tx *tx) { - /* Delay only once for the whole Tx Path Shutdown */ - if (!test_and_set_bit(BNAD_RF_TX_SHUTDOWN_DELAYED, &bnad->run_flags)) - mdelay(BNAD_TXRX_SYNC_MDELAY); + struct bnad_tx_info *tx_info = (struct bnad_tx_info *)tx->priv; + struct bna_tcb *tcb; + int i; + + for (i = 0; i < BNAD_MAX_TXQ_PER_TX; i++) { + tcb = tx_info->tcb[i]; + if (!tcb) + continue; + } + + mdelay(BNAD_TXRX_SYNC_MDELAY); + bna_tx_cleanup_complete(tx); } static void -bnad_cb_rx_cleanup(struct bnad *bnad, - struct bna_ccb *ccb) +bnad_cb_rx_cleanup(struct bnad *bnad, struct bna_rx *rx) { - clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags); + struct bnad_rx_info *rx_info = (struct bnad_rx_info *)rx->priv; + struct bna_ccb *ccb; + struct bnad_rx_ctrl *rx_ctrl; + int i; + + mdelay(BNAD_TXRX_SYNC_MDELAY); + + for (i = 0; i < BNAD_MAX_RXPS_PER_RX; i++) { + rx_ctrl = &rx_info->rx_ctrl[i]; + ccb = rx_ctrl->ccb; + if (!ccb) + continue; + + clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[0]->flags); + + if (ccb->rcb[1]) + clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[1]->flags); - if (ccb->rcb[1]) - clear_bit(BNAD_RXQ_STARTED, &ccb->rcb[1]->flags); + while (test_bit(BNAD_FP_IN_RX_PATH, &rx_ctrl->flags)) + cpu_relax(); + } - if (!test_and_set_bit(BNAD_RF_RX_SHUTDOWN_DELAYED, &bnad->run_flags)) - mdelay(BNAD_TXRX_SYNC_MDELAY); + bna_rx_cleanup_complete(rx); } static void -bnad_cb_rx_post(struct bnad *bnad, struct bna_rcb *rcb) +bnad_cb_rx_post(struct bnad *bnad, struct bna_rx *rx) { - struct bnad_unmap_q *unmap_q = rcb->unmap_q; - - clear_bit(BNAD_RF_RX_SHUTDOWN_DELAYED, &bnad->run_flags); - - if (rcb == rcb->cq->ccb->rcb[0]) - bnad_cq_cmpl_init(bnad, rcb->cq->ccb); + struct bnad_rx_info *rx_info = (struct bnad_rx_info *)rx->priv; + struct bna_ccb *ccb; + struct bna_rcb *rcb; + struct bnad_rx_ctrl *rx_ctrl; + struct bnad_unmap_q *unmap_q; + int i; + int j; - bnad_free_all_rxbufs(bnad, rcb); + for (i = 0; i < BNAD_MAX_RXPS_PER_RX; i++) { + rx_ctrl = &rx_info->rx_ctrl[i]; + ccb = rx_ctrl->ccb; + if (!ccb) + continue; - set_bit(BNAD_RXQ_STARTED, &rcb->flags); + bnad_cq_cmpl_init(bnad, ccb); - /* Now allocate & post buffers for this RCB */ - /* !!Allocation in callback context */ - if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) { - if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth) - >> BNAD_RXQ_REFILL_THRESHOLD_SHIFT) - bnad_alloc_n_post_rxbufs(bnad, rcb); - smp_mb__before_clear_bit(); - clear_bit(BNAD_RXQ_REFILL, &rcb->flags); + for (j = 0; j < BNAD_MAX_RXQ_PER_RXP; j++) { + rcb = ccb->rcb[j]; + if (!rcb) + continue; + bnad_free_all_rxbufs(bnad, rcb); + + set_bit(BNAD_RXQ_STARTED, &rcb->flags); + unmap_q = rcb->unmap_q; + + /* Now allocate & post buffers for this RCB */ + /* !!Allocation in callback context */ + if (!test_and_set_bit(BNAD_RXQ_REFILL, &rcb->flags)) { + if (BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth) + >> BNAD_RXQ_REFILL_THRESHOLD_SHIFT) + bnad_alloc_n_post_rxbufs(bnad, rcb); + smp_mb__before_clear_bit(); + clear_bit(BNAD_RXQ_REFILL, &rcb->flags); + } + } } } static void -bnad_cb_rx_disabled(void *arg, struct bna_rx *rx, - enum bna_cb_status status) +bnad_cb_rx_disabled(void *arg, struct bna_rx *rx) { struct bnad *bnad = (struct bnad *)arg; @@ -973,10 +1069,9 @@ bnad_cb_rx_disabled(void *arg, struct bna_rx *rx, } static void -bnad_cb_rx_mcast_add(struct bnad *bnad, struct bna_rx *rx, - enum bna_cb_status status) +bnad_cb_rx_mcast_add(struct bnad *bnad, struct bna_rx *rx) { - bnad->bnad_completions.mcast_comp_status = status; + bnad->bnad_completions.mcast_comp_status = BNA_CB_SUCCESS; complete(&bnad->bnad_completions.mcast_comp); } @@ -995,6 +1090,13 @@ bnad_cb_stats_get(struct bnad *bnad, enum bna_cb_status status, jiffies + msecs_to_jiffies(BNAD_STATS_TIMER_FREQ)); } +static void +bnad_cb_enet_mtu_set(struct bnad *bnad) +{ + bnad->bnad_completions.mtu_comp_status = BNA_CB_SUCCESS; + complete(&bnad->bnad_completions.mtu_comp); +} + /* Resource allocation, free functions */ static void @@ -1073,23 +1175,17 @@ err_return: /* Free IRQ for Mailbox */ static void -bnad_mbox_irq_free(struct bnad *bnad, - struct bna_intr_info *intr_info) +bnad_mbox_irq_free(struct bnad *bnad) { int irq; unsigned long flags; - if (intr_info->idl == NULL) - return; - spin_lock_irqsave(&bnad->bna_lock, flags); bnad_disable_mbox_irq(bnad); spin_unlock_irqrestore(&bnad->bna_lock, flags); irq = BNAD_GET_MBOX_IRQ(bnad); free_irq(irq, bnad); - - kfree(intr_info->idl); } /* @@ -1098,32 +1194,22 @@ bnad_mbox_irq_free(struct bnad *bnad, * from bna */ static int -bnad_mbox_irq_alloc(struct bnad *bnad, - struct bna_intr_info *intr_info) +bnad_mbox_irq_alloc(struct bnad *bnad) { int err = 0; unsigned long irq_flags, flags; u32 irq; irq_handler_t irq_handler; - /* Mbox should use only 1 vector */ - - intr_info->idl = kzalloc(sizeof(*(intr_info->idl)), GFP_KERNEL); - if (!intr_info->idl) - return -ENOMEM; - spin_lock_irqsave(&bnad->bna_lock, flags); if (bnad->cfg_flags & BNAD_CF_MSIX) { irq_handler = (irq_handler_t)bnad_msix_mbox_handler; irq = bnad->msix_table[BNAD_MAILBOX_MSIX_INDEX].vector; irq_flags = 0; - intr_info->intr_type = BNA_INTR_T_MSIX; - intr_info->idl[0].vector = BNAD_MAILBOX_MSIX_INDEX; } else { irq_handler = (irq_handler_t)bnad_isr; irq = bnad->pcidev->irq; irq_flags = IRQF_SHARED; - intr_info->intr_type = BNA_INTR_T_INTX; } spin_unlock_irqrestore(&bnad->bna_lock, flags); @@ -1140,11 +1226,6 @@ bnad_mbox_irq_alloc(struct bnad *bnad, err = request_irq(irq, irq_handler, irq_flags, bnad->mbox_irq_name, bnad); - if (err) { - kfree(intr_info->idl); - intr_info->idl = NULL; - } - return err; } @@ -1158,7 +1239,7 @@ bnad_txrx_irq_free(struct bnad *bnad, struct bna_intr_info *intr_info) /* Allocates Interrupt Descriptor List for MSIX/INT-X vectors */ static int bnad_txrx_irq_alloc(struct bnad *bnad, enum bnad_intr_source src, - uint txrx_id, struct bna_intr_info *intr_info) + u32 txrx_id, struct bna_intr_info *intr_info) { int i, vector_start = 0; u32 cfg_flags; @@ -1241,7 +1322,7 @@ bnad_tx_msix_unregister(struct bnad *bnad, struct bnad_tx_info *tx_info, */ static int bnad_tx_msix_register(struct bnad *bnad, struct bnad_tx_info *tx_info, - uint tx_id, int num_txqs) + u32 tx_id, int num_txqs) { int i; int err; @@ -1294,7 +1375,7 @@ bnad_rx_msix_unregister(struct bnad *bnad, struct bnad_rx_info *rx_info, */ static int bnad_rx_msix_register(struct bnad *bnad, struct bnad_rx_info *rx_info, - uint rx_id, int num_rxps) + u32 rx_id, int num_rxps) { int i; int err; @@ -1338,7 +1419,7 @@ bnad_tx_res_free(struct bnad *bnad, struct bna_res_info *res_info) /* Allocates memory and interrupt resources for Tx object */ static int bnad_tx_res_alloc(struct bnad *bnad, struct bna_res_info *res_info, - uint tx_id) + u32 tx_id) { int i, err = 0; @@ -1407,7 +1488,7 @@ bnad_ioc_timeout(unsigned long data) unsigned long flags; spin_lock_irqsave(&bnad->bna_lock, flags); - bfa_nw_ioc_timeout((void *) &bnad->bna.device.ioc); + bfa_nw_ioc_timeout((void *) &bnad->bna.ioceth.ioc); spin_unlock_irqrestore(&bnad->bna_lock, flags); } @@ -1418,7 +1499,7 @@ bnad_ioc_hb_check(unsigned long data) unsigned long flags; spin_lock_irqsave(&bnad->bna_lock, flags); - bfa_nw_ioc_hb_check((void *) &bnad->bna.device.ioc); + bfa_nw_ioc_hb_check((void *) &bnad->bna.ioceth.ioc); spin_unlock_irqrestore(&bnad->bna_lock, flags); } @@ -1429,7 +1510,7 @@ bnad_iocpf_timeout(unsigned long data) unsigned long flags; spin_lock_irqsave(&bnad->bna_lock, flags); - bfa_nw_iocpf_timeout((void *) &bnad->bna.device.ioc); + bfa_nw_iocpf_timeout((void *) &bnad->bna.ioceth.ioc); spin_unlock_irqrestore(&bnad->bna_lock, flags); } @@ -1440,7 +1521,7 @@ bnad_iocpf_sem_timeout(unsigned long data) unsigned long flags; spin_lock_irqsave(&bnad->bna_lock, flags); - bfa_nw_iocpf_sem_timeout((void *) &bnad->bna.device.ioc); + bfa_nw_iocpf_sem_timeout((void *) &bnad->bna.ioceth.ioc); spin_unlock_irqrestore(&bnad->bna_lock, flags); } @@ -1499,7 +1580,7 @@ bnad_stats_timeout(unsigned long data) return; spin_lock_irqsave(&bnad->bna_lock, flags); - bna_stats_get(&bnad->bna); + bna_hw_stats_get(&bnad->bna); spin_unlock_irqrestore(&bnad->bna_lock, flags); } @@ -1632,7 +1713,7 @@ bnad_napi_disable(struct bnad *bnad, u32 rx_id) /* Should be held with conf_lock held */ void -bnad_cleanup_tx(struct bnad *bnad, uint tx_id) +bnad_cleanup_tx(struct bnad *bnad, u32 tx_id) { struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id]; struct bna_res_info *res_info = &bnad->tx_res_info[tx_id].res_info[0]; @@ -1656,6 +1737,7 @@ bnad_cleanup_tx(struct bnad *bnad, uint tx_id) spin_unlock_irqrestore(&bnad->bna_lock, flags); tx_info->tx = NULL; + tx_info->tx_id = 0; if (0 == tx_id) tasklet_kill(&bnad->tx_free_tasklet); @@ -1665,7 +1747,7 @@ bnad_cleanup_tx(struct bnad *bnad, uint tx_id) /* Should be held with conf_lock held */ int -bnad_setup_tx(struct bnad *bnad, uint tx_id) +bnad_setup_tx(struct bnad *bnad, u32 tx_id) { int err; struct bnad_tx_info *tx_info = &bnad->tx_info[tx_id]; @@ -1677,10 +1759,13 @@ bnad_setup_tx(struct bnad *bnad, uint tx_id) struct bna_tx *tx; unsigned long flags; + tx_info->tx_id = tx_id; + /* Initialize the Tx object configuration */ tx_config->num_txq = bnad->num_txq_per_tx; tx_config->txq_depth = bnad->txq_depth; tx_config->tx_type = BNA_TX_T_REGULAR; + tx_config->coalescing_timeo = bnad->tx_coalescing_timeo; /* Initialize the tx event handlers */ tx_cbfn.tcb_setup_cbfn = bnad_cb_tcb_setup; @@ -1741,14 +1826,15 @@ bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config) { rx_config->rx_type = BNA_RX_T_REGULAR; rx_config->num_paths = bnad->num_rxp_per_rx; + rx_config->coalescing_timeo = bnad->rx_coalescing_timeo; if (bnad->num_rxp_per_rx > 1) { rx_config->rss_status = BNA_STATUS_T_ENABLED; rx_config->rss_config.hash_type = - (BFI_RSS_T_V4_TCP | - BFI_RSS_T_V6_TCP | - BFI_RSS_T_V4_IP | - BFI_RSS_T_V6_IP); + (BFI_ENET_RSS_IPV6 | + BFI_ENET_RSS_IPV6_TCP | + BFI_ENET_RSS_IPV4 | + BFI_ENET_RSS_IPV4_TCP); rx_config->rss_config.hash_mask = bnad->num_rxp_per_rx - 1; get_random_bytes(rx_config->rss_config.toeplitz_hash_key, @@ -1768,7 +1854,7 @@ bnad_init_rx_config(struct bnad *bnad, struct bna_rx_config *rx_config) /* Called with mutex_lock(&bnad->conf_mutex) held */ void -bnad_cleanup_rx(struct bnad *bnad, uint rx_id) +bnad_cleanup_rx(struct bnad *bnad, u32 rx_id) { struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id]; struct bna_rx_config *rx_config = &bnad->rx_config[rx_id]; @@ -1811,7 +1897,7 @@ bnad_cleanup_rx(struct bnad *bnad, uint rx_id) /* Called with mutex_lock(&bnad->conf_mutex) held */ int -bnad_setup_rx(struct bnad *bnad, uint rx_id) +bnad_setup_rx(struct bnad *bnad, u32 rx_id) { int err; struct bnad_rx_info *rx_info = &bnad->rx_info[rx_id]; @@ -1823,6 +1909,8 @@ bnad_setup_rx(struct bnad *bnad, uint rx_id) struct bna_rx *rx; unsigned long flags; + rx_info->rx_id = rx_id; + /* Initialize the Rx object configuration */ bnad_init_rx_config(bnad, rx_config); @@ -1978,7 +2066,7 @@ bnad_restore_vlans(struct bnad *bnad, u32 rx_id) u16 vid; unsigned long flags; - BUG_ON(!(VLAN_N_VID == (BFI_MAX_VLAN + 1))); + BUG_ON(!(VLAN_N_VID == BFI_ENET_VLAN_ID_MAX)); for_each_set_bit(vid, bnad->active_vlans, VLAN_N_VID) { spin_lock_irqsave(&bnad->bna_lock, flags); @@ -2031,11 +2119,11 @@ bnad_netdev_qstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats) void bnad_netdev_hwstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats) { - struct bfi_ll_stats_mac *mac_stats; - u64 bmap; + struct bfi_enet_stats_mac *mac_stats; + u32 bmap; int i; - mac_stats = &bnad->stats.bna_stats->hw_stats->mac_stats; + mac_stats = &bnad->stats.bna_stats->hw_stats.mac_stats; stats->rx_errors = mac_stats->rx_fcs_error + mac_stats->rx_alignment_error + mac_stats->rx_frame_length_error + mac_stats->rx_code_error + @@ -2054,13 +2142,12 @@ bnad_netdev_hwstats_fill(struct bnad *bnad, struct rtnl_link_stats64 *stats) stats->rx_crc_errors = mac_stats->rx_fcs_error; stats->rx_frame_errors = mac_stats->rx_alignment_error; /* recv'r fifo overrun */ - bmap = (u64)bnad->stats.bna_stats->rxf_bmap[0] | - ((u64)bnad->stats.bna_stats->rxf_bmap[1] << 32); - for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) { + bmap = bna_rx_rid_mask(&bnad->bna); + for (i = 0; bmap; i++) { if (bmap & 1) { stats->rx_fifo_errors += bnad->stats.bna_stats-> - hw_stats->rxf_stats[i].frame_drops; + hw_stats.rxf_stats[i].frame_drops; break; } bmap >>= 1; @@ -2158,7 +2245,7 @@ bnad_q_num_init(struct bnad *bnad) * Called with bnad->bna_lock held b'cos of cfg_flags access */ static void -bnad_q_num_adjust(struct bnad *bnad, int msix_vectors) +bnad_q_num_adjust(struct bnad *bnad, int msix_vectors, int temp) { bnad->num_txq_per_tx = 1; if ((msix_vectors >= (bnad->num_tx * bnad->num_txq_per_tx) + @@ -2171,76 +2258,72 @@ bnad_q_num_adjust(struct bnad *bnad, int msix_vectors) bnad->num_rxp_per_rx = 1; } -/* Enable / disable device */ -static void -bnad_device_disable(struct bnad *bnad) +/* Enable / disable ioceth */ +static int +bnad_ioceth_disable(struct bnad *bnad) { unsigned long flags; - - init_completion(&bnad->bnad_completions.ioc_comp); + int err = 0; spin_lock_irqsave(&bnad->bna_lock, flags); - bna_device_disable(&bnad->bna.device, BNA_HARD_CLEANUP); + init_completion(&bnad->bnad_completions.ioc_comp); + bna_ioceth_disable(&bnad->bna.ioceth, BNA_HARD_CLEANUP); spin_unlock_irqrestore(&bnad->bna_lock, flags); - wait_for_completion(&bnad->bnad_completions.ioc_comp); + wait_for_completion_timeout(&bnad->bnad_completions.ioc_comp, + msecs_to_jiffies(BNAD_IOCETH_TIMEOUT)); + + err = bnad->bnad_completions.ioc_comp_status; + return err; } static int -bnad_device_enable(struct bnad *bnad) +bnad_ioceth_enable(struct bnad *bnad) { int err = 0; unsigned long flags; - init_completion(&bnad->bnad_completions.ioc_comp); - spin_lock_irqsave(&bnad->bna_lock, flags); - bna_device_enable(&bnad->bna.device); + init_completion(&bnad->bnad_completions.ioc_comp); + bnad->bnad_completions.ioc_comp_status = BNA_CB_WAITING; + bna_ioceth_enable(&bnad->bna.ioceth); spin_unlock_irqrestore(&bnad->bna_lock, flags); - wait_for_completion(&bnad->bnad_completions.ioc_comp); + wait_for_completion_timeout(&bnad->bnad_completions.ioc_comp, + msecs_to_jiffies(BNAD_IOCETH_TIMEOUT)); - if (bnad->bnad_completions.ioc_comp_status) - err = bnad->bnad_completions.ioc_comp_status; + err = bnad->bnad_completions.ioc_comp_status; return err; } /* Free BNA resources */ static void -bnad_res_free(struct bnad *bnad) +bnad_res_free(struct bnad *bnad, struct bna_res_info *res_info, + u32 res_val_max) { int i; - struct bna_res_info *res_info = &bnad->res_info[0]; - for (i = 0; i < BNA_RES_T_MAX; i++) { - if (res_info[i].res_type == BNA_RES_T_MEM) - bnad_mem_free(bnad, &res_info[i].res_u.mem_info); - else - bnad_mbox_irq_free(bnad, &res_info[i].res_u.intr_info); - } + for (i = 0; i < res_val_max; i++) + bnad_mem_free(bnad, &res_info[i].res_u.mem_info); } /* Allocates memory and interrupt resources for BNA */ static int -bnad_res_alloc(struct bnad *bnad) +bnad_res_alloc(struct bnad *bnad, struct bna_res_info *res_info, + u32 res_val_max) { int i, err; - struct bna_res_info *res_info = &bnad->res_info[0]; - for (i = 0; i < BNA_RES_T_MAX; i++) { - if (res_info[i].res_type == BNA_RES_T_MEM) - err = bnad_mem_alloc(bnad, &res_info[i].res_u.mem_info); - else - err = bnad_mbox_irq_alloc(bnad, - &res_info[i].res_u.intr_info); + for (i = 0; i < res_val_max; i++) { + err = bnad_mem_alloc(bnad, &res_info[i].res_u.mem_info); if (err) goto err_return; } return 0; err_return: - bnad_res_free(bnad); + bnad_res_free(bnad, res_info, res_val_max); return err; } @@ -2276,7 +2359,7 @@ bnad_enable_msix(struct bnad *bnad) spin_lock_irqsave(&bnad->bna_lock, flags); /* ret = #of vectors that we got */ - bnad_q_num_adjust(bnad, ret); + bnad_q_num_adjust(bnad, ret, 0); spin_unlock_irqrestore(&bnad->bna_lock, flags); bnad->msix_num = (bnad->num_tx * bnad->num_txq_per_tx) @@ -2284,6 +2367,9 @@ bnad_enable_msix(struct bnad *bnad) * bnad->num_rxp_per_rx) + BNAD_MAILBOX_MSIX_VECTORS; + if (bnad->msix_num > ret) + goto intx_mode; + /* Try once more with adjusted numbers */ /* If this fails, fall back to INTx */ ret = pci_enable_msix(bnad->pcidev, bnad->msix_table, @@ -2293,6 +2379,9 @@ bnad_enable_msix(struct bnad *bnad) } else if (ret < 0) goto intx_mode; + + pci_intx(bnad->pcidev, 0); + return; intx_mode: @@ -2351,12 +2440,12 @@ bnad_open(struct net_device *netdev) pause_config.tx_pause = 0; pause_config.rx_pause = 0; - mtu = ETH_HLEN + bnad->netdev->mtu + ETH_FCS_LEN; + mtu = ETH_HLEN + VLAN_HLEN + bnad->netdev->mtu + ETH_FCS_LEN; spin_lock_irqsave(&bnad->bna_lock, flags); - bna_port_mtu_set(&bnad->bna.port, mtu, NULL); - bna_port_pause_config(&bnad->bna.port, &pause_config, NULL); - bna_port_enable(&bnad->bna.port); + bna_enet_mtu_set(&bnad->bna.enet, mtu, NULL); + bna_enet_pause_config(&bnad->bna.enet, &pause_config, NULL); + bna_enet_enable(&bnad->bna.enet); spin_unlock_irqrestore(&bnad->bna_lock, flags); /* Enable broadcast */ @@ -2396,14 +2485,14 @@ bnad_stop(struct net_device *netdev) /* Stop the stats timer */ bnad_stats_timer_stop(bnad); - init_completion(&bnad->bnad_completions.port_comp); + init_completion(&bnad->bnad_completions.enet_comp); spin_lock_irqsave(&bnad->bna_lock, flags); - bna_port_disable(&bnad->bna.port, BNA_HARD_CLEANUP, - bnad_cb_port_disabled); + bna_enet_disable(&bnad->bna.enet, BNA_HARD_CLEANUP, + bnad_cb_enet_disabled); spin_unlock_irqrestore(&bnad->bna_lock, flags); - wait_for_completion(&bnad->bnad_completions.port_comp); + wait_for_completion(&bnad->bnad_completions.enet_comp); bnad_cleanup_tx(bnad, 0); bnad_cleanup_rx(bnad, 0); @@ -2425,19 +2514,18 @@ static netdev_tx_t bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev) { struct bnad *bnad = netdev_priv(netdev); + u32 txq_id = 0; + struct bna_tcb *tcb = bnad->tx_info[0].tcb[txq_id]; u16 txq_prod, vlan_tag = 0; u32 unmap_prod, wis, wis_used, wi_range; u32 vectors, vect_id, i, acked; - u32 tx_id; int err; - struct bnad_tx_info *tx_info; - struct bna_tcb *tcb; - struct bnad_unmap_q *unmap_q; + struct bnad_unmap_q *unmap_q = tcb->unmap_q; dma_addr_t dma_addr; struct bna_txq_entry *txqent; - bna_txq_wi_ctrl_flag_t flags; + u16 flags; if (unlikely (skb->len <= ETH_HLEN || skb->len > BFI_TX_MAX_DATA_PER_PKT)) { @@ -2445,15 +2533,9 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev) return NETDEV_TX_OK; } - tx_id = 0; - - tx_info = &bnad->tx_info[tx_id]; - tcb = tx_info->tcb[tx_id]; - unmap_q = tcb->unmap_q; - /* * Takes care of the Tx that is scheduled between clearing the flag - * and the netif_stop_queue() call. + * and the netif_stop_all_queue() call. */ if (unlikely(!test_bit(BNAD_TXQ_TX_STARTED, &tcb->flags))) { dev_kfree_skb(skb); @@ -2467,9 +2549,8 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev) } wis = BNA_TXQ_WI_NEEDED(vectors); /* 4 vectors per work item */ acked = 0; - if (unlikely - (wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) || - vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) { + if (unlikely(wis > BNA_QE_FREE_CNT(tcb, tcb->q_depth) || + vectors > BNA_QE_FREE_CNT(unmap_q, unmap_q->q_depth))) { if ((u16) (*tcb->hw_consumer_index) != tcb->consumer_index && !test_and_set_bit(BNAD_TXQ_FREE_SENT, &tcb->flags)) { @@ -2602,7 +2683,7 @@ bnad_start_xmit(struct sk_buff *skb, struct net_device *netdev) for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; - u32 size = frag->size; + u16 size = frag->size; if (++vect_id == BFI_TX_MAX_VECTORS_PER_WI) { vect_id = 0; @@ -2760,11 +2841,25 @@ bnad_set_mac_address(struct net_device *netdev, void *mac_addr) } static int -bnad_change_mtu(struct net_device *netdev, int new_mtu) +bnad_mtu_set(struct bnad *bnad, int mtu) { - int mtu, err = 0; unsigned long flags; + init_completion(&bnad->bnad_completions.mtu_comp); + + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_enet_mtu_set(&bnad->bna.enet, mtu, bnad_cb_enet_mtu_set); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + wait_for_completion(&bnad->bnad_completions.mtu_comp); + + return bnad->bnad_completions.mtu_comp_status; +} + +static int +bnad_change_mtu(struct net_device *netdev, int new_mtu) +{ + int err, mtu = netdev->mtu; struct bnad *bnad = netdev_priv(netdev); if (new_mtu + ETH_HLEN < ETH_ZLEN || new_mtu > BNAD_JUMBO_MTU) @@ -2774,11 +2869,10 @@ bnad_change_mtu(struct net_device *netdev, int new_mtu) netdev->mtu = new_mtu; - mtu = ETH_HLEN + new_mtu + ETH_FCS_LEN; - - spin_lock_irqsave(&bnad->bna_lock, flags); - bna_port_mtu_set(&bnad->bna.port, mtu, NULL); - spin_unlock_irqrestore(&bnad->bna_lock, flags); + mtu = ETH_HLEN + VLAN_HLEN + new_mtu + ETH_FCS_LEN; + err = bnad_mtu_set(bnad, mtu); + if (err) + err = -EBUSY; mutex_unlock(&bnad->conf_mutex); return err; @@ -2968,7 +3062,7 @@ bnad_uninit(struct bnad *bnad) /* * Initialize locks - a) Per device mutes used for serializing configuration + a) Per ioceth mutes used for serializing configuration changes from OS interface b) spin lock used to protect bna state machine */ @@ -3058,12 +3152,15 @@ bnad_pci_probe(struct pci_dev *pdev, */ netdev = alloc_etherdev(sizeof(struct bnad)); if (!netdev) { - dev_err(&pdev->dev, "alloc_etherdev failed\n"); + dev_err(&pdev->dev, "netdev allocation failed\n"); err = -ENOMEM; return err; } bnad = netdev_priv(netdev); + bnad_lock_init(bnad); + + mutex_lock(&bnad->conf_mutex); /* * PCI initialization * Output : using_dac = 1 for 64 bit DMA @@ -3073,7 +3170,6 @@ bnad_pci_probe(struct pci_dev *pdev, if (err) goto free_netdev; - bnad_lock_init(bnad); /* * Initialize bnad structure * Setup relation between pci_dev & netdev @@ -3082,21 +3178,22 @@ bnad_pci_probe(struct pci_dev *pdev, err = bnad_init(bnad, pdev, netdev); if (err) goto pci_uninit; + /* Initialize netdev structure, set up ethtool ops */ bnad_netdev_init(bnad, using_dac); /* Set link to down state */ netif_carrier_off(netdev); - bnad_enable_msix(bnad); - /* Get resource requirement form bna */ + spin_lock_irqsave(&bnad->bna_lock, flags); bna_res_req(&bnad->res_info[0]); + spin_unlock_irqrestore(&bnad->bna_lock, flags); /* Allocate resources from bna */ - err = bnad_res_alloc(bnad); + err = bnad_res_alloc(bnad, &bnad->res_info[0], BNA_RES_T_MAX); if (err) - goto free_netdev; + goto drv_uninit; bna = &bnad->bna; @@ -3106,69 +3203,102 @@ bnad_pci_probe(struct pci_dev *pdev, pcidev_info.device_id = bnad->pcidev->device; pcidev_info.pci_bar_kva = bnad->bar0; - mutex_lock(&bnad->conf_mutex); - spin_lock_irqsave(&bnad->bna_lock, flags); bna_init(bna, bnad, &pcidev_info, &bnad->res_info[0]); spin_unlock_irqrestore(&bnad->bna_lock, flags); bnad->stats.bna_stats = &bna->stats; + bnad_enable_msix(bnad); + err = bnad_mbox_irq_alloc(bnad); + if (err) + goto res_free; + + /* Set up timers */ - setup_timer(&bnad->bna.device.ioc.ioc_timer, bnad_ioc_timeout, + setup_timer(&bnad->bna.ioceth.ioc.ioc_timer, bnad_ioc_timeout, ((unsigned long)bnad)); - setup_timer(&bnad->bna.device.ioc.hb_timer, bnad_ioc_hb_check, + setup_timer(&bnad->bna.ioceth.ioc.hb_timer, bnad_ioc_hb_check, ((unsigned long)bnad)); - setup_timer(&bnad->bna.device.ioc.iocpf_timer, bnad_iocpf_timeout, + setup_timer(&bnad->bna.ioceth.ioc.iocpf_timer, bnad_iocpf_timeout, ((unsigned long)bnad)); - setup_timer(&bnad->bna.device.ioc.sem_timer, bnad_iocpf_sem_timeout, + setup_timer(&bnad->bna.ioceth.ioc.sem_timer, bnad_iocpf_sem_timeout, ((unsigned long)bnad)); /* Now start the timer before calling IOC */ - mod_timer(&bnad->bna.device.ioc.iocpf_timer, + mod_timer(&bnad->bna.ioceth.ioc.iocpf_timer, jiffies + msecs_to_jiffies(BNA_IOC_TIMER_FREQ)); /* * Start the chip - * Don't care even if err != 0, bna state machine will - * deal with it + * If the call back comes with error, we bail out. + * This is a catastrophic error. */ - err = bnad_device_enable(bnad); + err = bnad_ioceth_enable(bnad); + if (err) { + pr_err("BNA: Initialization failed err=%d\n", + err); + goto probe_success; + } + + spin_lock_irqsave(&bnad->bna_lock, flags); + if (bna_num_txq_set(bna, BNAD_NUM_TXQ + 1) || + bna_num_rxp_set(bna, BNAD_NUM_RXP + 1)) { + bnad_q_num_adjust(bnad, bna_attr(bna)->num_txq - 1, + bna_attr(bna)->num_rxp - 1); + if (bna_num_txq_set(bna, BNAD_NUM_TXQ + 1) || + bna_num_rxp_set(bna, BNAD_NUM_RXP + 1)) + err = -EIO; + } + bna_mod_res_req(&bnad->bna, &bnad->mod_res_info[0]); + spin_unlock_irqrestore(&bnad->bna_lock, flags); + + err = bnad_res_alloc(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX); + if (err) + goto disable_ioceth; + + spin_lock_irqsave(&bnad->bna_lock, flags); + bna_mod_init(&bnad->bna, &bnad->mod_res_info[0]); + spin_unlock_irqrestore(&bnad->bna_lock, flags); /* Get the burnt-in mac */ spin_lock_irqsave(&bnad->bna_lock, flags); - bna_port_mac_get(&bna->port, &bnad->perm_addr); + bna_enet_perm_mac_get(&bna->enet, &bnad->perm_addr); bnad_set_netdev_perm_addr(bnad); spin_unlock_irqrestore(&bnad->bna_lock, flags); - mutex_unlock(&bnad->conf_mutex); - /* Finally, reguister with net_device layer */ err = register_netdev(netdev); if (err) { pr_err("BNA : Registering with netdev failed\n"); - goto disable_device; + goto probe_uninit; } + set_bit(BNAD_RF_NETDEV_REGISTERED, &bnad->run_flags); +probe_success: + mutex_unlock(&bnad->conf_mutex); return 0; -disable_device: - mutex_lock(&bnad->conf_mutex); - bnad_device_disable(bnad); - del_timer_sync(&bnad->bna.device.ioc.ioc_timer); - del_timer_sync(&bnad->bna.device.ioc.sem_timer); - del_timer_sync(&bnad->bna.device.ioc.hb_timer); +probe_uninit: + bnad_res_free(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX); +disable_ioceth: + bnad_ioceth_disable(bnad); + del_timer_sync(&bnad->bna.ioceth.ioc.ioc_timer); + del_timer_sync(&bnad->bna.ioceth.ioc.sem_timer); + del_timer_sync(&bnad->bna.ioceth.ioc.hb_timer); spin_lock_irqsave(&bnad->bna_lock, flags); bna_uninit(bna); spin_unlock_irqrestore(&bnad->bna_lock, flags); - mutex_unlock(&bnad->conf_mutex); - - bnad_res_free(bnad); + bnad_mbox_irq_free(bnad); bnad_disable_msix(bnad); +res_free: + bnad_res_free(bnad, &bnad->res_info[0], BNA_RES_T_MAX); +drv_uninit: + bnad_uninit(bnad); pci_uninit: bnad_pci_uninit(pdev); + mutex_unlock(&bnad->conf_mutex); bnad_lock_uninit(bnad); - bnad_uninit(bnad); free_netdev: free_netdev(netdev); return err; @@ -3189,21 +3319,24 @@ bnad_pci_remove(struct pci_dev *pdev) bnad = netdev_priv(netdev); bna = &bnad->bna; - unregister_netdev(netdev); + if (test_and_clear_bit(BNAD_RF_NETDEV_REGISTERED, &bnad->run_flags)) + unregister_netdev(netdev); mutex_lock(&bnad->conf_mutex); - bnad_device_disable(bnad); - del_timer_sync(&bnad->bna.device.ioc.ioc_timer); - del_timer_sync(&bnad->bna.device.ioc.sem_timer); - del_timer_sync(&bnad->bna.device.ioc.hb_timer); + bnad_ioceth_disable(bnad); + del_timer_sync(&bnad->bna.ioceth.ioc.ioc_timer); + del_timer_sync(&bnad->bna.ioceth.ioc.sem_timer); + del_timer_sync(&bnad->bna.ioceth.ioc.hb_timer); spin_lock_irqsave(&bnad->bna_lock, flags); bna_uninit(bna); spin_unlock_irqrestore(&bnad->bna_lock, flags); - mutex_unlock(&bnad->conf_mutex); - bnad_res_free(bnad); + bnad_res_free(bnad, &bnad->mod_res_info[0], BNA_MOD_RES_T_MAX); + bnad_res_free(bnad, &bnad->res_info[0], BNA_RES_T_MAX); + bnad_mbox_irq_free(bnad); bnad_disable_msix(bnad); bnad_pci_uninit(pdev); + mutex_unlock(&bnad->conf_mutex); bnad_lock_uninit(bnad); bnad_uninit(bnad); free_netdev(netdev); diff --git a/drivers/net/ethernet/brocade/bna/bnad.h b/drivers/net/ethernet/brocade/bna/bnad.h index 458eb30371b5..a538cf4383b1 100644 --- a/drivers/net/ethernet/brocade/bna/bnad.h +++ b/drivers/net/ethernet/brocade/bna/bnad.h @@ -44,6 +44,7 @@ #define BNAD_MAX_RXS 1 #define BNAD_MAX_RXPS_PER_RX 16 +#define BNAD_MAX_RXQ_PER_RXP 2 /* * Control structure pointed to ccb->ctrl, which @@ -76,6 +77,8 @@ struct bnad_rx_ctrl { #define BNAD_STATS_TIMER_FREQ 1000 /* in msecs */ #define BNAD_DIM_TIMER_FREQ 1000 /* in msecs */ +#define BNAD_IOCETH_TIMEOUT 10000 + #define BNAD_MAX_Q_DEPTH 0x10000 #define BNAD_MIN_Q_DEPTH 0x200 @@ -93,6 +96,10 @@ struct bnad_rx_ctrl { #define BNAD_RXQ_REFILL 0 #define BNAD_RXQ_STARTED 1 +/* Resource limits */ +#define BNAD_NUM_TXQ (bnad->num_tx * bnad->num_txq_per_tx) +#define BNAD_NUM_RXP (bnad->num_rx * bnad->num_rxp_per_rx) + /* * DATA STRUCTURES */ @@ -115,7 +122,8 @@ struct bnad_completion { struct completion tx_comp; struct completion rx_comp; struct completion stats_comp; - struct completion port_comp; + struct completion enet_comp; + struct completion mtu_comp; u8 ioc_comp_status; u8 ucast_comp_status; @@ -124,6 +132,7 @@ struct bnad_completion { u8 rx_comp_status; u8 stats_comp_status; u8 port_comp_status; + u8 mtu_comp_status; }; /* Tx Rx Control Stats */ @@ -145,6 +154,7 @@ struct bnad_drv_stats { u64 netif_rx_dropped; u64 link_toggle; + u64 cee_toggle; u64 cee_up; u64 rxp_info_alloc_failed; @@ -174,12 +184,14 @@ struct bnad_rx_res_info { struct bnad_tx_info { struct bna_tx *tx; /* 1:1 between tx_info & tx */ struct bna_tcb *tcb[BNAD_MAX_TXQ_PER_TX]; + u32 tx_id; } ____cacheline_aligned; struct bnad_rx_info { struct bna_rx *rx; /* 1:1 between rx_info & rx */ struct bnad_rx_ctrl rx_ctrl[BNAD_MAX_RXPS_PER_RX]; + u32 rx_id; } ____cacheline_aligned; /* Unmap queues for Tx / Rx cleanup */ @@ -205,13 +217,18 @@ struct bnad_unmap_q { /* Defines for run_flags bit-mask */ /* Set, tested & cleared using xxx_bit() functions */ /* Values indicated bit positions */ -#define BNAD_RF_CEE_RUNNING 1 +#define BNAD_RF_CEE_RUNNING 0 +#define BNAD_RF_MTU_SET 1 #define BNAD_RF_MBOX_IRQ_DISABLED 2 -#define BNAD_RF_RX_STARTED 3 +#define BNAD_RF_NETDEV_REGISTERED 3 #define BNAD_RF_DIM_TIMER_RUNNING 4 #define BNAD_RF_STATS_TIMER_RUNNING 5 -#define BNAD_RF_TX_SHUTDOWN_DELAYED 6 -#define BNAD_RF_RX_SHUTDOWN_DELAYED 7 +#define BNAD_RF_TX_PRIO_SET 6 + + +/* Define for Fast Path flags */ +/* Defined as bit positions */ +#define BNAD_FP_IN_RX_PATH 0 struct bnad { struct net_device *netdev; @@ -265,6 +282,7 @@ struct bnad { /* Control path resources, memory & irq */ struct bna_res_info res_info[BNA_RES_T_MAX]; + struct bna_res_info mod_res_info[BNA_MOD_RES_T_MAX]; struct bnad_tx_res_info tx_res_info[BNAD_MAX_TXS]; struct bnad_rx_res_info rx_res_info[BNAD_MAX_RXS]; @@ -302,10 +320,10 @@ extern void bnad_set_ethtool_ops(struct net_device *netdev); extern void bnad_tx_coalescing_timeo_set(struct bnad *bnad); extern void bnad_rx_coalescing_timeo_set(struct bnad *bnad); -extern int bnad_setup_rx(struct bnad *bnad, uint rx_id); -extern int bnad_setup_tx(struct bnad *bnad, uint tx_id); -extern void bnad_cleanup_tx(struct bnad *bnad, uint tx_id); -extern void bnad_cleanup_rx(struct bnad *bnad, uint rx_id); +extern int bnad_setup_rx(struct bnad *bnad, u32 rx_id); +extern int bnad_setup_tx(struct bnad *bnad, u32 tx_id); +extern void bnad_cleanup_tx(struct bnad *bnad, u32 tx_id); +extern void bnad_cleanup_rx(struct bnad *bnad, u32 rx_id); /* Timer start/stop protos */ extern void bnad_dim_timer_start(struct bnad *bnad); diff --git a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c index 49174f87f4d1..1c19dcea83c2 100644 --- a/drivers/net/ethernet/brocade/bna/bnad_ethtool.c +++ b/drivers/net/ethernet/brocade/bna/bnad_ethtool.c @@ -29,14 +29,14 @@ #define BNAD_NUM_TXF_COUNTERS 12 #define BNAD_NUM_RXF_COUNTERS 10 -#define BNAD_NUM_CQ_COUNTERS 3 +#define BNAD_NUM_CQ_COUNTERS (3 + 5) #define BNAD_NUM_RXQ_COUNTERS 6 #define BNAD_NUM_TXQ_COUNTERS 5 #define BNAD_ETHTOOL_STATS_NUM \ (sizeof(struct rtnl_link_stats64) / sizeof(u64) + \ sizeof(struct bnad_drv_stats) / sizeof(u64) + \ - offsetof(struct bfi_ll_stats, rxf_stats[0]) / sizeof(u64)) + offsetof(struct bfi_enet_stats, rxf_stats[0]) / sizeof(u64)) static char *bnad_net_stats_strings[BNAD_ETHTOOL_STATS_NUM] = { "rx_packets", @@ -277,7 +277,7 @@ bnad_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) ioc_attr = kzalloc(sizeof(*ioc_attr), GFP_KERNEL); if (ioc_attr) { spin_lock_irqsave(&bnad->bna_lock, flags); - bfa_nw_ioc_get_attr(&bnad->bna.device.ioc, ioc_attr); + bfa_nw_ioc_get_attr(&bnad->bna.ioceth.ioc, ioc_attr); spin_unlock_irqrestore(&bnad->bna_lock, flags); strncpy(drvinfo->fw_version, ioc_attr->adapter_attr.fw_ver, @@ -462,8 +462,8 @@ bnad_get_pauseparam(struct net_device *netdev, struct bnad *bnad = netdev_priv(netdev); pauseparam->autoneg = 0; - pauseparam->rx_pause = bnad->bna.port.pause_config.rx_pause; - pauseparam->tx_pause = bnad->bna.port.pause_config.tx_pause; + pauseparam->rx_pause = bnad->bna.enet.pause_config.rx_pause; + pauseparam->tx_pause = bnad->bna.enet.pause_config.tx_pause; } static int @@ -478,12 +478,12 @@ bnad_set_pauseparam(struct net_device *netdev, return -EINVAL; mutex_lock(&bnad->conf_mutex); - if (pauseparam->rx_pause != bnad->bna.port.pause_config.rx_pause || - pauseparam->tx_pause != bnad->bna.port.pause_config.tx_pause) { + if (pauseparam->rx_pause != bnad->bna.enet.pause_config.rx_pause || + pauseparam->tx_pause != bnad->bna.enet.pause_config.tx_pause) { pause_config.rx_pause = pauseparam->rx_pause; pause_config.tx_pause = pauseparam->tx_pause; spin_lock_irqsave(&bnad->bna_lock, flags); - bna_port_pause_config(&bnad->bna.port, &pause_config, NULL); + bna_enet_pause_config(&bnad->bna.enet, &pause_config, NULL); spin_unlock_irqrestore(&bnad->bna_lock, flags); } mutex_unlock(&bnad->conf_mutex); @@ -495,7 +495,7 @@ bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string) { struct bnad *bnad = netdev_priv(netdev); int i, j, q_num; - u64 bmap; + u32 bmap; mutex_lock(&bnad->conf_mutex); @@ -508,9 +508,8 @@ bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string) ETH_GSTRING_LEN); string += ETH_GSTRING_LEN; } - bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] | - ((u64)bnad->bna.tx_mod.txf_bmap[1] << 32); - for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) { + bmap = bna_tx_rid_mask(&bnad->bna); + for (i = 0; bmap; i++) { if (bmap & 1) { sprintf(string, "txf%d_ucast_octets", i); string += ETH_GSTRING_LEN; @@ -540,9 +539,8 @@ bnad_get_strings(struct net_device *netdev, u32 stringset, u8 * string) bmap >>= 1; } - bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] | - ((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32); - for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) { + bmap = bna_rx_rid_mask(&bnad->bna); + for (i = 0; bmap; i++) { if (bmap & 1) { sprintf(string, "rxf%d_ucast_octets", i); string += ETH_GSTRING_LEN; @@ -663,18 +661,16 @@ bnad_get_stats_count_locked(struct net_device *netdev) { struct bnad *bnad = netdev_priv(netdev); int i, j, count, rxf_active_num = 0, txf_active_num = 0; - u64 bmap; + u32 bmap; - bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] | - ((u64)bnad->bna.tx_mod.txf_bmap[1] << 32); - for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) { + bmap = bna_tx_rid_mask(&bnad->bna); + for (i = 0; bmap; i++) { if (bmap & 1) txf_active_num++; bmap >>= 1; } - bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] | - ((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32); - for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) { + bmap = bna_rx_rid_mask(&bnad->bna); + for (i = 0; bmap; i++) { if (bmap & 1) rxf_active_num++; bmap >>= 1; @@ -787,7 +783,7 @@ bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, unsigned long flags; struct rtnl_link_stats64 *net_stats64; u64 *stats64; - u64 bmap; + u32 bmap; mutex_lock(&bnad->conf_mutex); if (bnad_get_stats_count_locked(netdev) != stats->n_stats) { @@ -818,20 +814,20 @@ bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, buf[bi++] = stats64[i]; /* Fill hardware stats excluding the rxf/txf into ethtool bufs */ - stats64 = (u64 *) bnad->stats.bna_stats->hw_stats; + stats64 = (u64 *) &bnad->stats.bna_stats->hw_stats; for (i = 0; - i < offsetof(struct bfi_ll_stats, rxf_stats[0]) / sizeof(u64); + i < offsetof(struct bfi_enet_stats, rxf_stats[0]) / + sizeof(u64); i++) buf[bi++] = stats64[i]; /* Fill txf stats into ethtool buffers */ - bmap = (u64)bnad->bna.tx_mod.txf_bmap[0] | - ((u64)bnad->bna.tx_mod.txf_bmap[1] << 32); - for (i = 0; bmap && (i < BFI_LL_TXF_ID_MAX); i++) { + bmap = bna_tx_rid_mask(&bnad->bna); + for (i = 0; bmap; i++) { if (bmap & 1) { stats64 = (u64 *)&bnad->stats.bna_stats-> - hw_stats->txf_stats[i]; - for (j = 0; j < sizeof(struct bfi_ll_stats_txf) / + hw_stats.txf_stats[i]; + for (j = 0; j < sizeof(struct bfi_enet_stats_txf) / sizeof(u64); j++) buf[bi++] = stats64[j]; } @@ -839,13 +835,12 @@ bnad_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, } /* Fill rxf stats into ethtool buffers */ - bmap = (u64)bnad->bna.rx_mod.rxf_bmap[0] | - ((u64)bnad->bna.rx_mod.rxf_bmap[1] << 32); - for (i = 0; bmap && (i < BFI_LL_RXF_ID_MAX); i++) { + bmap = bna_rx_rid_mask(&bnad->bna); + for (i = 0; bmap; i++) { if (bmap & 1) { stats64 = (u64 *)&bnad->stats.bna_stats-> - hw_stats->rxf_stats[i]; - for (j = 0; j < sizeof(struct bfi_ll_stats_rxf) / + hw_stats.rxf_stats[i]; + for (j = 0; j < sizeof(struct bfi_enet_stats_rxf) / sizeof(u64); j++) buf[bi++] = stats64[j]; } diff --git a/drivers/net/ethernet/brocade/bna/cna.h b/drivers/net/ethernet/brocade/bna/cna.h index a679e038747b..50fce15feacc 100644 --- a/drivers/net/ethernet/brocade/bna/cna.h +++ b/drivers/net/ethernet/brocade/bna/cna.h @@ -40,7 +40,7 @@ extern char bfa_version[]; -#define CNA_FW_FILE_CT "ctfw_cna.bin" +#define CNA_FW_FILE_CT "ctfw.bin" #define FC_SYMNAME_MAX 256 /*!< max name server symbolic name size */ #pragma pack(1) @@ -77,4 +77,33 @@ typedef struct mac { u8 mac[MAC_ADDRLEN]; } mac_t; } \ } +/* + * bfa_q_deq_tail - dequeue an element from tail of the queue + */ +#define bfa_q_deq_tail(_q, _qe) { \ + if (!list_empty(_q)) { \ + *((struct list_head **) (_qe)) = bfa_q_prev(_q); \ + bfa_q_next(bfa_q_prev(*((struct list_head **) _qe))) = \ + (struct list_head *) (_q); \ + bfa_q_prev(_q) = bfa_q_prev(*(struct list_head **) _qe);\ + bfa_q_qe_init(*((struct list_head **) _qe)); \ + } else { \ + *((struct list_head **) (_qe)) = (struct list_head *) NULL; \ + } \ +} + +/* + * bfa_add_tail_head - enqueue an element at the head of queue + */ +#define bfa_q_enq_head(_q, _qe) { \ + if (!(bfa_q_next(_qe) == NULL) && (bfa_q_prev(_qe) == NULL)) \ + pr_err("Assertion failure: %s:%d: %d", \ + __FILE__, __LINE__, \ + (bfa_q_next(_qe) == NULL) && (bfa_q_prev(_qe) == NULL));\ + bfa_q_next(_qe) = bfa_q_next(_q); \ + bfa_q_prev(_qe) = (struct list_head *) (_q); \ + bfa_q_prev(bfa_q_next(_q)) = (struct list_head *) (_qe); \ + bfa_q_next(_q) = (struct list_head *) (_qe); \ +} + #endif /* __CNA_H__ */ |