1 /* 2 * Copyright (C) 2003 - 2009 NetXen, Inc. 3 * Copyright (C) 2009 - QLogic Corporation. 4 * All rights reserved. 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * as published by the Free Software Foundation; either version 2 9 * of the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, 19 * MA 02111-1307, USA. 20 * 21 * The full GNU General Public License is included in this distribution 22 * in the file called "COPYING". 23 * 24 */ 25 26 #include "netxen_nic_hw.h" 27 #include "netxen_nic.h" 28 29 #define NXHAL_VERSION 1 30 31 static u32 32 netxen_poll_rsp(struct netxen_adapter *adapter) 33 { 34 u32 rsp = NX_CDRP_RSP_OK; 35 int timeout = 0; 36 37 do { 38 /* give atleast 1ms for firmware to respond */ 39 msleep(1); 40 41 if (++timeout > NX_OS_CRB_RETRY_COUNT) 42 return NX_CDRP_RSP_TIMEOUT; 43 44 rsp = NXRD32(adapter, NX_CDRP_CRB_OFFSET); 45 } while (!NX_CDRP_IS_RSP(rsp)); 46 47 return rsp; 48 } 49 50 static u32 51 netxen_issue_cmd(struct netxen_adapter *adapter, struct netxen_cmd_args *cmd) 52 { 53 u32 rsp; 54 u32 signature = 0; 55 u32 rcode = NX_RCODE_SUCCESS; 56 57 signature = NX_CDRP_SIGNATURE_MAKE(adapter->ahw.pci_func, 58 NXHAL_VERSION); 59 /* Acquire semaphore before accessing CRB */ 60 if (netxen_api_lock(adapter)) 61 return NX_RCODE_TIMEOUT; 62 63 NXWR32(adapter, NX_SIGN_CRB_OFFSET, signature); 64 65 NXWR32(adapter, NX_ARG1_CRB_OFFSET, cmd->req.arg1); 66 67 NXWR32(adapter, NX_ARG2_CRB_OFFSET, cmd->req.arg2); 68 69 NXWR32(adapter, NX_ARG3_CRB_OFFSET, cmd->req.arg3); 70 71 NXWR32(adapter, NX_CDRP_CRB_OFFSET, NX_CDRP_FORM_CMD(cmd->req.cmd)); 72 73 rsp = netxen_poll_rsp(adapter); 74 75 if (rsp == NX_CDRP_RSP_TIMEOUT) { 76 printk(KERN_ERR "%s: card response timeout.\n", 77 netxen_nic_driver_name); 78 79 rcode = NX_RCODE_TIMEOUT; 80 } else if (rsp == NX_CDRP_RSP_FAIL) { 81 rcode = NXRD32(adapter, NX_ARG1_CRB_OFFSET); 82 83 printk(KERN_ERR "%s: failed card response code:0x%x\n", 84 netxen_nic_driver_name, rcode); 85 } else if (rsp == NX_CDRP_RSP_OK) { 86 cmd->rsp.cmd = NX_RCODE_SUCCESS; 87 if (cmd->rsp.arg2) 88 cmd->rsp.arg2 = NXRD32(adapter, NX_ARG2_CRB_OFFSET); 89 if (cmd->rsp.arg3) 90 cmd->rsp.arg3 = NXRD32(adapter, NX_ARG3_CRB_OFFSET); 91 } 92 93 if (cmd->rsp.arg1) 94 cmd->rsp.arg1 = NXRD32(adapter, NX_ARG1_CRB_OFFSET); 95 /* Release semaphore */ 96 netxen_api_unlock(adapter); 97 98 return rcode; 99 } 100 101 static int 102 netxen_get_minidump_template_size(struct netxen_adapter *adapter) 103 { 104 struct netxen_cmd_args cmd; 105 memset(&cmd, 0, sizeof(cmd)); 106 cmd.req.cmd = NX_CDRP_CMD_TEMP_SIZE; 107 memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd)); 108 netxen_issue_cmd(adapter, &cmd); 109 if (cmd.rsp.cmd != NX_RCODE_SUCCESS) { 110 dev_info(&adapter->pdev->dev, 111 "Can't get template size %d\n", cmd.rsp.cmd); 112 return -EIO; 113 } 114 adapter->mdump.md_template_size = cmd.rsp.arg2; 115 adapter->mdump.md_template_ver = cmd.rsp.arg3; 116 return 0; 117 } 118 119 static int 120 netxen_get_minidump_template(struct netxen_adapter *adapter) 121 { 122 dma_addr_t md_template_addr; 123 void *addr; 124 u32 size; 125 struct netxen_cmd_args cmd; 126 size = adapter->mdump.md_template_size; 127 128 if (size == 0) { 129 dev_err(&adapter->pdev->dev, "Can not capture Minidump " 130 "template. Invalid template size.\n"); 131 return NX_RCODE_INVALID_ARGS; 132 } 133 134 addr = pci_alloc_consistent(adapter->pdev, size, &md_template_addr); 135 136 if (!addr) { 137 dev_err(&adapter->pdev->dev, "Unable to allocate dmable memory for template.\n"); 138 return -ENOMEM; 139 } 140 141 memset(addr, 0, size); 142 memset(&cmd, 0, sizeof(cmd)); 143 memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd)); 144 cmd.req.cmd = NX_CDRP_CMD_GET_TEMP_HDR; 145 cmd.req.arg1 = LSD(md_template_addr); 146 cmd.req.arg2 = MSD(md_template_addr); 147 cmd.req.arg3 |= size; 148 netxen_issue_cmd(adapter, &cmd); 149 150 if ((cmd.rsp.cmd == NX_RCODE_SUCCESS) && (size == cmd.rsp.arg2)) { 151 memcpy(adapter->mdump.md_template, addr, size); 152 } else { 153 dev_err(&adapter->pdev->dev, "Failed to get minidump template, " 154 "err_code : %d, requested_size : %d, actual_size : %d\n ", 155 cmd.rsp.cmd, size, cmd.rsp.arg2); 156 } 157 pci_free_consistent(adapter->pdev, size, addr, md_template_addr); 158 return 0; 159 } 160 161 static u32 162 netxen_check_template_checksum(struct netxen_adapter *adapter) 163 { 164 u64 sum = 0 ; 165 u32 *buff = adapter->mdump.md_template; 166 int count = adapter->mdump.md_template_size/sizeof(uint32_t) ; 167 168 while (count-- > 0) 169 sum += *buff++ ; 170 while (sum >> 32) 171 sum = (sum & 0xFFFFFFFF) + (sum >> 32) ; 172 173 return ~sum; 174 } 175 176 int 177 netxen_setup_minidump(struct netxen_adapter *adapter) 178 { 179 int err = 0, i; 180 u32 *template, *tmp_buf; 181 struct netxen_minidump_template_hdr *hdr; 182 err = netxen_get_minidump_template_size(adapter); 183 if (err) { 184 adapter->mdump.fw_supports_md = 0; 185 if ((err == NX_RCODE_CMD_INVALID) || 186 (err == NX_RCODE_CMD_NOT_IMPL)) { 187 dev_info(&adapter->pdev->dev, 188 "Flashed firmware version does not support minidump, " 189 "minimum version required is [ %u.%u.%u ].\n ", 190 NX_MD_SUPPORT_MAJOR, NX_MD_SUPPORT_MINOR, 191 NX_MD_SUPPORT_SUBVERSION); 192 } 193 return err; 194 } 195 196 if (!adapter->mdump.md_template_size) { 197 dev_err(&adapter->pdev->dev, "Error : Invalid template size " 198 ",should be non-zero.\n"); 199 return -EIO; 200 } 201 adapter->mdump.md_template = 202 kmalloc(adapter->mdump.md_template_size, GFP_KERNEL); 203 204 if (!adapter->mdump.md_template) { 205 dev_err(&adapter->pdev->dev, "Unable to allocate memory " 206 "for minidump template.\n"); 207 return -ENOMEM; 208 } 209 210 err = netxen_get_minidump_template(adapter); 211 if (err) { 212 if (err == NX_RCODE_CMD_NOT_IMPL) 213 adapter->mdump.fw_supports_md = 0; 214 goto free_template; 215 } 216 217 if (netxen_check_template_checksum(adapter)) { 218 dev_err(&adapter->pdev->dev, "Minidump template checksum Error\n"); 219 err = -EIO; 220 goto free_template; 221 } 222 223 adapter->mdump.md_capture_mask = NX_DUMP_MASK_DEF; 224 tmp_buf = (u32 *) adapter->mdump.md_template; 225 template = (u32 *) adapter->mdump.md_template; 226 for (i = 0; i < adapter->mdump.md_template_size/sizeof(u32); i++) 227 *template++ = __le32_to_cpu(*tmp_buf++); 228 hdr = (struct netxen_minidump_template_hdr *) 229 adapter->mdump.md_template; 230 adapter->mdump.md_capture_buff = NULL; 231 adapter->mdump.fw_supports_md = 1; 232 adapter->mdump.md_enabled = 0; 233 234 return err; 235 236 free_template: 237 kfree(adapter->mdump.md_template); 238 adapter->mdump.md_template = NULL; 239 return err; 240 } 241 242 243 int 244 nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu) 245 { 246 u32 rcode = NX_RCODE_SUCCESS; 247 struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; 248 struct netxen_cmd_args cmd; 249 250 memset(&cmd, 0, sizeof(cmd)); 251 cmd.req.cmd = NX_CDRP_CMD_SET_MTU; 252 cmd.req.arg1 = recv_ctx->context_id; 253 cmd.req.arg2 = mtu; 254 cmd.req.arg3 = 0; 255 256 if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE) 257 netxen_issue_cmd(adapter, &cmd); 258 259 if (rcode != NX_RCODE_SUCCESS) 260 return -EIO; 261 262 return 0; 263 } 264 265 int 266 nx_fw_cmd_set_gbe_port(struct netxen_adapter *adapter, 267 u32 speed, u32 duplex, u32 autoneg) 268 { 269 struct netxen_cmd_args cmd; 270 271 memset(&cmd, 0, sizeof(cmd)); 272 cmd.req.cmd = NX_CDRP_CMD_CONFIG_GBE_PORT; 273 cmd.req.arg1 = speed; 274 cmd.req.arg2 = duplex; 275 cmd.req.arg3 = autoneg; 276 return netxen_issue_cmd(adapter, &cmd); 277 } 278 279 static int 280 nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter) 281 { 282 void *addr; 283 nx_hostrq_rx_ctx_t *prq; 284 nx_cardrsp_rx_ctx_t *prsp; 285 nx_hostrq_rds_ring_t *prq_rds; 286 nx_hostrq_sds_ring_t *prq_sds; 287 nx_cardrsp_rds_ring_t *prsp_rds; 288 nx_cardrsp_sds_ring_t *prsp_sds; 289 struct nx_host_rds_ring *rds_ring; 290 struct nx_host_sds_ring *sds_ring; 291 struct netxen_cmd_args cmd; 292 293 dma_addr_t hostrq_phys_addr, cardrsp_phys_addr; 294 u64 phys_addr; 295 296 int i, nrds_rings, nsds_rings; 297 size_t rq_size, rsp_size; 298 u32 cap, reg, val; 299 300 int err; 301 302 struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; 303 304 nrds_rings = adapter->max_rds_rings; 305 nsds_rings = adapter->max_sds_rings; 306 307 rq_size = 308 SIZEOF_HOSTRQ_RX(nx_hostrq_rx_ctx_t, nrds_rings, nsds_rings); 309 rsp_size = 310 SIZEOF_CARDRSP_RX(nx_cardrsp_rx_ctx_t, nrds_rings, nsds_rings); 311 312 addr = pci_alloc_consistent(adapter->pdev, 313 rq_size, &hostrq_phys_addr); 314 if (addr == NULL) 315 return -ENOMEM; 316 prq = addr; 317 318 addr = pci_alloc_consistent(adapter->pdev, 319 rsp_size, &cardrsp_phys_addr); 320 if (addr == NULL) { 321 err = -ENOMEM; 322 goto out_free_rq; 323 } 324 prsp = addr; 325 326 prq->host_rsp_dma_addr = cpu_to_le64(cardrsp_phys_addr); 327 328 cap = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN); 329 cap |= (NX_CAP0_JUMBO_CONTIGUOUS | NX_CAP0_LRO_CONTIGUOUS); 330 331 if (adapter->flags & NETXEN_FW_MSS_CAP) 332 cap |= NX_CAP0_HW_LRO_MSS; 333 334 prq->capabilities[0] = cpu_to_le32(cap); 335 prq->host_int_crb_mode = 336 cpu_to_le32(NX_HOST_INT_CRB_MODE_SHARED); 337 prq->host_rds_crb_mode = 338 cpu_to_le32(NX_HOST_RDS_CRB_MODE_UNIQUE); 339 340 prq->num_rds_rings = cpu_to_le16(nrds_rings); 341 prq->num_sds_rings = cpu_to_le16(nsds_rings); 342 prq->rds_ring_offset = cpu_to_le32(0); 343 344 val = le32_to_cpu(prq->rds_ring_offset) + 345 (sizeof(nx_hostrq_rds_ring_t) * nrds_rings); 346 prq->sds_ring_offset = cpu_to_le32(val); 347 348 prq_rds = (nx_hostrq_rds_ring_t *)(prq->data + 349 le32_to_cpu(prq->rds_ring_offset)); 350 351 for (i = 0; i < nrds_rings; i++) { 352 353 rds_ring = &recv_ctx->rds_rings[i]; 354 355 prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr); 356 prq_rds[i].ring_size = cpu_to_le32(rds_ring->num_desc); 357 prq_rds[i].ring_kind = cpu_to_le32(i); 358 prq_rds[i].buff_size = cpu_to_le64(rds_ring->dma_size); 359 } 360 361 prq_sds = (nx_hostrq_sds_ring_t *)(prq->data + 362 le32_to_cpu(prq->sds_ring_offset)); 363 364 for (i = 0; i < nsds_rings; i++) { 365 366 sds_ring = &recv_ctx->sds_rings[i]; 367 368 prq_sds[i].host_phys_addr = cpu_to_le64(sds_ring->phys_addr); 369 prq_sds[i].ring_size = cpu_to_le32(sds_ring->num_desc); 370 prq_sds[i].msi_index = cpu_to_le16(i); 371 } 372 373 phys_addr = hostrq_phys_addr; 374 memset(&cmd, 0, sizeof(cmd)); 375 cmd.req.arg1 = (u32)(phys_addr >> 32); 376 cmd.req.arg2 = (u32)(phys_addr & 0xffffffff); 377 cmd.req.arg3 = rq_size; 378 cmd.req.cmd = NX_CDRP_CMD_CREATE_RX_CTX; 379 err = netxen_issue_cmd(adapter, &cmd); 380 if (err) { 381 printk(KERN_WARNING 382 "Failed to create rx ctx in firmware%d\n", err); 383 goto out_free_rsp; 384 } 385 386 387 prsp_rds = ((nx_cardrsp_rds_ring_t *) 388 &prsp->data[le32_to_cpu(prsp->rds_ring_offset)]); 389 390 for (i = 0; i < le16_to_cpu(prsp->num_rds_rings); i++) { 391 rds_ring = &recv_ctx->rds_rings[i]; 392 393 reg = le32_to_cpu(prsp_rds[i].host_producer_crb); 394 rds_ring->crb_rcv_producer = netxen_get_ioaddr(adapter, 395 NETXEN_NIC_REG(reg - 0x200)); 396 } 397 398 prsp_sds = ((nx_cardrsp_sds_ring_t *) 399 &prsp->data[le32_to_cpu(prsp->sds_ring_offset)]); 400 401 for (i = 0; i < le16_to_cpu(prsp->num_sds_rings); i++) { 402 sds_ring = &recv_ctx->sds_rings[i]; 403 404 reg = le32_to_cpu(prsp_sds[i].host_consumer_crb); 405 sds_ring->crb_sts_consumer = netxen_get_ioaddr(adapter, 406 NETXEN_NIC_REG(reg - 0x200)); 407 408 reg = le32_to_cpu(prsp_sds[i].interrupt_crb); 409 sds_ring->crb_intr_mask = netxen_get_ioaddr(adapter, 410 NETXEN_NIC_REG(reg - 0x200)); 411 } 412 413 recv_ctx->state = le32_to_cpu(prsp->host_ctx_state); 414 recv_ctx->context_id = le16_to_cpu(prsp->context_id); 415 recv_ctx->virt_port = prsp->virt_port; 416 417 out_free_rsp: 418 pci_free_consistent(adapter->pdev, rsp_size, prsp, cardrsp_phys_addr); 419 out_free_rq: 420 pci_free_consistent(adapter->pdev, rq_size, prq, hostrq_phys_addr); 421 return err; 422 } 423 424 static void 425 nx_fw_cmd_destroy_rx_ctx(struct netxen_adapter *adapter) 426 { 427 struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; 428 struct netxen_cmd_args cmd; 429 430 memset(&cmd, 0, sizeof(cmd)); 431 cmd.req.arg1 = recv_ctx->context_id; 432 cmd.req.arg2 = NX_DESTROY_CTX_RESET; 433 cmd.req.arg3 = 0; 434 cmd.req.cmd = NX_CDRP_CMD_DESTROY_RX_CTX; 435 436 if (netxen_issue_cmd(adapter, &cmd)) { 437 printk(KERN_WARNING 438 "%s: Failed to destroy rx ctx in firmware\n", 439 netxen_nic_driver_name); 440 } 441 } 442 443 static int 444 nx_fw_cmd_create_tx_ctx(struct netxen_adapter *adapter) 445 { 446 nx_hostrq_tx_ctx_t *prq; 447 nx_hostrq_cds_ring_t *prq_cds; 448 nx_cardrsp_tx_ctx_t *prsp; 449 void *rq_addr, *rsp_addr; 450 size_t rq_size, rsp_size; 451 u32 temp; 452 int err = 0; 453 u64 offset, phys_addr; 454 dma_addr_t rq_phys_addr, rsp_phys_addr; 455 struct nx_host_tx_ring *tx_ring = adapter->tx_ring; 456 struct netxen_recv_context *recv_ctx = &adapter->recv_ctx; 457 struct netxen_cmd_args cmd; 458 459 rq_size = SIZEOF_HOSTRQ_TX(nx_hostrq_tx_ctx_t); 460 rq_addr = pci_alloc_consistent(adapter->pdev, 461 rq_size, &rq_phys_addr); 462 if (!rq_addr) 463 return -ENOMEM; 464 465 rsp_size = SIZEOF_CARDRSP_TX(nx_cardrsp_tx_ctx_t); 466 rsp_addr = pci_alloc_consistent(adapter->pdev, 467 rsp_size, &rsp_phys_addr); 468 if (!rsp_addr) { 469 err = -ENOMEM; 470 goto out_free_rq; 471 } 472 473 memset(rq_addr, 0, rq_size); 474 prq = rq_addr; 475 476 memset(rsp_addr, 0, rsp_size); 477 prsp = rsp_addr; 478 479 prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr); 480 481 temp = (NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN | NX_CAP0_LSO); 482 prq->capabilities[0] = cpu_to_le32(temp); 483 484 prq->host_int_crb_mode = 485 cpu_to_le32(NX_HOST_INT_CRB_MODE_SHARED); 486 487 prq->interrupt_ctl = 0; 488 prq->msi_index = 0; 489 490 prq->dummy_dma_addr = cpu_to_le64(adapter->dummy_dma.phys_addr); 491 492 offset = recv_ctx->phys_addr + sizeof(struct netxen_ring_ctx); 493 prq->cmd_cons_dma_addr = cpu_to_le64(offset); 494 495 prq_cds = &prq->cds_ring; 496 497 prq_cds->host_phys_addr = cpu_to_le64(tx_ring->phys_addr); 498 prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc); 499 500 phys_addr = rq_phys_addr; 501 memset(&cmd, 0, sizeof(cmd)); 502 cmd.req.arg1 = (u32)(phys_addr >> 32); 503 cmd.req.arg2 = ((u32)phys_addr & 0xffffffff); 504 cmd.req.arg3 = rq_size; 505 cmd.req.cmd = NX_CDRP_CMD_CREATE_TX_CTX; 506 err = netxen_issue_cmd(adapter, &cmd); 507 508 if (err == NX_RCODE_SUCCESS) { 509 temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); 510 tx_ring->crb_cmd_producer = netxen_get_ioaddr(adapter, 511 NETXEN_NIC_REG(temp - 0x200)); 512 #if 0 513 adapter->tx_state = 514 le32_to_cpu(prsp->host_ctx_state); 515 #endif 516 adapter->tx_context_id = 517 le16_to_cpu(prsp->context_id); 518 } else { 519 printk(KERN_WARNING 520 "Failed to create tx ctx in firmware%d\n", err); 521 err = -EIO; 522 } 523 524 pci_free_consistent(adapter->pdev, rsp_size, rsp_addr, rsp_phys_addr); 525 526 out_free_rq: 527 pci_free_consistent(adapter->pdev, rq_size, rq_addr, rq_phys_addr); 528 529 return err; 530 } 531 532 static void 533 nx_fw_cmd_destroy_tx_ctx(struct netxen_adapter *adapter) 534 { 535 struct netxen_cmd_args cmd; 536 537 memset(&cmd, 0, sizeof(cmd)); 538 cmd.req.arg1 = adapter->tx_context_id; 539 cmd.req.arg2 = NX_DESTROY_CTX_RESET; 540 cmd.req.arg3 = 0; 541 cmd.req.cmd = NX_CDRP_CMD_DESTROY_TX_CTX; 542 if (netxen_issue_cmd(adapter, &cmd)) { 543 printk(KERN_WARNING 544 "%s: Failed to destroy tx ctx in firmware\n", 545 netxen_nic_driver_name); 546 } 547 } 548 549 int 550 nx_fw_cmd_query_phy(struct netxen_adapter *adapter, u32 reg, u32 *val) 551 { 552 u32 rcode; 553 struct netxen_cmd_args cmd; 554 555 memset(&cmd, 0, sizeof(cmd)); 556 cmd.req.arg1 = reg; 557 cmd.req.arg2 = 0; 558 cmd.req.arg3 = 0; 559 cmd.req.cmd = NX_CDRP_CMD_READ_PHY; 560 cmd.rsp.arg1 = 1; 561 rcode = netxen_issue_cmd(adapter, &cmd); 562 if (rcode != NX_RCODE_SUCCESS) 563 return -EIO; 564 565 if (val == NULL) 566 return -EIO; 567 568 *val = cmd.rsp.arg1; 569 return 0; 570 } 571 572 int 573 nx_fw_cmd_set_phy(struct netxen_adapter *adapter, u32 reg, u32 val) 574 { 575 u32 rcode; 576 struct netxen_cmd_args cmd; 577 578 memset(&cmd, 0, sizeof(cmd)); 579 cmd.req.arg1 = reg; 580 cmd.req.arg2 = val; 581 cmd.req.arg3 = 0; 582 cmd.req.cmd = NX_CDRP_CMD_WRITE_PHY; 583 rcode = netxen_issue_cmd(adapter, &cmd); 584 if (rcode != NX_RCODE_SUCCESS) 585 return -EIO; 586 587 return 0; 588 } 589 590 static u64 ctx_addr_sig_regs[][3] = { 591 {NETXEN_NIC_REG(0x188), NETXEN_NIC_REG(0x18c), NETXEN_NIC_REG(0x1c0)}, 592 {NETXEN_NIC_REG(0x190), NETXEN_NIC_REG(0x194), NETXEN_NIC_REG(0x1c4)}, 593 {NETXEN_NIC_REG(0x198), NETXEN_NIC_REG(0x19c), NETXEN_NIC_REG(0x1c8)}, 594 {NETXEN_NIC_REG(0x1a0), NETXEN_NIC_REG(0x1a4), NETXEN_NIC_REG(0x1cc)} 595 }; 596 597 #define CRB_CTX_ADDR_REG_LO(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][0]) 598 #define CRB_CTX_ADDR_REG_HI(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][2]) 599 #define CRB_CTX_SIGNATURE_REG(FUNC_ID) (ctx_addr_sig_regs[FUNC_ID][1]) 600 601 #define lower32(x) ((u32)((x) & 0xffffffff)) 602 #define upper32(x) ((u32)(((u64)(x) >> 32) & 0xffffffff)) 603 604 static struct netxen_recv_crb recv_crb_registers[] = { 605 /* Instance 0 */ 606 { 607 /* crb_rcv_producer: */ 608 { 609 NETXEN_NIC_REG(0x100), 610 /* Jumbo frames */ 611 NETXEN_NIC_REG(0x110), 612 /* LRO */ 613 NETXEN_NIC_REG(0x120) 614 }, 615 /* crb_sts_consumer: */ 616 { 617 NETXEN_NIC_REG(0x138), 618 NETXEN_NIC_REG_2(0x000), 619 NETXEN_NIC_REG_2(0x004), 620 NETXEN_NIC_REG_2(0x008), 621 }, 622 /* sw_int_mask */ 623 { 624 CRB_SW_INT_MASK_0, 625 NETXEN_NIC_REG_2(0x044), 626 NETXEN_NIC_REG_2(0x048), 627 NETXEN_NIC_REG_2(0x04c), 628 }, 629 }, 630 /* Instance 1 */ 631 { 632 /* crb_rcv_producer: */ 633 { 634 NETXEN_NIC_REG(0x144), 635 /* Jumbo frames */ 636 NETXEN_NIC_REG(0x154), 637 /* LRO */ 638 NETXEN_NIC_REG(0x164) 639 }, 640 /* crb_sts_consumer: */ 641 { 642 NETXEN_NIC_REG(0x17c), 643 NETXEN_NIC_REG_2(0x020), 644 NETXEN_NIC_REG_2(0x024), 645 NETXEN_NIC_REG_2(0x028), 646 }, 647 /* sw_int_mask */ 648 { 649 CRB_SW_INT_MASK_1, 650 NETXEN_NIC_REG_2(0x064), 651 NETXEN_NIC_REG_2(0x068), 652 NETXEN_NIC_REG_2(0x06c), 653 }, 654 }, 655 /* Instance 2 */ 656 { 657 /* crb_rcv_producer: */ 658 { 659 NETXEN_NIC_REG(0x1d8), 660 /* Jumbo frames */ 661 NETXEN_NIC_REG(0x1f8), 662 /* LRO */ 663 NETXEN_NIC_REG(0x208) 664 }, 665 /* crb_sts_consumer: */ 666 { 667 NETXEN_NIC_REG(0x220), 668 NETXEN_NIC_REG_2(0x03c), 669 NETXEN_NIC_REG_2(0x03c), 670 NETXEN_NIC_REG_2(0x03c), 671 }, 672 /* sw_int_mask */ 673 { 674 CRB_SW_INT_MASK_2, 675 NETXEN_NIC_REG_2(0x03c), 676 NETXEN_NIC_REG_2(0x03c), 677 NETXEN_NIC_REG_2(0x03c), 678 }, 679 }, 680 /* Instance 3 */ 681 { 682 /* crb_rcv_producer: */ 683 { 684 NETXEN_NIC_REG(0x22c), 685 /* Jumbo frames */ 686 NETXEN_NIC_REG(0x23c), 687 /* LRO */ 688 NETXEN_NIC_REG(0x24c) 689 }, 690 /* crb_sts_consumer: */ 691 { 692 NETXEN_NIC_REG(0x264), 693 NETXEN_NIC_REG_2(0x03c), 694 NETXEN_NIC_REG_2(0x03c), 695 NETXEN_NIC_REG_2(0x03c), 696 }, 697 /* sw_int_mask */ 698 { 699 CRB_SW_INT_MASK_3, 700 NETXEN_NIC_REG_2(0x03c), 701 NETXEN_NIC_REG_2(0x03c), 702 NETXEN_NIC_REG_2(0x03c), 703 }, 704 }, 705 }; 706 707 static int 708 netxen_init_old_ctx(struct netxen_adapter *adapter) 709 { 710 struct netxen_recv_context *recv_ctx; 711 struct nx_host_rds_ring *rds_ring; 712 struct nx_host_sds_ring *sds_ring; 713 struct nx_host_tx_ring *tx_ring; 714 int ring; 715 int port = adapter->portnum; 716 struct netxen_ring_ctx *hwctx; 717 u32 signature; 718 719 tx_ring = adapter->tx_ring; 720 recv_ctx = &adapter->recv_ctx; 721 hwctx = recv_ctx->hwctx; 722 723 hwctx->cmd_ring_addr = cpu_to_le64(tx_ring->phys_addr); 724 hwctx->cmd_ring_size = cpu_to_le32(tx_ring->num_desc); 725 726 727 for (ring = 0; ring < adapter->max_rds_rings; ring++) { 728 rds_ring = &recv_ctx->rds_rings[ring]; 729 730 hwctx->rcv_rings[ring].addr = 731 cpu_to_le64(rds_ring->phys_addr); 732 hwctx->rcv_rings[ring].size = 733 cpu_to_le32(rds_ring->num_desc); 734 } 735 736 for (ring = 0; ring < adapter->max_sds_rings; ring++) { 737 sds_ring = &recv_ctx->sds_rings[ring]; 738 739 if (ring == 0) { 740 hwctx->sts_ring_addr = cpu_to_le64(sds_ring->phys_addr); 741 hwctx->sts_ring_size = cpu_to_le32(sds_ring->num_desc); 742 } 743 hwctx->sts_rings[ring].addr = cpu_to_le64(sds_ring->phys_addr); 744 hwctx->sts_rings[ring].size = cpu_to_le32(sds_ring->num_desc); 745 hwctx->sts_rings[ring].msi_index = cpu_to_le16(ring); 746 } 747 hwctx->sts_ring_count = cpu_to_le32(adapter->max_sds_rings); 748 749 signature = (adapter->max_sds_rings > 1) ? 750 NETXEN_CTX_SIGNATURE_V2 : NETXEN_CTX_SIGNATURE; 751 752 NXWR32(adapter, CRB_CTX_ADDR_REG_LO(port), 753 lower32(recv_ctx->phys_addr)); 754 NXWR32(adapter, CRB_CTX_ADDR_REG_HI(port), 755 upper32(recv_ctx->phys_addr)); 756 NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port), 757 signature | port); 758 return 0; 759 } 760 761 int netxen_alloc_hw_resources(struct netxen_adapter *adapter) 762 { 763 void *addr; 764 int err = 0; 765 int ring; 766 struct netxen_recv_context *recv_ctx; 767 struct nx_host_rds_ring *rds_ring; 768 struct nx_host_sds_ring *sds_ring; 769 struct nx_host_tx_ring *tx_ring; 770 771 struct pci_dev *pdev = adapter->pdev; 772 struct net_device *netdev = adapter->netdev; 773 int port = adapter->portnum; 774 775 recv_ctx = &adapter->recv_ctx; 776 tx_ring = adapter->tx_ring; 777 778 addr = pci_alloc_consistent(pdev, 779 sizeof(struct netxen_ring_ctx) + sizeof(uint32_t), 780 &recv_ctx->phys_addr); 781 if (addr == NULL) { 782 dev_err(&pdev->dev, "failed to allocate hw context\n"); 783 return -ENOMEM; 784 } 785 786 memset(addr, 0, sizeof(struct netxen_ring_ctx)); 787 recv_ctx->hwctx = addr; 788 recv_ctx->hwctx->ctx_id = cpu_to_le32(port); 789 recv_ctx->hwctx->cmd_consumer_offset = 790 cpu_to_le64(recv_ctx->phys_addr + 791 sizeof(struct netxen_ring_ctx)); 792 tx_ring->hw_consumer = 793 (__le32 *)(((char *)addr) + sizeof(struct netxen_ring_ctx)); 794 795 /* cmd desc ring */ 796 addr = pci_alloc_consistent(pdev, TX_DESC_RINGSIZE(tx_ring), 797 &tx_ring->phys_addr); 798 799 if (addr == NULL) { 800 dev_err(&pdev->dev, "%s: failed to allocate tx desc ring\n", 801 netdev->name); 802 err = -ENOMEM; 803 goto err_out_free; 804 } 805 806 tx_ring->desc_head = addr; 807 808 for (ring = 0; ring < adapter->max_rds_rings; ring++) { 809 rds_ring = &recv_ctx->rds_rings[ring]; 810 addr = pci_alloc_consistent(adapter->pdev, 811 RCV_DESC_RINGSIZE(rds_ring), 812 &rds_ring->phys_addr); 813 if (addr == NULL) { 814 dev_err(&pdev->dev, 815 "%s: failed to allocate rds ring [%d]\n", 816 netdev->name, ring); 817 err = -ENOMEM; 818 goto err_out_free; 819 } 820 rds_ring->desc_head = addr; 821 822 if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) 823 rds_ring->crb_rcv_producer = 824 netxen_get_ioaddr(adapter, 825 recv_crb_registers[port].crb_rcv_producer[ring]); 826 } 827 828 for (ring = 0; ring < adapter->max_sds_rings; ring++) { 829 sds_ring = &recv_ctx->sds_rings[ring]; 830 831 addr = pci_alloc_consistent(adapter->pdev, 832 STATUS_DESC_RINGSIZE(sds_ring), 833 &sds_ring->phys_addr); 834 if (addr == NULL) { 835 dev_err(&pdev->dev, 836 "%s: failed to allocate sds ring [%d]\n", 837 netdev->name, ring); 838 err = -ENOMEM; 839 goto err_out_free; 840 } 841 sds_ring->desc_head = addr; 842 843 if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { 844 sds_ring->crb_sts_consumer = 845 netxen_get_ioaddr(adapter, 846 recv_crb_registers[port].crb_sts_consumer[ring]); 847 848 sds_ring->crb_intr_mask = 849 netxen_get_ioaddr(adapter, 850 recv_crb_registers[port].sw_int_mask[ring]); 851 } 852 } 853 854 855 if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) { 856 if (test_and_set_bit(__NX_FW_ATTACHED, &adapter->state)) 857 goto done; 858 err = nx_fw_cmd_create_rx_ctx(adapter); 859 if (err) 860 goto err_out_free; 861 err = nx_fw_cmd_create_tx_ctx(adapter); 862 if (err) 863 goto err_out_free; 864 } else { 865 err = netxen_init_old_ctx(adapter); 866 if (err) 867 goto err_out_free; 868 } 869 870 done: 871 return 0; 872 873 err_out_free: 874 netxen_free_hw_resources(adapter); 875 return err; 876 } 877 878 void netxen_free_hw_resources(struct netxen_adapter *adapter) 879 { 880 struct netxen_recv_context *recv_ctx; 881 struct nx_host_rds_ring *rds_ring; 882 struct nx_host_sds_ring *sds_ring; 883 struct nx_host_tx_ring *tx_ring; 884 int ring; 885 886 int port = adapter->portnum; 887 888 if (!NX_IS_REVISION_P2(adapter->ahw.revision_id)) { 889 if (!test_and_clear_bit(__NX_FW_ATTACHED, &adapter->state)) 890 goto done; 891 892 nx_fw_cmd_destroy_rx_ctx(adapter); 893 nx_fw_cmd_destroy_tx_ctx(adapter); 894 } else { 895 netxen_api_lock(adapter); 896 NXWR32(adapter, CRB_CTX_SIGNATURE_REG(port), 897 NETXEN_CTX_D3_RESET | port); 898 netxen_api_unlock(adapter); 899 } 900 901 /* Allow dma queues to drain after context reset */ 902 msleep(20); 903 904 done: 905 recv_ctx = &adapter->recv_ctx; 906 907 if (recv_ctx->hwctx != NULL) { 908 pci_free_consistent(adapter->pdev, 909 sizeof(struct netxen_ring_ctx) + 910 sizeof(uint32_t), 911 recv_ctx->hwctx, 912 recv_ctx->phys_addr); 913 recv_ctx->hwctx = NULL; 914 } 915 916 tx_ring = adapter->tx_ring; 917 if (tx_ring->desc_head != NULL) { 918 pci_free_consistent(adapter->pdev, 919 TX_DESC_RINGSIZE(tx_ring), 920 tx_ring->desc_head, tx_ring->phys_addr); 921 tx_ring->desc_head = NULL; 922 } 923 924 for (ring = 0; ring < adapter->max_rds_rings; ring++) { 925 rds_ring = &recv_ctx->rds_rings[ring]; 926 927 if (rds_ring->desc_head != NULL) { 928 pci_free_consistent(adapter->pdev, 929 RCV_DESC_RINGSIZE(rds_ring), 930 rds_ring->desc_head, 931 rds_ring->phys_addr); 932 rds_ring->desc_head = NULL; 933 } 934 } 935 936 for (ring = 0; ring < adapter->max_sds_rings; ring++) { 937 sds_ring = &recv_ctx->sds_rings[ring]; 938 939 if (sds_ring->desc_head != NULL) { 940 pci_free_consistent(adapter->pdev, 941 STATUS_DESC_RINGSIZE(sds_ring), 942 sds_ring->desc_head, 943 sds_ring->phys_addr); 944 sds_ring->desc_head = NULL; 945 } 946 } 947 } 948 949