1/* 2 * Copyright (c) 2005-2009 Brocade Communications Systems, Inc. 3 * All rights reserved 4 * www.brocade.com 5 * 6 * Linux driver for Brocade Fibre Channel Host Bus Adapter. 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License (GPL) Version 2 as 10 * published by the Free Software Foundation 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 */ 17 18#include <defs/bfa_defs_cee.h> 19#include <cs/bfa_trc.h> 20#include <cs/bfa_log.h> 21#include <cs/bfa_debug.h> 22#include <cee/bfa_cee.h> 23#include <bfi/bfi_cee.h> 24#include <bfi/bfi.h> 25#include <bfa_ioc.h> 26#include <cna/bfa_cna_trcmod.h> 27 28BFA_TRC_FILE(CNA, CEE); 29 30#define bfa_ioc_portid(__ioc) ((__ioc)->port_id) 31#define bfa_lpuid(__arg) bfa_ioc_portid(&(__arg)->ioc) 32 33static void bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg); 34static void bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s 35 *dcbcx_stats); 36static void bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s 37 *lldp_stats); 38static void bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats); 39static void bfa_cee_format_cee_cfg(void *buffer); 40static void bfa_cee_format_cee_stats(void *buffer); 41 42static void 43bfa_cee_format_cee_stats(void *buffer) 44{ 45 struct bfa_cee_stats_s *cee_stats = buffer; 46 bfa_cee_format_dcbcx_stats(&cee_stats->dcbx_stats); 47 bfa_cee_format_lldp_stats(&cee_stats->lldp_stats); 48 bfa_cee_format_cfg_stats(&cee_stats->cfg_stats); 49} 50 51static void 52bfa_cee_format_cee_cfg(void *buffer) 53{ 54 struct bfa_cee_attr_s *cee_cfg = buffer; 55 bfa_cee_format_lldp_cfg(&cee_cfg->lldp_remote); 56} 57 58static void 59bfa_cee_format_dcbcx_stats(struct bfa_cee_dcbx_stats_s *dcbcx_stats) 60{ 61 dcbcx_stats->subtlvs_unrecognized = 62 bfa_os_ntohl(dcbcx_stats->subtlvs_unrecognized); 63 dcbcx_stats->negotiation_failed = 64 bfa_os_ntohl(dcbcx_stats->negotiation_failed); 65 dcbcx_stats->remote_cfg_changed = 66 bfa_os_ntohl(dcbcx_stats->remote_cfg_changed); 67 dcbcx_stats->tlvs_received = bfa_os_ntohl(dcbcx_stats->tlvs_received); 68 dcbcx_stats->tlvs_invalid = bfa_os_ntohl(dcbcx_stats->tlvs_invalid); 69 dcbcx_stats->seqno = bfa_os_ntohl(dcbcx_stats->seqno); 70 dcbcx_stats->ackno = bfa_os_ntohl(dcbcx_stats->ackno); 71 dcbcx_stats->recvd_seqno = bfa_os_ntohl(dcbcx_stats->recvd_seqno); 72 dcbcx_stats->recvd_ackno = bfa_os_ntohl(dcbcx_stats->recvd_ackno); 73} 74 75static void 76bfa_cee_format_lldp_stats(struct bfa_cee_lldp_stats_s *lldp_stats) 77{ 78 lldp_stats->frames_transmitted = 79 bfa_os_ntohl(lldp_stats->frames_transmitted); 80 lldp_stats->frames_aged_out = bfa_os_ntohl(lldp_stats->frames_aged_out); 81 lldp_stats->frames_discarded = 82 bfa_os_ntohl(lldp_stats->frames_discarded); 83 lldp_stats->frames_in_error = bfa_os_ntohl(lldp_stats->frames_in_error); 84 lldp_stats->frames_rcvd = bfa_os_ntohl(lldp_stats->frames_rcvd); 85 lldp_stats->tlvs_discarded = bfa_os_ntohl(lldp_stats->tlvs_discarded); 86 lldp_stats->tlvs_unrecognized = 87 bfa_os_ntohl(lldp_stats->tlvs_unrecognized); 88} 89 90static void 91bfa_cee_format_cfg_stats(struct bfa_cee_cfg_stats_s *cfg_stats) 92{ 93 cfg_stats->cee_status_down = bfa_os_ntohl(cfg_stats->cee_status_down); 94 cfg_stats->cee_status_up = bfa_os_ntohl(cfg_stats->cee_status_up); 95 cfg_stats->cee_hw_cfg_changed = 96 bfa_os_ntohl(cfg_stats->cee_hw_cfg_changed); 97 cfg_stats->recvd_invalid_cfg = 98 bfa_os_ntohl(cfg_stats->recvd_invalid_cfg); 99} 100 101static void 102bfa_cee_format_lldp_cfg(struct bfa_cee_lldp_cfg_s *lldp_cfg) 103{ 104 lldp_cfg->time_to_interval = bfa_os_ntohs(lldp_cfg->time_to_interval); 105 lldp_cfg->enabled_system_cap = 106 bfa_os_ntohs(lldp_cfg->enabled_system_cap); 107} 108 109/** 110 * bfa_cee_attr_meminfo() 111 * 112 * 113 * @param[in] void 114 * 115 * @return Size of DMA region 116 */ 117static u32 118bfa_cee_attr_meminfo(void) 119{ 120 return BFA_ROUNDUP(sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ); 121} 122 123/** 124 * bfa_cee_stats_meminfo() 125 * 126 * 127 * @param[in] void 128 * 129 * @return Size of DMA region 130 */ 131static u32 132bfa_cee_stats_meminfo(void) 133{ 134 return BFA_ROUNDUP(sizeof(struct bfa_cee_stats_s), BFA_DMA_ALIGN_SZ); 135} 136 137/** 138 * bfa_cee_get_attr_isr() 139 * 140 * 141 * @param[in] cee - Pointer to the CEE module 142 * status - Return status from the f/w 143 * 144 * @return void 145 */ 146static void 147bfa_cee_get_attr_isr(struct bfa_cee_s *cee, bfa_status_t status) 148{ 149 cee->get_attr_status = status; 150 bfa_trc(cee, 0); 151 if (status == BFA_STATUS_OK) { 152 bfa_trc(cee, 0); 153 /* 154 * The requested data has been copied to the DMA area, *process 155 * it. 156 */ 157 memcpy(cee->attr, cee->attr_dma.kva, 158 sizeof(struct bfa_cee_attr_s)); 159 bfa_cee_format_cee_cfg(cee->attr); 160 } 161 cee->get_attr_pending = BFA_FALSE; 162 if (cee->cbfn.get_attr_cbfn) { 163 bfa_trc(cee, 0); 164 cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status); 165 } 166 bfa_trc(cee, 0); 167} 168 169/** 170 * bfa_cee_get_attr_isr() 171 * 172 * 173 * @param[in] cee - Pointer to the CEE module 174 * status - Return status from the f/w 175 * 176 * @return void 177 */ 178static void 179bfa_cee_get_stats_isr(struct bfa_cee_s *cee, bfa_status_t status) 180{ 181 cee->get_stats_status = status; 182 bfa_trc(cee, 0); 183 if (status == BFA_STATUS_OK) { 184 bfa_trc(cee, 0); 185 /* 186 * The requested data has been copied to the DMA area, process 187 * it. 188 */ 189 memcpy(cee->stats, cee->stats_dma.kva, 190 sizeof(struct bfa_cee_stats_s)); 191 bfa_cee_format_cee_stats(cee->stats); 192 } 193 cee->get_stats_pending = BFA_FALSE; 194 bfa_trc(cee, 0); 195 if (cee->cbfn.get_stats_cbfn) { 196 bfa_trc(cee, 0); 197 cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status); 198 } 199 bfa_trc(cee, 0); 200} 201 202/** 203 * bfa_cee_get_attr_isr() 204 * 205 * 206 * @param[in] cee - Pointer to the CEE module 207 * status - Return status from the f/w 208 * 209 * @return void 210 */ 211static void 212bfa_cee_reset_stats_isr(struct bfa_cee_s *cee, bfa_status_t status) 213{ 214 cee->reset_stats_status = status; 215 cee->reset_stats_pending = BFA_FALSE; 216 if (cee->cbfn.reset_stats_cbfn) 217 cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status); 218} 219 220/** 221 * bfa_cee_meminfo() 222 * 223 * 224 * @param[in] void 225 * 226 * @return Size of DMA region 227 */ 228u32 229bfa_cee_meminfo(void) 230{ 231 return bfa_cee_attr_meminfo() + bfa_cee_stats_meminfo(); 232} 233 234/** 235 * bfa_cee_mem_claim() 236 * 237 * 238 * @param[in] cee CEE module pointer 239 * dma_kva Kernel Virtual Address of CEE DMA Memory 240 * dma_pa Physical Address of CEE DMA Memory 241 * 242 * @return void 243 */ 244void 245bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, u64 dma_pa) 246{ 247 cee->attr_dma.kva = dma_kva; 248 cee->attr_dma.pa = dma_pa; 249 cee->stats_dma.kva = dma_kva + bfa_cee_attr_meminfo(); 250 cee->stats_dma.pa = dma_pa + bfa_cee_attr_meminfo(); 251 cee->attr = (struct bfa_cee_attr_s *)dma_kva; 252 cee->stats = 253 (struct bfa_cee_stats_s *)(dma_kva + bfa_cee_attr_meminfo()); 254} 255 256/** 257 * bfa_cee_get_attr() 258 * 259 * Send the request to the f/w to fetch CEE attributes. 260 * 261 * @param[in] Pointer to the CEE module data structure. 262 * 263 * @return Status 264 */ 265 266bfa_status_t 267bfa_cee_get_attr(struct bfa_cee_s *cee, struct bfa_cee_attr_s *attr, 268 bfa_cee_get_attr_cbfn_t cbfn, void *cbarg) 269{ 270 struct bfi_cee_get_req_s *cmd; 271 272 bfa_assert((cee != NULL) && (cee->ioc != NULL)); 273 bfa_trc(cee, 0); 274 if (!bfa_ioc_is_operational(cee->ioc)) { 275 bfa_trc(cee, 0); 276 return BFA_STATUS_IOC_FAILURE; 277 } 278 if (cee->get_attr_pending == BFA_TRUE) { 279 bfa_trc(cee, 0); 280 return BFA_STATUS_DEVBUSY; 281 } 282 cee->get_attr_pending = BFA_TRUE; 283 cmd = (struct bfi_cee_get_req_s *)cee->get_cfg_mb.msg; 284 cee->attr = attr; 285 cee->cbfn.get_attr_cbfn = cbfn; 286 cee->cbfn.get_attr_cbarg = cbarg; 287 bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ, 288 bfa_ioc_portid(cee->ioc)); 289 bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa); 290 bfa_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb); 291 bfa_trc(cee, 0); 292 293 return BFA_STATUS_OK; 294} 295 296/** 297 * bfa_cee_get_stats() 298 * 299 * Send the request to the f/w to fetch CEE statistics. 300 * 301 * @param[in] Pointer to the CEE module data structure. 302 * 303 * @return Status 304 */ 305 306bfa_status_t 307bfa_cee_get_stats(struct bfa_cee_s *cee, struct bfa_cee_stats_s *stats, 308 bfa_cee_get_stats_cbfn_t cbfn, void *cbarg) 309{ 310 struct bfi_cee_get_req_s *cmd; 311 312 bfa_assert((cee != NULL) && (cee->ioc != NULL)); 313 314 if (!bfa_ioc_is_operational(cee->ioc)) { 315 bfa_trc(cee, 0); 316 return BFA_STATUS_IOC_FAILURE; 317 } 318 if (cee->get_stats_pending == BFA_TRUE) { 319 bfa_trc(cee, 0); 320 return BFA_STATUS_DEVBUSY; 321 } 322 cee->get_stats_pending = BFA_TRUE; 323 cmd = (struct bfi_cee_get_req_s *)cee->get_stats_mb.msg; 324 cee->stats = stats; 325 cee->cbfn.get_stats_cbfn = cbfn; 326 cee->cbfn.get_stats_cbarg = cbarg; 327 bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_STATS_REQ, 328 bfa_ioc_portid(cee->ioc)); 329 bfa_dma_be_addr_set(cmd->dma_addr, cee->stats_dma.pa); 330 bfa_ioc_mbox_queue(cee->ioc, &cee->get_stats_mb); 331 bfa_trc(cee, 0); 332 333 return BFA_STATUS_OK; 334} 335 336/** 337 * bfa_cee_reset_stats() 338 * 339 * 340 * @param[in] Pointer to the CEE module data structure. 341 * 342 * @return Status 343 */ 344 345bfa_status_t 346bfa_cee_reset_stats(struct bfa_cee_s *cee, bfa_cee_reset_stats_cbfn_t cbfn, 347 void *cbarg) 348{ 349 struct bfi_cee_reset_stats_s *cmd; 350 351 bfa_assert((cee != NULL) && (cee->ioc != NULL)); 352 if (!bfa_ioc_is_operational(cee->ioc)) { 353 bfa_trc(cee, 0); 354 return BFA_STATUS_IOC_FAILURE; 355 } 356 if (cee->reset_stats_pending == BFA_TRUE) { 357 bfa_trc(cee, 0); 358 return BFA_STATUS_DEVBUSY; 359 } 360 cee->reset_stats_pending = BFA_TRUE; 361 cmd = (struct bfi_cee_reset_stats_s *)cee->reset_stats_mb.msg; 362 cee->cbfn.reset_stats_cbfn = cbfn; 363 cee->cbfn.reset_stats_cbarg = cbarg; 364 bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_RESET_STATS, 365 bfa_ioc_portid(cee->ioc)); 366 bfa_ioc_mbox_queue(cee->ioc, &cee->reset_stats_mb); 367 bfa_trc(cee, 0); 368 return BFA_STATUS_OK; 369} 370 371/** 372 * bfa_cee_isrs() 373 * 374 * 375 * @param[in] Pointer to the CEE module data structure. 376 * 377 * @return void 378 */ 379 380void 381bfa_cee_isr(void *cbarg, struct bfi_mbmsg_s *m) 382{ 383 union bfi_cee_i2h_msg_u *msg; 384 struct bfi_cee_get_rsp_s *get_rsp; 385 struct bfa_cee_s *cee = (struct bfa_cee_s *)cbarg; 386 msg = (union bfi_cee_i2h_msg_u *)m; 387 get_rsp = (struct bfi_cee_get_rsp_s *)m; 388 bfa_trc(cee, msg->mh.msg_id); 389 switch (msg->mh.msg_id) { 390 case BFI_CEE_I2H_GET_CFG_RSP: 391 bfa_trc(cee, get_rsp->cmd_status); 392 bfa_cee_get_attr_isr(cee, get_rsp->cmd_status); 393 break; 394 case BFI_CEE_I2H_GET_STATS_RSP: 395 bfa_cee_get_stats_isr(cee, get_rsp->cmd_status); 396 break; 397 case BFI_CEE_I2H_RESET_STATS_RSP: 398 bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status); 399 break; 400 default: 401 bfa_assert(0); 402 } 403} 404 405/** 406 * bfa_cee_hbfail() 407 * 408 * 409 * @param[in] Pointer to the CEE module data structure. 410 * 411 * @return void 412 */ 413 414void 415bfa_cee_hbfail(void *arg) 416{ 417 struct bfa_cee_s *cee; 418 cee = (struct bfa_cee_s *)arg; 419 420 if (cee->get_attr_pending == BFA_TRUE) { 421 cee->get_attr_status = BFA_STATUS_FAILED; 422 cee->get_attr_pending = BFA_FALSE; 423 if (cee->cbfn.get_attr_cbfn) { 424 cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, 425 BFA_STATUS_FAILED); 426 } 427 } 428 if (cee->get_stats_pending == BFA_TRUE) { 429 cee->get_stats_status = BFA_STATUS_FAILED; 430 cee->get_stats_pending = BFA_FALSE; 431 if (cee->cbfn.get_stats_cbfn) { 432 cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, 433 BFA_STATUS_FAILED); 434 } 435 } 436 if (cee->reset_stats_pending == BFA_TRUE) { 437 cee->reset_stats_status = BFA_STATUS_FAILED; 438 cee->reset_stats_pending = BFA_FALSE; 439 if (cee->cbfn.reset_stats_cbfn) { 440 cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, 441 BFA_STATUS_FAILED); 442 } 443 } 444} 445 446/** 447 * bfa_cee_attach() 448 * 449 * 450 * @param[in] cee - Pointer to the CEE module data structure 451 * ioc - Pointer to the ioc module data structure 452 * dev - Pointer to the device driver module data structure 453 * The device driver specific mbox ISR functions have 454 * this pointer as one of the parameters. 455 * trcmod - 456 * logmod - 457 * 458 * @return void 459 */ 460void 461bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc, void *dev, 462 struct bfa_trc_mod_s *trcmod, struct bfa_log_mod_s *logmod) 463{ 464 bfa_assert(cee != NULL); 465 cee->dev = dev; 466 cee->trcmod = trcmod; 467 cee->logmod = logmod; 468 cee->ioc = ioc; 469 470 bfa_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee); 471 bfa_ioc_hbfail_init(&cee->hbfail, bfa_cee_hbfail, cee); 472 bfa_ioc_hbfail_register(cee->ioc, &cee->hbfail); 473 bfa_trc(cee, 0); 474} 475 476/** 477 * bfa_cee_detach() 478 * 479 * 480 * @param[in] cee - Pointer to the CEE module data structure 481 * 482 * @return void 483 */ 484void 485bfa_cee_detach(struct bfa_cee_s *cee) 486{ 487 /* 488 * For now, just check if there is some ioctl pending and mark that as 489 * failed? 490 */ 491 /* bfa_cee_hbfail(cee); */ 492} 493