Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | // SPDX-License-Identifier: GPL-2.0-only /* * Linux network driver for QLogic BR-series Converged Network Adapter. */ /* * Copyright (c) 2005-2014 Brocade Communications Systems, Inc. * Copyright (c) 2014-2015 QLogic Corporation * All rights reserved * www.qlogic.com */ #include "bfa_cee.h" #include "bfi_cna.h" #include "bfa_ioc.h" static void bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg *lldp_cfg); static void bfa_cee_format_cee_cfg(void *buffer); static void bfa_cee_format_cee_cfg(void *buffer) { struct bfa_cee_attr *cee_cfg = buffer; bfa_cee_format_lldp_cfg(&cee_cfg->lldp_remote); } static void bfa_cee_stats_swap(struct bfa_cee_stats *stats) { u32 *buffer = (u32 *)stats; int i; for (i = 0; i < (sizeof(struct bfa_cee_stats) / sizeof(u32)); i++) { buffer[i] = ntohl(buffer[i]); } } static void bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg *lldp_cfg) { lldp_cfg->time_to_live = ntohs(lldp_cfg->time_to_live); lldp_cfg->enabled_system_cap = ntohs(lldp_cfg->enabled_system_cap); } /** * bfa_cee_attr_meminfo - Returns the size of the DMA memory needed by CEE attributes */ static u32 bfa_cee_attr_meminfo(void) { return roundup(sizeof(struct bfa_cee_attr), BFA_DMA_ALIGN_SZ); } /** * bfa_cee_stats_meminfo - Returns the size of the DMA memory needed by CEE stats */ static u32 bfa_cee_stats_meminfo(void) { return roundup(sizeof(struct bfa_cee_stats), BFA_DMA_ALIGN_SZ); } /** * bfa_cee_get_attr_isr - CEE ISR for get-attributes responses from f/w * * @cee: Pointer to the CEE module * @status: Return status from the f/w */ static void bfa_cee_get_attr_isr(struct bfa_cee *cee, enum bfa_status status) { cee->get_attr_status = status; if (status == BFA_STATUS_OK) { memcpy(cee->attr, cee->attr_dma.kva, sizeof(struct bfa_cee_attr)); bfa_cee_format_cee_cfg(cee->attr); } cee->get_attr_pending = false; if (cee->cbfn.get_attr_cbfn) cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status); } /** * bfa_cee_get_attr_isr - CEE ISR for get-stats responses from f/w * * @cee: Pointer to the CEE module * @status: Return status from the f/w */ static void bfa_cee_get_stats_isr(struct bfa_cee *cee, enum bfa_status status) { cee->get_stats_status = status; if (status == BFA_STATUS_OK) { memcpy(cee->stats, cee->stats_dma.kva, sizeof(struct bfa_cee_stats)); bfa_cee_stats_swap(cee->stats); } cee->get_stats_pending = false; if (cee->cbfn.get_stats_cbfn) cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status); } /** * bfa_cee_get_attr_isr() * * @brief CEE ISR for reset-stats responses from f/w * * @param[in] cee - Pointer to the CEE module * status - Return status from the f/w * * @return void */ static void bfa_cee_reset_stats_isr(struct bfa_cee *cee, enum bfa_status status) { cee->reset_stats_status = status; cee->reset_stats_pending = false; if (cee->cbfn.reset_stats_cbfn) cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status); } /** * bfa_nw_cee_meminfo - Returns the size of the DMA memory needed by CEE module */ u32 bfa_nw_cee_meminfo(void) { return bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo(); } /** * bfa_nw_cee_mem_claim - Initialized CEE DMA Memory * * @cee: CEE module pointer * @dma_kva: Kernel Virtual Address of CEE DMA Memory * @dma_pa: Physical Address of CEE DMA Memory */ void bfa_nw_cee_mem_claim(struct bfa_cee *cee, u8 *dma_kva, u64 dma_pa) { cee->attr_dma.kva = dma_kva; cee->attr_dma.pa = dma_pa; cee->stats_dma.kva = dma_kva + bfa_cee_attr_meminfo(); cee->stats_dma.pa = dma_pa + bfa_cee_attr_meminfo(); cee->attr = (struct bfa_cee_attr *) dma_kva; cee->stats = (struct bfa_cee_stats *) (dma_kva + bfa_cee_attr_meminfo()); } /** * bfa_cee_get_attr - Send the request to the f/w to fetch CEE attributes. * * @cee: Pointer to the CEE module data structure. * * Return: status */ enum bfa_status bfa_nw_cee_get_attr(struct bfa_cee *cee, struct bfa_cee_attr *attr, bfa_cee_get_attr_cbfn_t cbfn, void *cbarg) { struct bfi_cee_get_req *cmd; BUG_ON(!((cee != NULL) && (cee->ioc != NULL))); if (!bfa_nw_ioc_is_operational(cee->ioc)) return BFA_STATUS_IOC_FAILURE; if (cee->get_attr_pending) return BFA_STATUS_DEVBUSY; cee->get_attr_pending = true; cmd = (struct bfi_cee_get_req *) cee->get_cfg_mb.msg; cee->attr = attr; cee->cbfn.get_attr_cbfn = cbfn; cee->cbfn.get_attr_cbarg = cbarg; bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ, bfa_ioc_portid(cee->ioc)); bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa); bfa_nw_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb, NULL, NULL); return BFA_STATUS_OK; } /** * bfa_cee_isrs - Handles Mail-box interrupts for CEE module. */ static void bfa_cee_isr(void *cbarg, struct bfi_mbmsg *m) { union bfi_cee_i2h_msg_u *msg; struct bfi_cee_get_rsp *get_rsp; struct bfa_cee *cee = (struct bfa_cee *) cbarg; msg = (union bfi_cee_i2h_msg_u *) m; get_rsp = (struct bfi_cee_get_rsp *) m; switch (msg->mh.msg_id) { case BFI_CEE_I2H_GET_CFG_RSP: bfa_cee_get_attr_isr(cee, get_rsp->cmd_status); break; case BFI_CEE_I2H_GET_STATS_RSP: bfa_cee_get_stats_isr(cee, get_rsp->cmd_status); break; case BFI_CEE_I2H_RESET_STATS_RSP: bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status); break; default: BUG_ON(1); } } /** * bfa_cee_notify - CEE module heart-beat failure handler. * * @event: IOC event type */ static void bfa_cee_notify(void *arg, enum bfa_ioc_event event) { struct bfa_cee *cee; cee = (struct bfa_cee *) arg; switch (event) { case BFA_IOC_E_DISABLED: case BFA_IOC_E_FAILED: if (cee->get_attr_pending) { cee->get_attr_status = BFA_STATUS_FAILED; cee->get_attr_pending = false; if (cee->cbfn.get_attr_cbfn) { cee->cbfn.get_attr_cbfn( cee->cbfn.get_attr_cbarg, BFA_STATUS_FAILED); } } if (cee->get_stats_pending) { cee->get_stats_status = BFA_STATUS_FAILED; cee->get_stats_pending = false; if (cee->cbfn.get_stats_cbfn) { cee->cbfn.get_stats_cbfn( cee->cbfn.get_stats_cbarg, BFA_STATUS_FAILED); } } if (cee->reset_stats_pending) { cee->reset_stats_status = BFA_STATUS_FAILED; cee->reset_stats_pending = false; if (cee->cbfn.reset_stats_cbfn) { cee->cbfn.reset_stats_cbfn( cee->cbfn.reset_stats_cbarg, BFA_STATUS_FAILED); } } break; default: break; } } /** * bfa_nw_cee_attach - CEE module-attach API * * @cee: Pointer to the CEE module data structure * @ioc: Pointer to the ioc module data structure * @dev: Pointer to the device driver module data structure. * The device driver specific mbox ISR functions have * this pointer as one of the parameters. */ void bfa_nw_cee_attach(struct bfa_cee *cee, struct bfa_ioc *ioc, void *dev) { BUG_ON(!(cee != NULL)); cee->dev = dev; cee->ioc = ioc; bfa_nw_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee); bfa_ioc_notify_init(&cee->ioc_notify, bfa_cee_notify, cee); bfa_nw_ioc_notify_register(cee->ioc, &cee->ioc_notify); } |