diff options
Diffstat (limited to 'drivers/net/qlcnic/qlcnic_ctx.c')
-rw-r--r-- | drivers/net/qlcnic/qlcnic_ctx.c | 513 |
1 files changed, 494 insertions, 19 deletions
diff --git a/drivers/net/qlcnic/qlcnic_ctx.c b/drivers/net/qlcnic/qlcnic_ctx.c index c2c1f5cc16c6..1e1dc58cddca 100644 --- a/drivers/net/qlcnic/qlcnic_ctx.c +++ b/drivers/net/qlcnic/qlcnic_ctx.c | |||
@@ -88,12 +88,12 @@ qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu) | |||
88 | 88 | ||
89 | if (recv_ctx->state == QLCNIC_HOST_CTX_STATE_ACTIVE) { | 89 | if (recv_ctx->state == QLCNIC_HOST_CTX_STATE_ACTIVE) { |
90 | if (qlcnic_issue_cmd(adapter, | 90 | if (qlcnic_issue_cmd(adapter, |
91 | adapter->ahw.pci_func, | 91 | adapter->ahw.pci_func, |
92 | QLCHAL_VERSION, | 92 | adapter->fw_hal_version, |
93 | recv_ctx->context_id, | 93 | recv_ctx->context_id, |
94 | mtu, | 94 | mtu, |
95 | 0, | 95 | 0, |
96 | QLCNIC_CDRP_CMD_SET_MTU)) { | 96 | QLCNIC_CDRP_CMD_SET_MTU)) { |
97 | 97 | ||
98 | dev_err(&adapter->pdev->dev, "Failed to set mtu\n"); | 98 | dev_err(&adapter->pdev->dev, "Failed to set mtu\n"); |
99 | return -EIO; | 99 | return -EIO; |
@@ -121,7 +121,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
121 | 121 | ||
122 | int i, nrds_rings, nsds_rings; | 122 | int i, nrds_rings, nsds_rings; |
123 | size_t rq_size, rsp_size; | 123 | size_t rq_size, rsp_size; |
124 | u32 cap, reg, val; | 124 | u32 cap, reg, val, reg2; |
125 | int err; | 125 | int err; |
126 | 126 | ||
127 | struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; | 127 | struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; |
@@ -197,7 +197,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
197 | phys_addr = hostrq_phys_addr; | 197 | phys_addr = hostrq_phys_addr; |
198 | err = qlcnic_issue_cmd(adapter, | 198 | err = qlcnic_issue_cmd(adapter, |
199 | adapter->ahw.pci_func, | 199 | adapter->ahw.pci_func, |
200 | QLCHAL_VERSION, | 200 | adapter->fw_hal_version, |
201 | (u32)(phys_addr >> 32), | 201 | (u32)(phys_addr >> 32), |
202 | (u32)(phys_addr & 0xffffffff), | 202 | (u32)(phys_addr & 0xffffffff), |
203 | rq_size, | 203 | rq_size, |
@@ -216,8 +216,12 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
216 | rds_ring = &recv_ctx->rds_rings[i]; | 216 | rds_ring = &recv_ctx->rds_rings[i]; |
217 | 217 | ||
218 | reg = le32_to_cpu(prsp_rds[i].host_producer_crb); | 218 | reg = le32_to_cpu(prsp_rds[i].host_producer_crb); |
219 | rds_ring->crb_rcv_producer = qlcnic_get_ioaddr(adapter, | 219 | if (adapter->fw_hal_version == QLCNIC_FW_BASE) |
220 | rds_ring->crb_rcv_producer = qlcnic_get_ioaddr(adapter, | ||
220 | QLCNIC_REG(reg - 0x200)); | 221 | QLCNIC_REG(reg - 0x200)); |
222 | else | ||
223 | rds_ring->crb_rcv_producer = adapter->ahw.pci_base0 + | ||
224 | reg; | ||
221 | } | 225 | } |
222 | 226 | ||
223 | prsp_sds = ((struct qlcnic_cardrsp_sds_ring *) | 227 | prsp_sds = ((struct qlcnic_cardrsp_sds_ring *) |
@@ -227,12 +231,18 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
227 | sds_ring = &recv_ctx->sds_rings[i]; | 231 | sds_ring = &recv_ctx->sds_rings[i]; |
228 | 232 | ||
229 | reg = le32_to_cpu(prsp_sds[i].host_consumer_crb); | 233 | reg = le32_to_cpu(prsp_sds[i].host_consumer_crb); |
230 | sds_ring->crb_sts_consumer = qlcnic_get_ioaddr(adapter, | 234 | reg2 = le32_to_cpu(prsp_sds[i].interrupt_crb); |
231 | QLCNIC_REG(reg - 0x200)); | ||
232 | 235 | ||
233 | reg = le32_to_cpu(prsp_sds[i].interrupt_crb); | 236 | if (adapter->fw_hal_version == QLCNIC_FW_BASE) { |
234 | sds_ring->crb_intr_mask = qlcnic_get_ioaddr(adapter, | 237 | sds_ring->crb_sts_consumer = qlcnic_get_ioaddr(adapter, |
235 | QLCNIC_REG(reg - 0x200)); | 238 | QLCNIC_REG(reg - 0x200)); |
239 | sds_ring->crb_intr_mask = qlcnic_get_ioaddr(adapter, | ||
240 | QLCNIC_REG(reg2 - 0x200)); | ||
241 | } else { | ||
242 | sds_ring->crb_sts_consumer = adapter->ahw.pci_base0 + | ||
243 | reg; | ||
244 | sds_ring->crb_intr_mask = adapter->ahw.pci_base0 + reg2; | ||
245 | } | ||
236 | } | 246 | } |
237 | 247 | ||
238 | recv_ctx->state = le32_to_cpu(prsp->host_ctx_state); | 248 | recv_ctx->state = le32_to_cpu(prsp->host_ctx_state); |
@@ -253,7 +263,7 @@ qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter) | |||
253 | 263 | ||
254 | if (qlcnic_issue_cmd(adapter, | 264 | if (qlcnic_issue_cmd(adapter, |
255 | adapter->ahw.pci_func, | 265 | adapter->ahw.pci_func, |
256 | QLCHAL_VERSION, | 266 | adapter->fw_hal_version, |
257 | recv_ctx->context_id, | 267 | recv_ctx->context_id, |
258 | QLCNIC_DESTROY_CTX_RESET, | 268 | QLCNIC_DESTROY_CTX_RESET, |
259 | 0, | 269 | 0, |
@@ -319,7 +329,7 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) | |||
319 | phys_addr = rq_phys_addr; | 329 | phys_addr = rq_phys_addr; |
320 | err = qlcnic_issue_cmd(adapter, | 330 | err = qlcnic_issue_cmd(adapter, |
321 | adapter->ahw.pci_func, | 331 | adapter->ahw.pci_func, |
322 | QLCHAL_VERSION, | 332 | adapter->fw_hal_version, |
323 | (u32)(phys_addr >> 32), | 333 | (u32)(phys_addr >> 32), |
324 | ((u32)phys_addr & 0xffffffff), | 334 | ((u32)phys_addr & 0xffffffff), |
325 | rq_size, | 335 | rq_size, |
@@ -327,8 +337,12 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) | |||
327 | 337 | ||
328 | if (err == QLCNIC_RCODE_SUCCESS) { | 338 | if (err == QLCNIC_RCODE_SUCCESS) { |
329 | temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); | 339 | temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); |
330 | tx_ring->crb_cmd_producer = qlcnic_get_ioaddr(adapter, | 340 | if (adapter->fw_hal_version == QLCNIC_FW_BASE) |
341 | tx_ring->crb_cmd_producer = qlcnic_get_ioaddr(adapter, | ||
331 | QLCNIC_REG(temp - 0x200)); | 342 | QLCNIC_REG(temp - 0x200)); |
343 | else | ||
344 | tx_ring->crb_cmd_producer = adapter->ahw.pci_base0 + | ||
345 | temp; | ||
332 | 346 | ||
333 | adapter->tx_context_id = | 347 | adapter->tx_context_id = |
334 | le16_to_cpu(prsp->context_id); | 348 | le16_to_cpu(prsp->context_id); |
@@ -351,7 +365,7 @@ qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter) | |||
351 | { | 365 | { |
352 | if (qlcnic_issue_cmd(adapter, | 366 | if (qlcnic_issue_cmd(adapter, |
353 | adapter->ahw.pci_func, | 367 | adapter->ahw.pci_func, |
354 | QLCHAL_VERSION, | 368 | adapter->fw_hal_version, |
355 | adapter->tx_context_id, | 369 | adapter->tx_context_id, |
356 | QLCNIC_DESTROY_CTX_RESET, | 370 | QLCNIC_DESTROY_CTX_RESET, |
357 | 0, | 371 | 0, |
@@ -368,7 +382,7 @@ qlcnic_fw_cmd_query_phy(struct qlcnic_adapter *adapter, u32 reg, u32 *val) | |||
368 | 382 | ||
369 | if (qlcnic_issue_cmd(adapter, | 383 | if (qlcnic_issue_cmd(adapter, |
370 | adapter->ahw.pci_func, | 384 | adapter->ahw.pci_func, |
371 | QLCHAL_VERSION, | 385 | adapter->fw_hal_version, |
372 | reg, | 386 | reg, |
373 | 0, | 387 | 0, |
374 | 0, | 388 | 0, |
@@ -385,7 +399,7 @@ qlcnic_fw_cmd_set_phy(struct qlcnic_adapter *adapter, u32 reg, u32 val) | |||
385 | { | 399 | { |
386 | return qlcnic_issue_cmd(adapter, | 400 | return qlcnic_issue_cmd(adapter, |
387 | adapter->ahw.pci_func, | 401 | adapter->ahw.pci_func, |
388 | QLCHAL_VERSION, | 402 | adapter->fw_hal_version, |
389 | reg, | 403 | reg, |
390 | val, | 404 | val, |
391 | 0, | 405 | 0, |
@@ -533,3 +547,464 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) | |||
533 | } | 547 | } |
534 | } | 548 | } |
535 | 549 | ||
550 | /* Set MAC address of a NIC partition */ | ||
551 | int qlcnic_set_mac_address(struct qlcnic_adapter *adapter, u8* mac) | ||
552 | { | ||
553 | int err = 0; | ||
554 | u32 arg1, arg2, arg3; | ||
555 | |||
556 | arg1 = adapter->ahw.pci_func | BIT_9; | ||
557 | arg2 = mac[0] | (mac[1] << 8) | (mac[2] << 16) | (mac[3] << 24); | ||
558 | arg3 = mac[4] | (mac[5] << 16); | ||
559 | |||
560 | err = qlcnic_issue_cmd(adapter, | ||
561 | adapter->ahw.pci_func, | ||
562 | adapter->fw_hal_version, | ||
563 | arg1, | ||
564 | arg2, | ||
565 | arg3, | ||
566 | QLCNIC_CDRP_CMD_MAC_ADDRESS); | ||
567 | |||
568 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
569 | dev_err(&adapter->pdev->dev, | ||
570 | "Failed to set mac address%d\n", err); | ||
571 | err = -EIO; | ||
572 | } | ||
573 | |||
574 | return err; | ||
575 | } | ||
576 | |||
577 | /* Get MAC address of a NIC partition */ | ||
578 | int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac) | ||
579 | { | ||
580 | int err; | ||
581 | u32 arg1; | ||
582 | |||
583 | arg1 = adapter->ahw.pci_func | BIT_8; | ||
584 | err = qlcnic_issue_cmd(adapter, | ||
585 | adapter->ahw.pci_func, | ||
586 | adapter->fw_hal_version, | ||
587 | arg1, | ||
588 | 0, | ||
589 | 0, | ||
590 | QLCNIC_CDRP_CMD_MAC_ADDRESS); | ||
591 | |||
592 | if (err == QLCNIC_RCODE_SUCCESS) { | ||
593 | qlcnic_fetch_mac(adapter, QLCNIC_ARG1_CRB_OFFSET, | ||
594 | QLCNIC_ARG2_CRB_OFFSET, 0, mac); | ||
595 | dev_info(&adapter->pdev->dev, "MAC address: %pM\n", mac); | ||
596 | } else { | ||
597 | dev_err(&adapter->pdev->dev, | ||
598 | "Failed to get mac address%d\n", err); | ||
599 | err = -EIO; | ||
600 | } | ||
601 | |||
602 | return err; | ||
603 | } | ||
604 | |||
605 | /* Get info of a NIC partition */ | ||
606 | int qlcnic_get_nic_info(struct qlcnic_adapter *adapter, u8 func_id) | ||
607 | { | ||
608 | int err; | ||
609 | dma_addr_t nic_dma_t; | ||
610 | struct qlcnic_info *nic_info; | ||
611 | void *nic_info_addr; | ||
612 | size_t nic_size = sizeof(struct qlcnic_info); | ||
613 | |||
614 | nic_info_addr = pci_alloc_consistent(adapter->pdev, | ||
615 | nic_size, &nic_dma_t); | ||
616 | if (!nic_info_addr) | ||
617 | return -ENOMEM; | ||
618 | memset(nic_info_addr, 0, nic_size); | ||
619 | |||
620 | nic_info = (struct qlcnic_info *) nic_info_addr; | ||
621 | err = qlcnic_issue_cmd(adapter, | ||
622 | adapter->ahw.pci_func, | ||
623 | adapter->fw_hal_version, | ||
624 | MSD(nic_dma_t), | ||
625 | LSD(nic_dma_t), | ||
626 | (func_id << 16 | nic_size), | ||
627 | QLCNIC_CDRP_CMD_GET_NIC_INFO); | ||
628 | |||
629 | if (err == QLCNIC_RCODE_SUCCESS) { | ||
630 | adapter->physical_port = le16_to_cpu(nic_info->phys_port); | ||
631 | adapter->switch_mode = le16_to_cpu(nic_info->switch_mode); | ||
632 | adapter->max_tx_ques = le16_to_cpu(nic_info->max_tx_ques); | ||
633 | adapter->max_rx_ques = le16_to_cpu(nic_info->max_rx_ques); | ||
634 | adapter->min_tx_bw = le16_to_cpu(nic_info->min_tx_bw); | ||
635 | adapter->max_tx_bw = le16_to_cpu(nic_info->max_tx_bw); | ||
636 | adapter->max_mtu = le16_to_cpu(nic_info->max_mtu); | ||
637 | adapter->capabilities = le32_to_cpu(nic_info->capabilities); | ||
638 | adapter->max_mac_filters = nic_info->max_mac_filters; | ||
639 | |||
640 | dev_info(&adapter->pdev->dev, | ||
641 | "phy port: %d switch_mode: %d,\n" | ||
642 | "\tmax_tx_q: %d max_rx_q: %d min_tx_bw: 0x%x,\n" | ||
643 | "\tmax_tx_bw: 0x%x max_mtu:0x%x, capabilities: 0x%x\n", | ||
644 | adapter->physical_port, adapter->switch_mode, | ||
645 | adapter->max_tx_ques, adapter->max_rx_ques, | ||
646 | adapter->min_tx_bw, adapter->max_tx_bw, | ||
647 | adapter->max_mtu, adapter->capabilities); | ||
648 | } else { | ||
649 | dev_err(&adapter->pdev->dev, | ||
650 | "Failed to get nic info%d\n", err); | ||
651 | err = -EIO; | ||
652 | } | ||
653 | |||
654 | pci_free_consistent(adapter->pdev, nic_size, nic_info_addr, nic_dma_t); | ||
655 | return err; | ||
656 | } | ||
657 | |||
658 | /* Configure a NIC partition */ | ||
659 | int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic) | ||
660 | { | ||
661 | int err = -EIO; | ||
662 | u32 func_state; | ||
663 | dma_addr_t nic_dma_t; | ||
664 | void *nic_info_addr; | ||
665 | struct qlcnic_info *nic_info; | ||
666 | size_t nic_size = sizeof(struct qlcnic_info); | ||
667 | |||
668 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
669 | return err; | ||
670 | |||
671 | if (qlcnic_api_lock(adapter)) | ||
672 | return err; | ||
673 | |||
674 | func_state = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT); | ||
675 | if (QLC_DEV_CHECK_ACTIVE(func_state, nic->pci_func)) { | ||
676 | qlcnic_api_unlock(adapter); | ||
677 | return err; | ||
678 | } | ||
679 | |||
680 | qlcnic_api_unlock(adapter); | ||
681 | |||
682 | nic_info_addr = pci_alloc_consistent(adapter->pdev, nic_size, | ||
683 | &nic_dma_t); | ||
684 | if (!nic_info_addr) | ||
685 | return -ENOMEM; | ||
686 | |||
687 | memset(nic_info_addr, 0, nic_size); | ||
688 | nic_info = (struct qlcnic_info *)nic_info_addr; | ||
689 | |||
690 | nic_info->pci_func = cpu_to_le16(nic->pci_func); | ||
691 | nic_info->op_mode = cpu_to_le16(nic->op_mode); | ||
692 | nic_info->phys_port = cpu_to_le16(nic->phys_port); | ||
693 | nic_info->switch_mode = cpu_to_le16(nic->switch_mode); | ||
694 | nic_info->capabilities = cpu_to_le32(nic->capabilities); | ||
695 | nic_info->max_mac_filters = nic->max_mac_filters; | ||
696 | nic_info->max_tx_ques = cpu_to_le16(nic->max_tx_ques); | ||
697 | nic_info->max_rx_ques = cpu_to_le16(nic->max_rx_ques); | ||
698 | nic_info->min_tx_bw = cpu_to_le16(nic->min_tx_bw); | ||
699 | nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw); | ||
700 | |||
701 | err = qlcnic_issue_cmd(adapter, | ||
702 | adapter->ahw.pci_func, | ||
703 | adapter->fw_hal_version, | ||
704 | MSD(nic_dma_t), | ||
705 | LSD(nic_dma_t), | ||
706 | nic_size, | ||
707 | QLCNIC_CDRP_CMD_SET_NIC_INFO); | ||
708 | |||
709 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
710 | dev_err(&adapter->pdev->dev, | ||
711 | "Failed to set nic info%d\n", err); | ||
712 | err = -EIO; | ||
713 | } | ||
714 | |||
715 | pci_free_consistent(adapter->pdev, nic_size, nic_info_addr, nic_dma_t); | ||
716 | return err; | ||
717 | } | ||
718 | |||
719 | /* Get PCI Info of a partition */ | ||
720 | int qlcnic_get_pci_info(struct qlcnic_adapter *adapter) | ||
721 | { | ||
722 | int err = 0, i; | ||
723 | dma_addr_t pci_info_dma_t; | ||
724 | struct qlcnic_pci_info *npar; | ||
725 | void *pci_info_addr; | ||
726 | size_t npar_size = sizeof(struct qlcnic_pci_info); | ||
727 | size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC; | ||
728 | |||
729 | pci_info_addr = pci_alloc_consistent(adapter->pdev, pci_size, | ||
730 | &pci_info_dma_t); | ||
731 | if (!pci_info_addr) | ||
732 | return -ENOMEM; | ||
733 | memset(pci_info_addr, 0, pci_size); | ||
734 | |||
735 | if (!adapter->npars) | ||
736 | adapter->npars = kzalloc(pci_size, GFP_KERNEL); | ||
737 | if (!adapter->npars) { | ||
738 | err = -ENOMEM; | ||
739 | goto err_npar; | ||
740 | } | ||
741 | |||
742 | if (!adapter->eswitch) | ||
743 | adapter->eswitch = kzalloc(sizeof(struct qlcnic_eswitch) * | ||
744 | QLCNIC_NIU_MAX_XG_PORTS, GFP_KERNEL); | ||
745 | if (!adapter->eswitch) { | ||
746 | err = -ENOMEM; | ||
747 | goto err_eswitch; | ||
748 | } | ||
749 | |||
750 | npar = (struct qlcnic_pci_info *) pci_info_addr; | ||
751 | err = qlcnic_issue_cmd(adapter, | ||
752 | adapter->ahw.pci_func, | ||
753 | adapter->fw_hal_version, | ||
754 | MSD(pci_info_dma_t), | ||
755 | LSD(pci_info_dma_t), | ||
756 | pci_size, | ||
757 | QLCNIC_CDRP_CMD_GET_PCI_INFO); | ||
758 | |||
759 | if (err == QLCNIC_RCODE_SUCCESS) { | ||
760 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++, npar++) { | ||
761 | adapter->npars[i].id = le32_to_cpu(npar->id); | ||
762 | adapter->npars[i].active = le32_to_cpu(npar->active); | ||
763 | adapter->npars[i].type = le32_to_cpu(npar->type); | ||
764 | adapter->npars[i].default_port = | ||
765 | le32_to_cpu(npar->default_port); | ||
766 | adapter->npars[i].tx_min_bw = | ||
767 | le32_to_cpu(npar->tx_min_bw); | ||
768 | adapter->npars[i].tx_max_bw = | ||
769 | le32_to_cpu(npar->tx_max_bw); | ||
770 | memcpy(adapter->npars[i].mac, npar->mac, ETH_ALEN); | ||
771 | } | ||
772 | } else { | ||
773 | dev_err(&adapter->pdev->dev, | ||
774 | "Failed to get PCI Info%d\n", err); | ||
775 | kfree(adapter->npars); | ||
776 | err = -EIO; | ||
777 | } | ||
778 | goto err_npar; | ||
779 | |||
780 | err_eswitch: | ||
781 | kfree(adapter->npars); | ||
782 | adapter->npars = NULL; | ||
783 | |||
784 | err_npar: | ||
785 | pci_free_consistent(adapter->pdev, pci_size, pci_info_addr, | ||
786 | pci_info_dma_t); | ||
787 | return err; | ||
788 | } | ||
789 | |||
790 | /* Reset a NIC partition */ | ||
791 | |||
792 | int qlcnic_reset_partition(struct qlcnic_adapter *adapter, u8 func_no) | ||
793 | { | ||
794 | int err = -EIO; | ||
795 | |||
796 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
797 | return err; | ||
798 | |||
799 | err = qlcnic_issue_cmd(adapter, | ||
800 | adapter->ahw.pci_func, | ||
801 | adapter->fw_hal_version, | ||
802 | func_no, | ||
803 | 0, | ||
804 | 0, | ||
805 | QLCNIC_CDRP_CMD_RESET_NPAR); | ||
806 | |||
807 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
808 | dev_err(&adapter->pdev->dev, | ||
809 | "Failed to issue reset partition%d\n", err); | ||
810 | err = -EIO; | ||
811 | } | ||
812 | |||
813 | return err; | ||
814 | } | ||
815 | |||
816 | /* Get eSwitch Capabilities */ | ||
817 | int qlcnic_get_eswitch_capabilities(struct qlcnic_adapter *adapter, u8 port, | ||
818 | struct qlcnic_eswitch *eswitch) | ||
819 | { | ||
820 | int err = -EIO; | ||
821 | u32 arg1, arg2; | ||
822 | |||
823 | if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) | ||
824 | return err; | ||
825 | |||
826 | err = qlcnic_issue_cmd(adapter, | ||
827 | adapter->ahw.pci_func, | ||
828 | adapter->fw_hal_version, | ||
829 | port, | ||
830 | 0, | ||
831 | 0, | ||
832 | QLCNIC_CDRP_CMD_GET_ESWITCH_CAPABILITY); | ||
833 | |||
834 | if (err == QLCNIC_RCODE_SUCCESS) { | ||
835 | arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); | ||
836 | arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET); | ||
837 | |||
838 | eswitch->port = arg1 & 0xf; | ||
839 | eswitch->active_vports = LSB(arg2); | ||
840 | eswitch->max_ucast_filters = MSB(arg2); | ||
841 | eswitch->max_active_vlans = LSB(MSW(arg2)); | ||
842 | if (arg1 & BIT_6) | ||
843 | eswitch->flags |= QLCNIC_SWITCH_VLAN_FILTERING; | ||
844 | if (arg1 & BIT_7) | ||
845 | eswitch->flags |= QLCNIC_SWITCH_PROMISC_MODE; | ||
846 | if (arg1 & BIT_8) | ||
847 | eswitch->flags |= QLCNIC_SWITCH_PORT_MIRRORING; | ||
848 | } else { | ||
849 | dev_err(&adapter->pdev->dev, | ||
850 | "Failed to get eswitch capabilities%d\n", err); | ||
851 | } | ||
852 | |||
853 | return err; | ||
854 | } | ||
855 | |||
856 | /* Get current status of eswitch */ | ||
857 | int qlcnic_get_eswitch_status(struct qlcnic_adapter *adapter, u8 port, | ||
858 | struct qlcnic_eswitch *eswitch) | ||
859 | { | ||
860 | int err = -EIO; | ||
861 | u32 arg1, arg2; | ||
862 | |||
863 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
864 | return err; | ||
865 | |||
866 | err = qlcnic_issue_cmd(adapter, | ||
867 | adapter->ahw.pci_func, | ||
868 | adapter->fw_hal_version, | ||
869 | port, | ||
870 | 0, | ||
871 | 0, | ||
872 | QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS); | ||
873 | |||
874 | if (err == QLCNIC_RCODE_SUCCESS) { | ||
875 | arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); | ||
876 | arg2 = QLCRD32(adapter, QLCNIC_ARG2_CRB_OFFSET); | ||
877 | |||
878 | eswitch->port = arg1 & 0xf; | ||
879 | eswitch->active_vports = LSB(arg2); | ||
880 | eswitch->active_ucast_filters = MSB(arg2); | ||
881 | eswitch->active_vlans = LSB(MSW(arg2)); | ||
882 | if (arg1 & BIT_6) | ||
883 | eswitch->flags |= QLCNIC_SWITCH_VLAN_FILTERING; | ||
884 | if (arg1 & BIT_8) | ||
885 | eswitch->flags |= QLCNIC_SWITCH_PORT_MIRRORING; | ||
886 | |||
887 | } else { | ||
888 | dev_err(&adapter->pdev->dev, | ||
889 | "Failed to get eswitch status%d\n", err); | ||
890 | } | ||
891 | |||
892 | return err; | ||
893 | } | ||
894 | |||
895 | /* Enable/Disable eSwitch */ | ||
896 | int qlcnic_toggle_eswitch(struct qlcnic_adapter *adapter, u8 id, u8 enable) | ||
897 | { | ||
898 | int err = -EIO; | ||
899 | u32 arg1, arg2; | ||
900 | struct qlcnic_eswitch *eswitch; | ||
901 | |||
902 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
903 | return err; | ||
904 | |||
905 | eswitch = &adapter->eswitch[id]; | ||
906 | if (!eswitch) | ||
907 | return err; | ||
908 | |||
909 | arg1 = eswitch->port | (enable ? BIT_4 : 0); | ||
910 | arg2 = eswitch->active_vports | (eswitch->max_ucast_filters << 8) | | ||
911 | (eswitch->max_active_vlans << 16); | ||
912 | err = qlcnic_issue_cmd(adapter, | ||
913 | adapter->ahw.pci_func, | ||
914 | adapter->fw_hal_version, | ||
915 | arg1, | ||
916 | arg2, | ||
917 | 0, | ||
918 | QLCNIC_CDRP_CMD_TOGGLE_ESWITCH); | ||
919 | |||
920 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
921 | dev_err(&adapter->pdev->dev, | ||
922 | "Failed to enable eswitch%d\n", eswitch->port); | ||
923 | eswitch->flags &= ~QLCNIC_SWITCH_ENABLE; | ||
924 | err = -EIO; | ||
925 | } else { | ||
926 | eswitch->flags |= QLCNIC_SWITCH_ENABLE; | ||
927 | dev_info(&adapter->pdev->dev, | ||
928 | "Enabled eSwitch for port %d\n", eswitch->port); | ||
929 | } | ||
930 | |||
931 | return err; | ||
932 | } | ||
933 | |||
934 | /* Configure eSwitch for port mirroring */ | ||
935 | int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id, | ||
936 | u8 enable_mirroring, u8 pci_func) | ||
937 | { | ||
938 | int err = -EIO; | ||
939 | u32 arg1; | ||
940 | |||
941 | if (adapter->op_mode != QLCNIC_MGMT_FUNC || | ||
942 | !(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE)) | ||
943 | return err; | ||
944 | |||
945 | arg1 = id | (enable_mirroring ? BIT_4 : 0); | ||
946 | arg1 |= pci_func << 8; | ||
947 | |||
948 | err = qlcnic_issue_cmd(adapter, | ||
949 | adapter->ahw.pci_func, | ||
950 | adapter->fw_hal_version, | ||
951 | arg1, | ||
952 | 0, | ||
953 | 0, | ||
954 | QLCNIC_CDRP_CMD_SET_PORTMIRRORING); | ||
955 | |||
956 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
957 | dev_err(&adapter->pdev->dev, | ||
958 | "Failed to configure port mirroring%d on eswitch:%d\n", | ||
959 | pci_func, id); | ||
960 | } else { | ||
961 | dev_info(&adapter->pdev->dev, | ||
962 | "Configured eSwitch %d for port mirroring:%d\n", | ||
963 | id, pci_func); | ||
964 | } | ||
965 | |||
966 | return err; | ||
967 | } | ||
968 | |||
969 | /* Configure eSwitch port */ | ||
970 | int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, u8 id, | ||
971 | int vlan_tagging, u8 discard_tagged, u8 promsc_mode, | ||
972 | u8 mac_learn, u8 pci_func, u16 vlan_id) | ||
973 | { | ||
974 | int err = -EIO; | ||
975 | u32 arg1; | ||
976 | struct qlcnic_eswitch *eswitch; | ||
977 | |||
978 | if (adapter->op_mode != QLCNIC_MGMT_FUNC) | ||
979 | return err; | ||
980 | |||
981 | eswitch = &adapter->eswitch[id]; | ||
982 | if (!(eswitch->flags & QLCNIC_SWITCH_ENABLE)) | ||
983 | return err; | ||
984 | |||
985 | arg1 = eswitch->port | (discard_tagged ? BIT_4 : 0); | ||
986 | arg1 |= (promsc_mode ? BIT_6 : 0) | (mac_learn ? BIT_7 : 0); | ||
987 | arg1 |= pci_func << 8; | ||
988 | if (vlan_tagging) | ||
989 | arg1 |= BIT_5 | (vlan_id << 16); | ||
990 | |||
991 | err = qlcnic_issue_cmd(adapter, | ||
992 | adapter->ahw.pci_func, | ||
993 | adapter->fw_hal_version, | ||
994 | arg1, | ||
995 | 0, | ||
996 | 0, | ||
997 | QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH); | ||
998 | |||
999 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
1000 | dev_err(&adapter->pdev->dev, | ||
1001 | "Failed to configure eswitch port%d\n", eswitch->port); | ||
1002 | eswitch->flags |= QLCNIC_SWITCH_ENABLE; | ||
1003 | } else { | ||
1004 | eswitch->flags &= ~QLCNIC_SWITCH_ENABLE; | ||
1005 | dev_info(&adapter->pdev->dev, | ||
1006 | "Configured eSwitch for port %d\n", eswitch->port); | ||
1007 | } | ||
1008 | |||
1009 | return err; | ||
1010 | } | ||