diff options
author | Dmitry Kravkov <dmitry@broadcom.com> | 2010-10-05 23:23:26 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-10-06 17:10:35 -0400 |
commit | 523224a3b3cd407ce4e6731a087194e13a90db18 (patch) | |
tree | bb0fda289682e4259c401b8a5763ba4cc4d41659 /drivers/net/bnx2x/bnx2x_init_ops.h | |
parent | 0c5b77152e736d23a23eb2546eab323e27a37f52 (diff) |
bnx2x, cnic, bnx2i: use new FW/HSI
This is the new FW HSI blob and the relevant definitions without logic changes.
It also included code adaptation for new HSI. New features are not enabled.
New FW/HSI includes:
- Support for 57712 HW
- Future support for VF (not used)
- Improvements in FW interrupts scheme
- FW FCoE hooks (stubs for future usage)
Signed-off-by: Dmitry Kravkov <dmitry@broadcom.com>
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bnx2x/bnx2x_init_ops.h')
-rw-r--r-- | drivers/net/bnx2x/bnx2x_init_ops.h | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/drivers/net/bnx2x/bnx2x_init_ops.h b/drivers/net/bnx2x/bnx2x_init_ops.h index 2b1363a6fe7..aae7fea0062 100644 --- a/drivers/net/bnx2x/bnx2x_init_ops.h +++ b/drivers/net/bnx2x/bnx2x_init_ops.h | |||
@@ -151,6 +151,15 @@ static void bnx2x_init_wr_wb(struct bnx2x *bp, u32 addr, const u32 *data, | |||
151 | bnx2x_init_ind_wr(bp, addr, data, len); | 151 | bnx2x_init_ind_wr(bp, addr, data, len); |
152 | } | 152 | } |
153 | 153 | ||
154 | static void bnx2x_wr_64(struct bnx2x *bp, u32 reg, u32 val_lo, u32 val_hi) | ||
155 | { | ||
156 | u32 wb_write[2]; | ||
157 | |||
158 | wb_write[0] = val_lo; | ||
159 | wb_write[1] = val_hi; | ||
160 | REG_WR_DMAE_LEN(bp, reg, wb_write, 2); | ||
161 | } | ||
162 | |||
154 | static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, u32 len, u32 blob_off) | 163 | static void bnx2x_init_wr_zp(struct bnx2x *bp, u32 addr, u32 len, u32 blob_off) |
155 | { | 164 | { |
156 | const u8 *data = NULL; | 165 | const u8 *data = NULL; |
@@ -503,4 +512,333 @@ static void bnx2x_init_pxp_arb(struct bnx2x *bp, int r_order, int w_order) | |||
503 | } | 512 | } |
504 | } | 513 | } |
505 | 514 | ||
515 | /**************************************************************************** | ||
516 | * ILT management | ||
517 | ****************************************************************************/ | ||
518 | /* | ||
519 | * This codes hides the low level HW interaction for ILT management and | ||
520 | * configuration. The API consists of a shadow ILT table which is set by the | ||
521 | * driver and a set of routines to use it to configure the HW. | ||
522 | * | ||
523 | */ | ||
524 | |||
525 | /* ILT HW init operations */ | ||
526 | |||
527 | /* ILT memory management operations */ | ||
528 | #define ILT_MEMOP_ALLOC 0 | ||
529 | #define ILT_MEMOP_FREE 1 | ||
530 | |||
531 | /* the phys address is shifted right 12 bits and has an added | ||
532 | * 1=valid bit added to the 53rd bit | ||
533 | * then since this is a wide register(TM) | ||
534 | * we split it into two 32 bit writes | ||
535 | */ | ||
536 | #define ILT_ADDR1(x) ((u32)(((u64)x >> 12) & 0xFFFFFFFF)) | ||
537 | #define ILT_ADDR2(x) ((u32)((1 << 20) | ((u64)x >> 44))) | ||
538 | #define ILT_RANGE(f, l) (((l) << 10) | f) | ||
539 | |||
540 | static int bnx2x_ilt_line_mem_op(struct bnx2x *bp, struct ilt_line *line, | ||
541 | u32 size, u8 memop) | ||
542 | { | ||
543 | if (memop == ILT_MEMOP_FREE) { | ||
544 | BNX2X_ILT_FREE(line->page, line->page_mapping, line->size); | ||
545 | return 0; | ||
546 | } | ||
547 | BNX2X_ILT_ZALLOC(line->page, &line->page_mapping, size); | ||
548 | if (!line->page) | ||
549 | return -1; | ||
550 | line->size = size; | ||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | |||
555 | static int bnx2x_ilt_client_mem_op(struct bnx2x *bp, int cli_num, u8 memop) | ||
556 | { | ||
557 | int i, rc; | ||
558 | struct bnx2x_ilt *ilt = BP_ILT(bp); | ||
559 | struct ilt_client_info *ilt_cli = &ilt->clients[cli_num]; | ||
560 | |||
561 | if (!ilt || !ilt->lines) | ||
562 | return -1; | ||
563 | |||
564 | if (ilt_cli->flags & (ILT_CLIENT_SKIP_INIT | ILT_CLIENT_SKIP_MEM)) | ||
565 | return 0; | ||
566 | |||
567 | for (rc = 0, i = ilt_cli->start; i <= ilt_cli->end && !rc; i++) { | ||
568 | rc = bnx2x_ilt_line_mem_op(bp, &ilt->lines[i], | ||
569 | ilt_cli->page_size, memop); | ||
570 | } | ||
571 | return rc; | ||
572 | } | ||
573 | |||
574 | int bnx2x_ilt_mem_op(struct bnx2x *bp, u8 memop) | ||
575 | { | ||
576 | int rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_CDU, memop); | ||
577 | if (!rc) | ||
578 | rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_QM, memop); | ||
579 | if (!rc) | ||
580 | rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_SRC, memop); | ||
581 | if (!rc) | ||
582 | rc = bnx2x_ilt_client_mem_op(bp, ILT_CLIENT_TM, memop); | ||
583 | |||
584 | return rc; | ||
585 | } | ||
586 | |||
587 | static void bnx2x_ilt_line_wr(struct bnx2x *bp, int abs_idx, | ||
588 | dma_addr_t page_mapping) | ||
589 | { | ||
590 | u32 reg; | ||
591 | |||
592 | if (CHIP_IS_E1(bp)) | ||
593 | reg = PXP2_REG_RQ_ONCHIP_AT + abs_idx*8; | ||
594 | else | ||
595 | reg = PXP2_REG_RQ_ONCHIP_AT_B0 + abs_idx*8; | ||
596 | |||
597 | bnx2x_wr_64(bp, reg, ILT_ADDR1(page_mapping), ILT_ADDR2(page_mapping)); | ||
598 | } | ||
599 | |||
600 | static void bnx2x_ilt_line_init_op(struct bnx2x *bp, struct bnx2x_ilt *ilt, | ||
601 | int idx, u8 initop) | ||
602 | { | ||
603 | dma_addr_t null_mapping; | ||
604 | int abs_idx = ilt->start_line + idx; | ||
605 | |||
606 | |||
607 | switch (initop) { | ||
608 | case INITOP_INIT: | ||
609 | /* set in the init-value array */ | ||
610 | case INITOP_SET: | ||
611 | bnx2x_ilt_line_wr(bp, abs_idx, ilt->lines[idx].page_mapping); | ||
612 | break; | ||
613 | case INITOP_CLEAR: | ||
614 | null_mapping = 0; | ||
615 | bnx2x_ilt_line_wr(bp, abs_idx, null_mapping); | ||
616 | break; | ||
617 | } | ||
618 | } | ||
619 | |||
620 | void bnx2x_ilt_boundry_init_op(struct bnx2x *bp, | ||
621 | struct ilt_client_info *ilt_cli, | ||
622 | u32 ilt_start, u8 initop) | ||
623 | { | ||
624 | u32 start_reg = 0; | ||
625 | u32 end_reg = 0; | ||
626 | |||
627 | /* The boundary is either SET or INIT, | ||
628 | CLEAR => SET and for now SET ~~ INIT */ | ||
629 | |||
630 | /* find the appropriate regs */ | ||
631 | if (CHIP_IS_E1(bp)) { | ||
632 | switch (ilt_cli->client_num) { | ||
633 | case ILT_CLIENT_CDU: | ||
634 | start_reg = PXP2_REG_PSWRQ_CDU0_L2P; | ||
635 | break; | ||
636 | case ILT_CLIENT_QM: | ||
637 | start_reg = PXP2_REG_PSWRQ_QM0_L2P; | ||
638 | break; | ||
639 | case ILT_CLIENT_SRC: | ||
640 | start_reg = PXP2_REG_PSWRQ_SRC0_L2P; | ||
641 | break; | ||
642 | case ILT_CLIENT_TM: | ||
643 | start_reg = PXP2_REG_PSWRQ_TM0_L2P; | ||
644 | break; | ||
645 | } | ||
646 | REG_WR(bp, start_reg + BP_FUNC(bp)*4, | ||
647 | ILT_RANGE((ilt_start + ilt_cli->start), | ||
648 | (ilt_start + ilt_cli->end))); | ||
649 | } else { | ||
650 | switch (ilt_cli->client_num) { | ||
651 | case ILT_CLIENT_CDU: | ||
652 | start_reg = PXP2_REG_RQ_CDU_FIRST_ILT; | ||
653 | end_reg = PXP2_REG_RQ_CDU_LAST_ILT; | ||
654 | break; | ||
655 | case ILT_CLIENT_QM: | ||
656 | start_reg = PXP2_REG_RQ_QM_FIRST_ILT; | ||
657 | end_reg = PXP2_REG_RQ_QM_LAST_ILT; | ||
658 | break; | ||
659 | case ILT_CLIENT_SRC: | ||
660 | start_reg = PXP2_REG_RQ_SRC_FIRST_ILT; | ||
661 | end_reg = PXP2_REG_RQ_SRC_LAST_ILT; | ||
662 | break; | ||
663 | case ILT_CLIENT_TM: | ||
664 | start_reg = PXP2_REG_RQ_TM_FIRST_ILT; | ||
665 | end_reg = PXP2_REG_RQ_TM_LAST_ILT; | ||
666 | break; | ||
667 | } | ||
668 | REG_WR(bp, start_reg, (ilt_start + ilt_cli->start)); | ||
669 | REG_WR(bp, end_reg, (ilt_start + ilt_cli->end)); | ||
670 | } | ||
671 | } | ||
672 | |||
673 | void bnx2x_ilt_client_init_op_ilt(struct bnx2x *bp, struct bnx2x_ilt *ilt, | ||
674 | struct ilt_client_info *ilt_cli, u8 initop) | ||
675 | { | ||
676 | int i; | ||
677 | |||
678 | if (ilt_cli->flags & ILT_CLIENT_SKIP_INIT) | ||
679 | return; | ||
680 | |||
681 | for (i = ilt_cli->start; i <= ilt_cli->end; i++) | ||
682 | bnx2x_ilt_line_init_op(bp, ilt, i, initop); | ||
683 | |||
684 | /* init/clear the ILT boundries */ | ||
685 | bnx2x_ilt_boundry_init_op(bp, ilt_cli, ilt->start_line, initop); | ||
686 | } | ||
687 | |||
688 | void bnx2x_ilt_client_init_op(struct bnx2x *bp, | ||
689 | struct ilt_client_info *ilt_cli, u8 initop) | ||
690 | { | ||
691 | struct bnx2x_ilt *ilt = BP_ILT(bp); | ||
692 | |||
693 | bnx2x_ilt_client_init_op_ilt(bp, ilt, ilt_cli, initop); | ||
694 | } | ||
695 | |||
696 | static void bnx2x_ilt_client_id_init_op(struct bnx2x *bp, | ||
697 | int cli_num, u8 initop) | ||
698 | { | ||
699 | struct bnx2x_ilt *ilt = BP_ILT(bp); | ||
700 | struct ilt_client_info *ilt_cli = &ilt->clients[cli_num]; | ||
701 | |||
702 | bnx2x_ilt_client_init_op(bp, ilt_cli, initop); | ||
703 | } | ||
704 | |||
705 | void bnx2x_ilt_init_op(struct bnx2x *bp, u8 initop) | ||
706 | { | ||
707 | bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_CDU, initop); | ||
708 | bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_QM, initop); | ||
709 | bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_SRC, initop); | ||
710 | bnx2x_ilt_client_id_init_op(bp, ILT_CLIENT_TM, initop); | ||
711 | } | ||
712 | |||
713 | static void bnx2x_ilt_init_client_psz(struct bnx2x *bp, int cli_num, | ||
714 | u32 psz_reg, u8 initop) | ||
715 | { | ||
716 | struct bnx2x_ilt *ilt = BP_ILT(bp); | ||
717 | struct ilt_client_info *ilt_cli = &ilt->clients[cli_num]; | ||
718 | |||
719 | if (ilt_cli->flags & ILT_CLIENT_SKIP_INIT) | ||
720 | return; | ||
721 | |||
722 | switch (initop) { | ||
723 | case INITOP_INIT: | ||
724 | /* set in the init-value array */ | ||
725 | case INITOP_SET: | ||
726 | REG_WR(bp, psz_reg, ILOG2(ilt_cli->page_size >> 12)); | ||
727 | break; | ||
728 | case INITOP_CLEAR: | ||
729 | break; | ||
730 | } | ||
731 | } | ||
732 | |||
733 | /* | ||
734 | * called during init common stage, ilt clients should be initialized | ||
735 | * prioir to calling this function | ||
736 | */ | ||
737 | void bnx2x_ilt_init_page_size(struct bnx2x *bp, u8 initop) | ||
738 | { | ||
739 | bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_CDU, | ||
740 | PXP2_REG_RQ_CDU_P_SIZE, initop); | ||
741 | bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_QM, | ||
742 | PXP2_REG_RQ_QM_P_SIZE, initop); | ||
743 | bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_SRC, | ||
744 | PXP2_REG_RQ_SRC_P_SIZE, initop); | ||
745 | bnx2x_ilt_init_client_psz(bp, ILT_CLIENT_TM, | ||
746 | PXP2_REG_RQ_TM_P_SIZE, initop); | ||
747 | } | ||
748 | |||
749 | /**************************************************************************** | ||
750 | * QM initializations | ||
751 | ****************************************************************************/ | ||
752 | #define QM_QUEUES_PER_FUNC 16 /* E1 has 32, but only 16 are used */ | ||
753 | #define QM_INIT_MIN_CID_COUNT 31 | ||
754 | #define QM_INIT(cid_cnt) (cid_cnt > QM_INIT_MIN_CID_COUNT) | ||
755 | |||
756 | /* called during init port stage */ | ||
757 | void bnx2x_qm_init_cid_count(struct bnx2x *bp, int qm_cid_count, | ||
758 | u8 initop) | ||
759 | { | ||
760 | int port = BP_PORT(bp); | ||
761 | |||
762 | if (QM_INIT(qm_cid_count)) { | ||
763 | switch (initop) { | ||
764 | case INITOP_INIT: | ||
765 | /* set in the init-value array */ | ||
766 | case INITOP_SET: | ||
767 | REG_WR(bp, QM_REG_CONNNUM_0 + port*4, | ||
768 | qm_cid_count/16 - 1); | ||
769 | break; | ||
770 | case INITOP_CLEAR: | ||
771 | break; | ||
772 | } | ||
773 | } | ||
774 | } | ||
775 | |||
776 | static void bnx2x_qm_set_ptr_table(struct bnx2x *bp, int qm_cid_count) | ||
777 | { | ||
778 | int i; | ||
779 | u32 wb_data[2]; | ||
780 | |||
781 | wb_data[0] = wb_data[1] = 0; | ||
782 | |||
783 | for (i = 0; i < 4 * QM_QUEUES_PER_FUNC; i++) { | ||
784 | REG_WR(bp, QM_REG_BASEADDR + i*4, | ||
785 | qm_cid_count * 4 * (i % QM_QUEUES_PER_FUNC)); | ||
786 | bnx2x_init_ind_wr(bp, QM_REG_PTRTBL + i*8, | ||
787 | wb_data, 2); | ||
788 | |||
789 | if (CHIP_IS_E1H(bp)) { | ||
790 | REG_WR(bp, QM_REG_BASEADDR_EXT_A + i*4, | ||
791 | qm_cid_count * 4 * (i % QM_QUEUES_PER_FUNC)); | ||
792 | bnx2x_init_ind_wr(bp, QM_REG_PTRTBL_EXT_A + i*8, | ||
793 | wb_data, 2); | ||
794 | } | ||
795 | } | ||
796 | } | ||
797 | |||
798 | /* called during init common stage */ | ||
799 | void bnx2x_qm_init_ptr_table(struct bnx2x *bp, int qm_cid_count, | ||
800 | u8 initop) | ||
801 | { | ||
802 | if (!QM_INIT(qm_cid_count)) | ||
803 | return; | ||
804 | |||
805 | switch (initop) { | ||
806 | case INITOP_INIT: | ||
807 | /* set in the init-value array */ | ||
808 | case INITOP_SET: | ||
809 | bnx2x_qm_set_ptr_table(bp, qm_cid_count); | ||
810 | break; | ||
811 | case INITOP_CLEAR: | ||
812 | break; | ||
813 | } | ||
814 | } | ||
815 | |||
816 | /**************************************************************************** | ||
817 | * SRC initializations | ||
818 | ****************************************************************************/ | ||
819 | |||
820 | /* called during init func stage */ | ||
821 | void bnx2x_src_init_t2(struct bnx2x *bp, struct src_ent *t2, | ||
822 | dma_addr_t t2_mapping, int src_cid_count) | ||
823 | { | ||
824 | int i; | ||
825 | int port = BP_PORT(bp); | ||
826 | |||
827 | /* Initialize T2 */ | ||
828 | for (i = 0; i < src_cid_count-1; i++) | ||
829 | t2[i].next = (u64)(t2_mapping + (i+1)*sizeof(struct src_ent)); | ||
830 | |||
831 | /* tell the searcher where the T2 table is */ | ||
832 | REG_WR(bp, SRC_REG_COUNTFREE0 + port*4, src_cid_count); | ||
833 | |||
834 | bnx2x_wr_64(bp, SRC_REG_FIRSTFREE0 + port*16, | ||
835 | U64_LO(t2_mapping), U64_HI(t2_mapping)); | ||
836 | |||
837 | bnx2x_wr_64(bp, SRC_REG_LASTFREE0 + port*16, | ||
838 | U64_LO((u64)t2_mapping + | ||
839 | (src_cid_count-1) * sizeof(struct src_ent)), | ||
840 | U64_HI((u64)t2_mapping + | ||
841 | (src_cid_count-1) * sizeof(struct src_ent))); | ||
842 | } | ||
843 | |||
506 | #endif /* BNX2X_INIT_OPS_H */ | 844 | #endif /* BNX2X_INIT_OPS_H */ |