diff options
Diffstat (limited to 'drivers/net/ethernet/qlogic')
23 files changed, 3367 insertions, 661 deletions
diff --git a/drivers/net/ethernet/qlogic/Kconfig b/drivers/net/ethernet/qlogic/Kconfig index 0e1797295a48..f59e6be4a66e 100644 --- a/drivers/net/ethernet/qlogic/Kconfig +++ b/drivers/net/ethernet/qlogic/Kconfig | |||
@@ -45,6 +45,17 @@ config QLCNIC_SRIOV | |||
45 | This allows for virtual function acceleration in virtualized | 45 | This allows for virtual function acceleration in virtualized |
46 | environments. | 46 | environments. |
47 | 47 | ||
48 | config QLCNIC_DCB | ||
49 | bool "QLOGIC QLCNIC 82XX and 83XX family DCB Support" | ||
50 | depends on QLCNIC && DCB | ||
51 | default y | ||
52 | ---help--- | ||
53 | This configuration parameter enables DCB support in QLE83XX | ||
54 | and QLE82XX Converged Ethernet devices. This allows for DCB | ||
55 | get operations support through rtNetlink interface. Only CEE | ||
56 | mode of DCB is supported. PG and PFC values are related only | ||
57 | to Tx. | ||
58 | |||
48 | config QLGE | 59 | config QLGE |
49 | tristate "QLogic QLGE 10Gb Ethernet Driver Support" | 60 | tristate "QLogic QLGE 10Gb Ethernet Driver Support" |
50 | depends on PCI | 61 | depends on PCI |
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c index 9fbb1cdbfa47..8375cbde9969 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c | |||
@@ -536,10 +536,10 @@ static void netxen_p2_nic_set_multi(struct net_device *netdev) | |||
536 | { | 536 | { |
537 | struct netxen_adapter *adapter = netdev_priv(netdev); | 537 | struct netxen_adapter *adapter = netdev_priv(netdev); |
538 | struct netdev_hw_addr *ha; | 538 | struct netdev_hw_addr *ha; |
539 | u8 null_addr[6]; | 539 | u8 null_addr[ETH_ALEN]; |
540 | int i; | 540 | int i; |
541 | 541 | ||
542 | memset(null_addr, 0, 6); | 542 | memset(null_addr, 0, ETH_ALEN); |
543 | 543 | ||
544 | if (netdev->flags & IFF_PROMISC) { | 544 | if (netdev->flags & IFF_PROMISC) { |
545 | 545 | ||
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index ec4cf7fd4123..cbd75f97ffb3 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | |||
@@ -459,16 +459,14 @@ static void netxen_pcie_strap_init(struct netxen_adapter *adapter) | |||
459 | static void netxen_set_msix_bit(struct pci_dev *pdev, int enable) | 459 | static void netxen_set_msix_bit(struct pci_dev *pdev, int enable) |
460 | { | 460 | { |
461 | u32 control; | 461 | u32 control; |
462 | int pos; | ||
463 | 462 | ||
464 | pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX); | 463 | if (pdev->msix_cap) { |
465 | if (pos) { | 464 | pci_read_config_dword(pdev, pdev->msix_cap, &control); |
466 | pci_read_config_dword(pdev, pos, &control); | ||
467 | if (enable) | 465 | if (enable) |
468 | control |= PCI_MSIX_FLAGS_ENABLE; | 466 | control |= PCI_MSIX_FLAGS_ENABLE; |
469 | else | 467 | else |
470 | control = 0; | 468 | control = 0; |
471 | pci_write_config_dword(pdev, pos, control); | 469 | pci_write_config_dword(pdev, pdev->msix_cap, control); |
472 | } | 470 | } |
473 | } | 471 | } |
474 | 472 | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile index 4b1fb3faa3b7..a848d2979722 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/Makefile +++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile | |||
@@ -11,3 +11,5 @@ qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \ | |||
11 | qlcnic_minidump.o qlcnic_sriov_common.o | 11 | qlcnic_minidump.o qlcnic_sriov_common.o |
12 | 12 | ||
13 | qlcnic-$(CONFIG_QLCNIC_SRIOV) += qlcnic_sriov_pf.o | 13 | qlcnic-$(CONFIG_QLCNIC_SRIOV) += qlcnic_sriov_pf.o |
14 | |||
15 | qlcnic-$(CONFIG_QLCNIC_DCB) += qlcnic_dcb.o | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 221645e9f182..88349b8fa39a 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/tcp.h> | 20 | #include <linux/tcp.h> |
21 | #include <linux/skbuff.h> | 21 | #include <linux/skbuff.h> |
22 | #include <linux/firmware.h> | 22 | #include <linux/firmware.h> |
23 | |||
24 | #include <linux/ethtool.h> | 23 | #include <linux/ethtool.h> |
25 | #include <linux/mii.h> | 24 | #include <linux/mii.h> |
26 | #include <linux/timer.h> | 25 | #include <linux/timer.h> |
@@ -35,11 +34,12 @@ | |||
35 | #include "qlcnic_hdr.h" | 34 | #include "qlcnic_hdr.h" |
36 | #include "qlcnic_hw.h" | 35 | #include "qlcnic_hw.h" |
37 | #include "qlcnic_83xx_hw.h" | 36 | #include "qlcnic_83xx_hw.h" |
37 | #include "qlcnic_dcb.h" | ||
38 | 38 | ||
39 | #define _QLCNIC_LINUX_MAJOR 5 | 39 | #define _QLCNIC_LINUX_MAJOR 5 |
40 | #define _QLCNIC_LINUX_MINOR 2 | 40 | #define _QLCNIC_LINUX_MINOR 3 |
41 | #define _QLCNIC_LINUX_SUBVERSION 44 | 41 | #define _QLCNIC_LINUX_SUBVERSION 50 |
42 | #define QLCNIC_LINUX_VERSIONID "5.2.44" | 42 | #define QLCNIC_LINUX_VERSIONID "5.3.50" |
43 | #define QLCNIC_DRV_IDC_VER 0x01 | 43 | #define QLCNIC_DRV_IDC_VER 0x01 |
44 | #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ | 44 | #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ |
45 | (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) | 45 | (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) |
@@ -98,6 +98,9 @@ | |||
98 | #define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \ | 98 | #define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \ |
99 | + MGMT_CMD_DESC_RESV) | 99 | + MGMT_CMD_DESC_RESV) |
100 | #define QLCNIC_MAX_TX_TIMEOUTS 2 | 100 | #define QLCNIC_MAX_TX_TIMEOUTS 2 |
101 | #define QLCNIC_MAX_TX_RINGS 8 | ||
102 | #define QLCNIC_MAX_SDS_RINGS 8 | ||
103 | |||
101 | /* | 104 | /* |
102 | * Following are the states of the Phantom. Phantom will set them and | 105 | * Following are the states of the Phantom. Phantom will set them and |
103 | * Host will read to check if the fields are correct. | 106 | * Host will read to check if the fields are correct. |
@@ -389,7 +392,7 @@ struct qlcnic_dump_template_hdr { | |||
389 | 392 | ||
390 | struct qlcnic_fw_dump { | 393 | struct qlcnic_fw_dump { |
391 | u8 clr; /* flag to indicate if dump is cleared */ | 394 | u8 clr; /* flag to indicate if dump is cleared */ |
392 | u8 enable; /* enable/disable dump */ | 395 | bool enable; /* enable/disable dump */ |
393 | u32 size; /* total size of the dump */ | 396 | u32 size; /* total size of the dump */ |
394 | void *data; /* dump data area */ | 397 | void *data; /* dump data area */ |
395 | struct qlcnic_dump_template_hdr *tmpl_hdr; | 398 | struct qlcnic_dump_template_hdr *tmpl_hdr; |
@@ -460,14 +463,16 @@ struct qlcnic_hardware_context { | |||
460 | struct qlcnic_fdt fdt; | 463 | struct qlcnic_fdt fdt; |
461 | struct qlc_83xx_reset reset; | 464 | struct qlc_83xx_reset reset; |
462 | struct qlc_83xx_idc idc; | 465 | struct qlc_83xx_idc idc; |
463 | struct qlc_83xx_fw_info fw_info; | 466 | struct qlc_83xx_fw_info *fw_info; |
464 | struct qlcnic_intrpt_config *intr_tbl; | 467 | struct qlcnic_intrpt_config *intr_tbl; |
465 | struct qlcnic_sriov *sriov; | 468 | struct qlcnic_sriov *sriov; |
466 | u32 *reg_tbl; | 469 | u32 *reg_tbl; |
467 | u32 *ext_reg_tbl; | 470 | u32 *ext_reg_tbl; |
468 | u32 mbox_aen[QLC_83XX_MBX_AEN_CNT]; | 471 | u32 mbox_aen[QLC_83XX_MBX_AEN_CNT]; |
469 | u32 mbox_reg[4]; | 472 | u32 mbox_reg[4]; |
470 | spinlock_t mbx_lock; | 473 | struct qlcnic_mailbox *mailbox; |
474 | u8 extend_lb_time; | ||
475 | u8 phys_port_id[ETH_ALEN]; | ||
471 | }; | 476 | }; |
472 | 477 | ||
473 | struct qlcnic_adapter_stats { | 478 | struct qlcnic_adapter_stats { |
@@ -515,6 +520,7 @@ struct qlcnic_host_sds_ring { | |||
515 | u32 num_desc; | 520 | u32 num_desc; |
516 | void __iomem *crb_sts_consumer; | 521 | void __iomem *crb_sts_consumer; |
517 | 522 | ||
523 | struct qlcnic_host_tx_ring *tx_ring; | ||
518 | struct status_desc *desc_head; | 524 | struct status_desc *desc_head; |
519 | struct qlcnic_adapter *adapter; | 525 | struct qlcnic_adapter *adapter; |
520 | struct napi_struct napi; | 526 | struct napi_struct napi; |
@@ -532,9 +538,17 @@ struct qlcnic_host_tx_ring { | |||
532 | void __iomem *crb_intr_mask; | 538 | void __iomem *crb_intr_mask; |
533 | char name[IFNAMSIZ + 12]; | 539 | char name[IFNAMSIZ + 12]; |
534 | u16 ctx_id; | 540 | u16 ctx_id; |
541 | |||
542 | u32 state; | ||
535 | u32 producer; | 543 | u32 producer; |
536 | u32 sw_consumer; | 544 | u32 sw_consumer; |
537 | u32 num_desc; | 545 | u32 num_desc; |
546 | |||
547 | u64 xmit_on; | ||
548 | u64 xmit_off; | ||
549 | u64 xmit_called; | ||
550 | u64 xmit_finished; | ||
551 | |||
538 | void __iomem *crb_cmd_producer; | 552 | void __iomem *crb_cmd_producer; |
539 | struct cmd_desc_type0 *desc_head; | 553 | struct cmd_desc_type0 *desc_head; |
540 | struct qlcnic_adapter *adapter; | 554 | struct qlcnic_adapter *adapter; |
@@ -559,7 +573,6 @@ struct qlcnic_recv_context { | |||
559 | u32 state; | 573 | u32 state; |
560 | u16 context_id; | 574 | u16 context_id; |
561 | u16 virt_port; | 575 | u16 virt_port; |
562 | |||
563 | }; | 576 | }; |
564 | 577 | ||
565 | /* HW context creation */ | 578 | /* HW context creation */ |
@@ -604,6 +617,7 @@ struct qlcnic_recv_context { | |||
604 | #define QLCNIC_CAP0_LRO_CONTIGUOUS (1 << 8) | 617 | #define QLCNIC_CAP0_LRO_CONTIGUOUS (1 << 8) |
605 | #define QLCNIC_CAP0_VALIDOFF (1 << 11) | 618 | #define QLCNIC_CAP0_VALIDOFF (1 << 11) |
606 | #define QLCNIC_CAP0_LRO_MSS (1 << 21) | 619 | #define QLCNIC_CAP0_LRO_MSS (1 << 21) |
620 | #define QLCNIC_CAP0_TX_MULTI (1 << 22) | ||
607 | 621 | ||
608 | /* | 622 | /* |
609 | * Context state | 623 | * Context state |
@@ -631,7 +645,7 @@ struct qlcnic_hostrq_rds_ring { | |||
631 | 645 | ||
632 | struct qlcnic_hostrq_rx_ctx { | 646 | struct qlcnic_hostrq_rx_ctx { |
633 | __le64 host_rsp_dma_addr; /* Response dma'd here */ | 647 | __le64 host_rsp_dma_addr; /* Response dma'd here */ |
634 | __le32 capabilities[4]; /* Flag bit vector */ | 648 | __le32 capabilities[4]; /* Flag bit vector */ |
635 | __le32 host_int_crb_mode; /* Interrupt crb usage */ | 649 | __le32 host_int_crb_mode; /* Interrupt crb usage */ |
636 | __le32 host_rds_crb_mode; /* RDS crb usage */ | 650 | __le32 host_rds_crb_mode; /* RDS crb usage */ |
637 | /* These ring offsets are relative to data[0] below */ | 651 | /* These ring offsets are relative to data[0] below */ |
@@ -802,6 +816,7 @@ struct qlcnic_mac_list_s { | |||
802 | 816 | ||
803 | #define QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK 0x8f | 817 | #define QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK 0x8f |
804 | #define QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE 0x8D | 818 | #define QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE 0x8D |
819 | #define QLCNIC_C2H_OPCODE_GET_DCB_AEN 0x90 | ||
805 | 820 | ||
806 | #define VPORT_MISS_MODE_DROP 0 /* drop all unmatched */ | 821 | #define VPORT_MISS_MODE_DROP 0 /* drop all unmatched */ |
807 | #define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */ | 822 | #define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */ |
@@ -814,6 +829,7 @@ struct qlcnic_mac_list_s { | |||
814 | #define QLCNIC_FW_CAPABILITY_BDG BIT_8 | 829 | #define QLCNIC_FW_CAPABILITY_BDG BIT_8 |
815 | #define QLCNIC_FW_CAPABILITY_FVLANTX BIT_9 | 830 | #define QLCNIC_FW_CAPABILITY_FVLANTX BIT_9 |
816 | #define QLCNIC_FW_CAPABILITY_HW_LRO BIT_10 | 831 | #define QLCNIC_FW_CAPABILITY_HW_LRO BIT_10 |
832 | #define QLCNIC_FW_CAPABILITY_2_MULTI_TX BIT_4 | ||
817 | #define QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK BIT_27 | 833 | #define QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK BIT_27 |
818 | #define QLCNIC_FW_CAPABILITY_MORE_CAPS BIT_31 | 834 | #define QLCNIC_FW_CAPABILITY_MORE_CAPS BIT_31 |
819 | 835 | ||
@@ -821,6 +837,7 @@ struct qlcnic_mac_list_s { | |||
821 | #define QLCNIC_FW_CAP2_HW_LRO_IPV6 BIT_3 | 837 | #define QLCNIC_FW_CAP2_HW_LRO_IPV6 BIT_3 |
822 | #define QLCNIC_FW_CAPABILITY_SET_DRV_VER BIT_5 | 838 | #define QLCNIC_FW_CAPABILITY_SET_DRV_VER BIT_5 |
823 | #define QLCNIC_FW_CAPABILITY_2_BEACON BIT_7 | 839 | #define QLCNIC_FW_CAPABILITY_2_BEACON BIT_7 |
840 | #define QLCNIC_FW_CAPABILITY_2_PER_PORT_ESWITCH_CFG BIT_8 | ||
824 | 841 | ||
825 | /* module types */ | 842 | /* module types */ |
826 | #define LINKEVENT_MODULE_NOT_PRESENT 1 | 843 | #define LINKEVENT_MODULE_NOT_PRESENT 1 |
@@ -913,6 +930,8 @@ struct qlcnic_ipaddr { | |||
913 | #define QLCNIC_FW_LRO_MSS_CAP 0x8000 | 930 | #define QLCNIC_FW_LRO_MSS_CAP 0x8000 |
914 | #define QLCNIC_TX_INTR_SHARED 0x10000 | 931 | #define QLCNIC_TX_INTR_SHARED 0x10000 |
915 | #define QLCNIC_APP_CHANGED_FLAGS 0x20000 | 932 | #define QLCNIC_APP_CHANGED_FLAGS 0x20000 |
933 | #define QLCNIC_HAS_PHYS_PORT_ID 0x40000 | ||
934 | |||
916 | #define QLCNIC_IS_MSI_FAMILY(adapter) \ | 935 | #define QLCNIC_IS_MSI_FAMILY(adapter) \ |
917 | ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) | 936 | ((adapter)->flags & (QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED)) |
918 | #define QLCNIC_IS_TSO_CAPABLE(adapter) \ | 937 | #define QLCNIC_IS_TSO_CAPABLE(adapter) \ |
@@ -922,11 +941,11 @@ struct qlcnic_ipaddr { | |||
922 | #define QLCNIC_BEACON_DISABLE 0xD | 941 | #define QLCNIC_BEACON_DISABLE 0xD |
923 | 942 | ||
924 | #define QLCNIC_DEF_NUM_STS_DESC_RINGS 4 | 943 | #define QLCNIC_DEF_NUM_STS_DESC_RINGS 4 |
944 | #define QLCNIC_DEF_NUM_TX_RINGS 4 | ||
925 | #define QLCNIC_MSIX_TBL_SPACE 8192 | 945 | #define QLCNIC_MSIX_TBL_SPACE 8192 |
926 | #define QLCNIC_PCI_REG_MSIX_TBL 0x44 | 946 | #define QLCNIC_PCI_REG_MSIX_TBL 0x44 |
927 | #define QLCNIC_MSIX_TBL_PGSIZE 4096 | 947 | #define QLCNIC_MSIX_TBL_PGSIZE 4096 |
928 | 948 | ||
929 | #define QLCNIC_NETDEV_WEIGHT 128 | ||
930 | #define QLCNIC_ADAPTER_UP_MAGIC 777 | 949 | #define QLCNIC_ADAPTER_UP_MAGIC 777 |
931 | 950 | ||
932 | #define __QLCNIC_FW_ATTACHED 0 | 951 | #define __QLCNIC_FW_ATTACHED 0 |
@@ -937,10 +956,13 @@ struct qlcnic_ipaddr { | |||
937 | #define __QLCNIC_DIAG_RES_ALLOC 6 | 956 | #define __QLCNIC_DIAG_RES_ALLOC 6 |
938 | #define __QLCNIC_LED_ENABLE 7 | 957 | #define __QLCNIC_LED_ENABLE 7 |
939 | #define __QLCNIC_ELB_INPROGRESS 8 | 958 | #define __QLCNIC_ELB_INPROGRESS 8 |
959 | #define __QLCNIC_MULTI_TX_UNIQUE 9 | ||
940 | #define __QLCNIC_SRIOV_ENABLE 10 | 960 | #define __QLCNIC_SRIOV_ENABLE 10 |
941 | #define __QLCNIC_SRIOV_CAPABLE 11 | 961 | #define __QLCNIC_SRIOV_CAPABLE 11 |
942 | #define __QLCNIC_MBX_POLL_ENABLE 12 | 962 | #define __QLCNIC_MBX_POLL_ENABLE 12 |
943 | #define __QLCNIC_DIAG_MODE 13 | 963 | #define __QLCNIC_DIAG_MODE 13 |
964 | #define __QLCNIC_DCB_STATE 14 | ||
965 | #define __QLCNIC_DCB_IN_AEN 15 | ||
944 | 966 | ||
945 | #define QLCNIC_INTERRUPT_TEST 1 | 967 | #define QLCNIC_INTERRUPT_TEST 1 |
946 | #define QLCNIC_LOOPBACK_TEST 2 | 968 | #define QLCNIC_LOOPBACK_TEST 2 |
@@ -950,12 +972,6 @@ struct qlcnic_ipaddr { | |||
950 | #define QLCNIC_READD_AGE 20 | 972 | #define QLCNIC_READD_AGE 20 |
951 | #define QLCNIC_LB_MAX_FILTERS 64 | 973 | #define QLCNIC_LB_MAX_FILTERS 64 |
952 | #define QLCNIC_LB_BUCKET_SIZE 32 | 974 | #define QLCNIC_LB_BUCKET_SIZE 32 |
953 | |||
954 | /* QLCNIC Driver Error Code */ | ||
955 | #define QLCNIC_FW_NOT_RESPOND 51 | ||
956 | #define QLCNIC_TEST_IN_PROGRESS 52 | ||
957 | #define QLCNIC_UNDEFINED_ERROR 53 | ||
958 | #define QLCNIC_LB_CABLE_NOT_CONN 54 | ||
959 | #define QLCNIC_ILB_MAX_RCV_LOOP 10 | 975 | #define QLCNIC_ILB_MAX_RCV_LOOP 10 |
960 | 976 | ||
961 | struct qlcnic_filter { | 977 | struct qlcnic_filter { |
@@ -972,6 +988,21 @@ struct qlcnic_filter_hash { | |||
972 | u16 fbucket_size; | 988 | u16 fbucket_size; |
973 | }; | 989 | }; |
974 | 990 | ||
991 | /* Mailbox specific data structures */ | ||
992 | struct qlcnic_mailbox { | ||
993 | struct workqueue_struct *work_q; | ||
994 | struct qlcnic_adapter *adapter; | ||
995 | struct qlcnic_mbx_ops *ops; | ||
996 | struct work_struct work; | ||
997 | struct completion completion; | ||
998 | struct list_head cmd_q; | ||
999 | unsigned long status; | ||
1000 | spinlock_t queue_lock; /* Mailbox queue lock */ | ||
1001 | spinlock_t aen_lock; /* Mailbox response/AEN lock */ | ||
1002 | atomic_t rsp_status; | ||
1003 | u32 num_cmds; | ||
1004 | }; | ||
1005 | |||
975 | struct qlcnic_adapter { | 1006 | struct qlcnic_adapter { |
976 | struct qlcnic_hardware_context *ahw; | 1007 | struct qlcnic_hardware_context *ahw; |
977 | struct qlcnic_recv_context *recv_ctx; | 1008 | struct qlcnic_recv_context *recv_ctx; |
@@ -1035,6 +1066,7 @@ struct qlcnic_adapter { | |||
1035 | struct delayed_work fw_work; | 1066 | struct delayed_work fw_work; |
1036 | struct delayed_work idc_aen_work; | 1067 | struct delayed_work idc_aen_work; |
1037 | struct delayed_work mbx_poll_work; | 1068 | struct delayed_work mbx_poll_work; |
1069 | struct qlcnic_dcb *dcb; | ||
1038 | 1070 | ||
1039 | struct qlcnic_filter_hash fhash; | 1071 | struct qlcnic_filter_hash fhash; |
1040 | struct qlcnic_filter_hash rx_fhash; | 1072 | struct qlcnic_filter_hash rx_fhash; |
@@ -1152,6 +1184,7 @@ struct qlcnic_pci_info { | |||
1152 | }; | 1184 | }; |
1153 | 1185 | ||
1154 | struct qlcnic_npar_info { | 1186 | struct qlcnic_npar_info { |
1187 | bool eswitch_status; | ||
1155 | u16 pvid; | 1188 | u16 pvid; |
1156 | u16 min_bw; | 1189 | u16 min_bw; |
1157 | u16 max_bw; | 1190 | u16 max_bw; |
@@ -1371,7 +1404,6 @@ struct qlcnic_esw_statistics { | |||
1371 | struct __qlcnic_esw_statistics tx; | 1404 | struct __qlcnic_esw_statistics tx; |
1372 | }; | 1405 | }; |
1373 | 1406 | ||
1374 | #define QLCNIC_DUMP_MASK_DEF 0x1f | ||
1375 | #define QLCNIC_FORCE_FW_DUMP_KEY 0xdeadfeed | 1407 | #define QLCNIC_FORCE_FW_DUMP_KEY 0xdeadfeed |
1376 | #define QLCNIC_ENABLE_FW_DUMP 0xaddfeed | 1408 | #define QLCNIC_ENABLE_FW_DUMP 0xaddfeed |
1377 | #define QLCNIC_DISABLE_FW_DUMP 0xbadfeed | 1409 | #define QLCNIC_DISABLE_FW_DUMP 0xbadfeed |
@@ -1385,9 +1417,20 @@ struct _cdrp_cmd { | |||
1385 | }; | 1417 | }; |
1386 | 1418 | ||
1387 | struct qlcnic_cmd_args { | 1419 | struct qlcnic_cmd_args { |
1388 | struct _cdrp_cmd req; | 1420 | struct completion completion; |
1389 | struct _cdrp_cmd rsp; | 1421 | struct list_head list; |
1390 | int op_type; | 1422 | struct _cdrp_cmd req; |
1423 | struct _cdrp_cmd rsp; | ||
1424 | atomic_t rsp_status; | ||
1425 | int pay_size; | ||
1426 | u32 rsp_opcode; | ||
1427 | u32 total_cmds; | ||
1428 | u32 op_type; | ||
1429 | u32 type; | ||
1430 | u32 cmd_op; | ||
1431 | u32 *hdr; /* Back channel message header */ | ||
1432 | u32 *pay; /* Back channel message payload */ | ||
1433 | u8 func_num; | ||
1391 | }; | 1434 | }; |
1392 | 1435 | ||
1393 | int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter); | 1436 | int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter); |
@@ -1435,6 +1478,12 @@ int qlcnic_wol_supported(struct qlcnic_adapter *adapter); | |||
1435 | void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter); | 1478 | void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter); |
1436 | void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter); | 1479 | void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter); |
1437 | int qlcnic_dump_fw(struct qlcnic_adapter *); | 1480 | int qlcnic_dump_fw(struct qlcnic_adapter *); |
1481 | int qlcnic_enable_fw_dump_state(struct qlcnic_adapter *); | ||
1482 | bool qlcnic_check_fw_dump_state(struct qlcnic_adapter *); | ||
1483 | pci_ers_result_t qlcnic_82xx_io_error_detected(struct pci_dev *, | ||
1484 | pci_channel_state_t); | ||
1485 | pci_ers_result_t qlcnic_82xx_io_slot_reset(struct pci_dev *); | ||
1486 | void qlcnic_82xx_io_resume(struct pci_dev *); | ||
1438 | 1487 | ||
1439 | /* Functions from qlcnic_init.c */ | 1488 | /* Functions from qlcnic_init.c */ |
1440 | void qlcnic_schedule_work(struct qlcnic_adapter *, work_func_t, int); | 1489 | void qlcnic_schedule_work(struct qlcnic_adapter *, work_func_t, int); |
@@ -1462,7 +1511,8 @@ void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter); | |||
1462 | 1511 | ||
1463 | void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter); | 1512 | void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter); |
1464 | void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter); | 1513 | void qlcnic_release_rx_buffers(struct qlcnic_adapter *adapter); |
1465 | void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter); | 1514 | void qlcnic_release_tx_buffers(struct qlcnic_adapter *, |
1515 | struct qlcnic_host_tx_ring *); | ||
1466 | 1516 | ||
1467 | int qlcnic_check_fw_status(struct qlcnic_adapter *adapter); | 1517 | int qlcnic_check_fw_status(struct qlcnic_adapter *adapter); |
1468 | void qlcnic_watchdog_task(struct work_struct *work); | 1518 | void qlcnic_watchdog_task(struct work_struct *work); |
@@ -1474,6 +1524,7 @@ void __qlcnic_set_multi(struct net_device *, u16); | |||
1474 | int qlcnic_nic_add_mac(struct qlcnic_adapter *, const u8 *, u16); | 1524 | int qlcnic_nic_add_mac(struct qlcnic_adapter *, const u8 *, u16); |
1475 | int qlcnic_nic_del_mac(struct qlcnic_adapter *, const u8 *); | 1525 | int qlcnic_nic_del_mac(struct qlcnic_adapter *, const u8 *); |
1476 | void qlcnic_82xx_free_mac_list(struct qlcnic_adapter *adapter); | 1526 | void qlcnic_82xx_free_mac_list(struct qlcnic_adapter *adapter); |
1527 | int qlcnic_82xx_read_phys_port_id(struct qlcnic_adapter *); | ||
1477 | 1528 | ||
1478 | int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu); | 1529 | int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu); |
1479 | int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *, u32); | 1530 | int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *, u32); |
@@ -1495,8 +1546,9 @@ int qlcnic_reset_context(struct qlcnic_adapter *); | |||
1495 | void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings); | 1546 | void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings); |
1496 | int qlcnic_diag_alloc_res(struct net_device *netdev, int test); | 1547 | int qlcnic_diag_alloc_res(struct net_device *netdev, int test); |
1497 | netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev); | 1548 | netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev); |
1498 | int qlcnic_set_max_rss(struct qlcnic_adapter *, u8, size_t); | 1549 | int qlcnic_set_max_rss(struct qlcnic_adapter *, u8, int); |
1499 | int qlcnic_validate_max_rss(struct qlcnic_adapter *, __u32); | 1550 | int qlcnic_validate_max_rss(struct qlcnic_adapter *, __u32); |
1551 | int qlcnic_validate_max_tx_rings(struct qlcnic_adapter *, u32 txq); | ||
1500 | void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter); | 1552 | void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter); |
1501 | void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *); | 1553 | void qlcnic_82xx_set_mac_filter_count(struct qlcnic_adapter *); |
1502 | int qlcnic_enable_msix(struct qlcnic_adapter *, u32); | 1554 | int qlcnic_enable_msix(struct qlcnic_adapter *, u32); |
@@ -1523,6 +1575,7 @@ void qlcnic_free_sds_rings(struct qlcnic_recv_context *); | |||
1523 | void qlcnic_advert_link_change(struct qlcnic_adapter *, int); | 1575 | void qlcnic_advert_link_change(struct qlcnic_adapter *, int); |
1524 | void qlcnic_free_tx_rings(struct qlcnic_adapter *); | 1576 | void qlcnic_free_tx_rings(struct qlcnic_adapter *); |
1525 | int qlcnic_alloc_tx_rings(struct qlcnic_adapter *, struct net_device *); | 1577 | int qlcnic_alloc_tx_rings(struct qlcnic_adapter *, struct net_device *); |
1578 | void qlcnic_dump_mbx(struct qlcnic_adapter *, struct qlcnic_cmd_args *); | ||
1526 | 1579 | ||
1527 | void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter); | 1580 | void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter); |
1528 | void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter); | 1581 | void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter); |
@@ -1585,6 +1638,26 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring) | |||
1585 | tx_ring->producer; | 1638 | tx_ring->producer; |
1586 | } | 1639 | } |
1587 | 1640 | ||
1641 | static inline int qlcnic_set_real_num_queues(struct qlcnic_adapter *adapter, | ||
1642 | struct net_device *netdev) | ||
1643 | { | ||
1644 | int err, tx_q; | ||
1645 | |||
1646 | tx_q = adapter->max_drv_tx_rings; | ||
1647 | |||
1648 | netdev->num_tx_queues = tx_q; | ||
1649 | netdev->real_num_tx_queues = tx_q; | ||
1650 | |||
1651 | err = netif_set_real_num_tx_queues(netdev, tx_q); | ||
1652 | if (err) | ||
1653 | dev_err(&adapter->pdev->dev, "failed to set %d Tx queues\n", | ||
1654 | tx_q); | ||
1655 | else | ||
1656 | dev_info(&adapter->pdev->dev, "set %d Tx queues\n", tx_q); | ||
1657 | |||
1658 | return err; | ||
1659 | } | ||
1660 | |||
1588 | struct qlcnic_nic_template { | 1661 | struct qlcnic_nic_template { |
1589 | int (*config_bridged_mode) (struct qlcnic_adapter *, u32); | 1662 | int (*config_bridged_mode) (struct qlcnic_adapter *, u32); |
1590 | int (*config_led) (struct qlcnic_adapter *, u32, u32); | 1663 | int (*config_led) (struct qlcnic_adapter *, u32, u32); |
@@ -1600,6 +1673,20 @@ struct qlcnic_nic_template { | |||
1600 | int (*resume)(struct qlcnic_adapter *); | 1673 | int (*resume)(struct qlcnic_adapter *); |
1601 | }; | 1674 | }; |
1602 | 1675 | ||
1676 | struct qlcnic_mbx_ops { | ||
1677 | int (*enqueue_cmd) (struct qlcnic_adapter *, | ||
1678 | struct qlcnic_cmd_args *, unsigned long *); | ||
1679 | void (*dequeue_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *); | ||
1680 | void (*decode_resp) (struct qlcnic_adapter *, struct qlcnic_cmd_args *); | ||
1681 | void (*encode_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *); | ||
1682 | void (*nofity_fw) (struct qlcnic_adapter *, u8); | ||
1683 | }; | ||
1684 | |||
1685 | int qlcnic_83xx_init_mailbox_work(struct qlcnic_adapter *); | ||
1686 | void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *); | ||
1687 | void qlcnic_83xx_reinit_mbx_work(struct qlcnic_mailbox *mbx); | ||
1688 | void qlcnic_83xx_free_mailbox(struct qlcnic_mailbox *mbx); | ||
1689 | |||
1603 | /* Adapter hardware abstraction */ | 1690 | /* Adapter hardware abstraction */ |
1604 | struct qlcnic_hardware_ops { | 1691 | struct qlcnic_hardware_ops { |
1605 | void (*read_crb) (struct qlcnic_adapter *, char *, loff_t, size_t); | 1692 | void (*read_crb) (struct qlcnic_adapter *, char *, loff_t, size_t); |
@@ -1607,8 +1694,8 @@ struct qlcnic_hardware_ops { | |||
1607 | int (*read_reg) (struct qlcnic_adapter *, ulong, int *); | 1694 | int (*read_reg) (struct qlcnic_adapter *, ulong, int *); |
1608 | int (*write_reg) (struct qlcnic_adapter *, ulong, u32); | 1695 | int (*write_reg) (struct qlcnic_adapter *, ulong, u32); |
1609 | void (*get_ocm_win) (struct qlcnic_hardware_context *); | 1696 | void (*get_ocm_win) (struct qlcnic_hardware_context *); |
1610 | int (*get_mac_address) (struct qlcnic_adapter *, u8 *); | 1697 | int (*get_mac_address) (struct qlcnic_adapter *, u8 *, u8); |
1611 | int (*setup_intr) (struct qlcnic_adapter *, u8); | 1698 | int (*setup_intr) (struct qlcnic_adapter *, u8, int); |
1612 | int (*alloc_mbx_args)(struct qlcnic_cmd_args *, | 1699 | int (*alloc_mbx_args)(struct qlcnic_cmd_args *, |
1613 | struct qlcnic_adapter *, u32); | 1700 | struct qlcnic_adapter *, u32); |
1614 | int (*mbx_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *); | 1701 | int (*mbx_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *); |
@@ -1641,6 +1728,11 @@ struct qlcnic_hardware_ops { | |||
1641 | int (*get_board_info) (struct qlcnic_adapter *); | 1728 | int (*get_board_info) (struct qlcnic_adapter *); |
1642 | void (*set_mac_filter_count) (struct qlcnic_adapter *); | 1729 | void (*set_mac_filter_count) (struct qlcnic_adapter *); |
1643 | void (*free_mac_list) (struct qlcnic_adapter *); | 1730 | void (*free_mac_list) (struct qlcnic_adapter *); |
1731 | int (*read_phys_port_id) (struct qlcnic_adapter *); | ||
1732 | pci_ers_result_t (*io_error_detected) (struct pci_dev *, | ||
1733 | pci_channel_state_t); | ||
1734 | pci_ers_result_t (*io_slot_reset) (struct pci_dev *); | ||
1735 | void (*io_resume) (struct pci_dev *); | ||
1644 | }; | 1736 | }; |
1645 | 1737 | ||
1646 | extern struct qlcnic_nic_template qlcnic_vf_ops; | 1738 | extern struct qlcnic_nic_template qlcnic_vf_ops; |
@@ -1669,14 +1761,15 @@ static inline int qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, | |||
1669 | } | 1761 | } |
1670 | 1762 | ||
1671 | static inline int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, | 1763 | static inline int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, |
1672 | u8 *mac) | 1764 | u8 *mac, u8 function) |
1673 | { | 1765 | { |
1674 | return adapter->ahw->hw_ops->get_mac_address(adapter, mac); | 1766 | return adapter->ahw->hw_ops->get_mac_address(adapter, mac, function); |
1675 | } | 1767 | } |
1676 | 1768 | ||
1677 | static inline int qlcnic_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr) | 1769 | static inline int qlcnic_setup_intr(struct qlcnic_adapter *adapter, |
1770 | u8 num_intr, int txq) | ||
1678 | { | 1771 | { |
1679 | return adapter->ahw->hw_ops->setup_intr(adapter, num_intr); | 1772 | return adapter->ahw->hw_ops->setup_intr(adapter, num_intr, txq); |
1680 | } | 1773 | } |
1681 | 1774 | ||
1682 | static inline int qlcnic_alloc_mbx_args(struct qlcnic_cmd_args *mbx, | 1775 | static inline int qlcnic_alloc_mbx_args(struct qlcnic_cmd_args *mbx, |
@@ -1867,6 +1960,12 @@ static inline void qlcnic_set_mac_filter_count(struct qlcnic_adapter *adapter) | |||
1867 | adapter->ahw->hw_ops->set_mac_filter_count(adapter); | 1960 | adapter->ahw->hw_ops->set_mac_filter_count(adapter); |
1868 | } | 1961 | } |
1869 | 1962 | ||
1963 | static inline void qlcnic_read_phys_port_id(struct qlcnic_adapter *adapter) | ||
1964 | { | ||
1965 | if (adapter->ahw->hw_ops->read_phys_port_id) | ||
1966 | adapter->ahw->hw_ops->read_phys_port_id(adapter); | ||
1967 | } | ||
1968 | |||
1870 | static inline void qlcnic_dev_request_reset(struct qlcnic_adapter *adapter, | 1969 | static inline void qlcnic_dev_request_reset(struct qlcnic_adapter *adapter, |
1871 | u32 key) | 1970 | u32 key) |
1872 | { | 1971 | { |
@@ -1898,16 +1997,45 @@ static inline void qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, | |||
1898 | adapter->nic_ops->config_ipaddr(adapter, ip, cmd); | 1997 | adapter->nic_ops->config_ipaddr(adapter, ip, cmd); |
1899 | } | 1998 | } |
1900 | 1999 | ||
2000 | static inline bool qlcnic_check_multi_tx(struct qlcnic_adapter *adapter) | ||
2001 | { | ||
2002 | return test_bit(__QLCNIC_MULTI_TX_UNIQUE, &adapter->state); | ||
2003 | } | ||
2004 | |||
2005 | static inline void qlcnic_disable_multi_tx(struct qlcnic_adapter *adapter) | ||
2006 | { | ||
2007 | test_and_clear_bit(__QLCNIC_MULTI_TX_UNIQUE, &adapter->state); | ||
2008 | adapter->max_drv_tx_rings = 1; | ||
2009 | } | ||
2010 | |||
2011 | /* When operating in a muti tx mode, driver needs to write 0x1 | ||
2012 | * to src register, instead of 0x0 to disable receiving interrupt. | ||
2013 | */ | ||
1901 | static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring) | 2014 | static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring) |
1902 | { | 2015 | { |
1903 | writel(0, sds_ring->crb_intr_mask); | 2016 | struct qlcnic_adapter *adapter = sds_ring->adapter; |
2017 | |||
2018 | if (qlcnic_check_multi_tx(adapter) && | ||
2019 | !adapter->ahw->diag_test && | ||
2020 | (adapter->flags & QLCNIC_MSIX_ENABLED)) | ||
2021 | writel(0x1, sds_ring->crb_intr_mask); | ||
2022 | else | ||
2023 | writel(0, sds_ring->crb_intr_mask); | ||
1904 | } | 2024 | } |
1905 | 2025 | ||
2026 | /* When operating in a muti tx mode, driver needs to write 0x0 | ||
2027 | * to src register, instead of 0x1 to enable receiving interrupts. | ||
2028 | */ | ||
1906 | static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring) | 2029 | static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring) |
1907 | { | 2030 | { |
1908 | struct qlcnic_adapter *adapter = sds_ring->adapter; | 2031 | struct qlcnic_adapter *adapter = sds_ring->adapter; |
1909 | 2032 | ||
1910 | writel(0x1, sds_ring->crb_intr_mask); | 2033 | if (qlcnic_check_multi_tx(adapter) && |
2034 | !adapter->ahw->diag_test && | ||
2035 | (adapter->flags & QLCNIC_MSIX_ENABLED)) | ||
2036 | writel(0, sds_ring->crb_intr_mask); | ||
2037 | else | ||
2038 | writel(0x1, sds_ring->crb_intr_mask); | ||
1911 | 2039 | ||
1912 | if (!QLCNIC_IS_MSI_FAMILY(adapter)) | 2040 | if (!QLCNIC_IS_MSI_FAMILY(adapter)) |
1913 | writel(0xfbff, adapter->tgt_mask_reg); | 2041 | writel(0xfbff, adapter->tgt_mask_reg); |
@@ -1939,9 +2067,11 @@ extern const struct ethtool_ops qlcnic_ethtool_failed_ops; | |||
1939 | __func__, ##_args); \ | 2067 | __func__, ##_args); \ |
1940 | } while (0) | 2068 | } while (0) |
1941 | 2069 | ||
1942 | #define PCI_DEVICE_ID_QLOGIC_QLE834X 0x8030 | 2070 | #define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020 |
2071 | #define PCI_DEVICE_ID_QLOGIC_QLE834X 0x8030 | ||
1943 | #define PCI_DEVICE_ID_QLOGIC_VF_QLE834X 0x8430 | 2072 | #define PCI_DEVICE_ID_QLOGIC_VF_QLE834X 0x8430 |
1944 | #define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020 | 2073 | #define PCI_DEVICE_ID_QLOGIC_QLE844X 0x8040 |
2074 | #define PCI_DEVICE_ID_QLOGIC_VF_QLE844X 0x8440 | ||
1945 | 2075 | ||
1946 | static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter) | 2076 | static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter) |
1947 | { | 2077 | { |
@@ -1949,12 +2079,22 @@ static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter) | |||
1949 | return (device == PCI_DEVICE_ID_QLOGIC_QLE824X) ? true : false; | 2079 | return (device == PCI_DEVICE_ID_QLOGIC_QLE824X) ? true : false; |
1950 | } | 2080 | } |
1951 | 2081 | ||
2082 | static inline bool qlcnic_84xx_check(struct qlcnic_adapter *adapter) | ||
2083 | { | ||
2084 | unsigned short device = adapter->pdev->device; | ||
2085 | |||
2086 | return ((device == PCI_DEVICE_ID_QLOGIC_QLE844X) || | ||
2087 | (device == PCI_DEVICE_ID_QLOGIC_VF_QLE844X)) ? true : false; | ||
2088 | } | ||
2089 | |||
1952 | static inline bool qlcnic_83xx_check(struct qlcnic_adapter *adapter) | 2090 | static inline bool qlcnic_83xx_check(struct qlcnic_adapter *adapter) |
1953 | { | 2091 | { |
1954 | unsigned short device = adapter->pdev->device; | 2092 | unsigned short device = adapter->pdev->device; |
1955 | bool status; | 2093 | bool status; |
1956 | 2094 | ||
1957 | status = ((device == PCI_DEVICE_ID_QLOGIC_QLE834X) || | 2095 | status = ((device == PCI_DEVICE_ID_QLOGIC_QLE834X) || |
2096 | (device == PCI_DEVICE_ID_QLOGIC_QLE844X) || | ||
2097 | (device == PCI_DEVICE_ID_QLOGIC_VF_QLE844X) || | ||
1958 | (device == PCI_DEVICE_ID_QLOGIC_VF_QLE834X)) ? true : false; | 2098 | (device == PCI_DEVICE_ID_QLOGIC_VF_QLE834X)) ? true : false; |
1959 | 2099 | ||
1960 | return status; | 2100 | return status; |
@@ -1968,7 +2108,105 @@ static inline bool qlcnic_sriov_pf_check(struct qlcnic_adapter *adapter) | |||
1968 | static inline bool qlcnic_sriov_vf_check(struct qlcnic_adapter *adapter) | 2108 | static inline bool qlcnic_sriov_vf_check(struct qlcnic_adapter *adapter) |
1969 | { | 2109 | { |
1970 | unsigned short device = adapter->pdev->device; | 2110 | unsigned short device = adapter->pdev->device; |
2111 | bool status; | ||
2112 | |||
2113 | status = ((device == PCI_DEVICE_ID_QLOGIC_VF_QLE834X) || | ||
2114 | (device == PCI_DEVICE_ID_QLOGIC_VF_QLE844X)) ? true : false; | ||
2115 | |||
2116 | return status; | ||
2117 | } | ||
2118 | |||
2119 | static inline int qlcnic_dcb_get_hw_capability(struct qlcnic_adapter *adapter) | ||
2120 | { | ||
2121 | struct qlcnic_dcb *dcb = adapter->dcb; | ||
2122 | |||
2123 | if (dcb && dcb->ops->get_hw_capability) | ||
2124 | return dcb->ops->get_hw_capability(adapter); | ||
2125 | |||
2126 | return 0; | ||
2127 | } | ||
2128 | |||
2129 | static inline void qlcnic_dcb_free(struct qlcnic_adapter *adapter) | ||
2130 | { | ||
2131 | struct qlcnic_dcb *dcb = adapter->dcb; | ||
2132 | |||
2133 | if (dcb && dcb->ops->free) | ||
2134 | dcb->ops->free(adapter); | ||
2135 | } | ||
2136 | |||
2137 | static inline int qlcnic_dcb_attach(struct qlcnic_adapter *adapter) | ||
2138 | { | ||
2139 | struct qlcnic_dcb *dcb = adapter->dcb; | ||
2140 | |||
2141 | if (dcb && dcb->ops->attach) | ||
2142 | return dcb->ops->attach(adapter); | ||
2143 | |||
2144 | return 0; | ||
2145 | } | ||
2146 | |||
2147 | static inline int | ||
2148 | qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *adapter, char *buf) | ||
2149 | { | ||
2150 | struct qlcnic_dcb *dcb = adapter->dcb; | ||
2151 | |||
2152 | if (dcb && dcb->ops->query_hw_capability) | ||
2153 | return dcb->ops->query_hw_capability(adapter, buf); | ||
2154 | |||
2155 | return 0; | ||
2156 | } | ||
2157 | |||
2158 | static inline void qlcnic_dcb_get_info(struct qlcnic_adapter *adapter) | ||
2159 | { | ||
2160 | struct qlcnic_dcb *dcb = adapter->dcb; | ||
2161 | |||
2162 | if (dcb && dcb->ops->get_info) | ||
2163 | dcb->ops->get_info(adapter); | ||
2164 | } | ||
2165 | |||
2166 | static inline int | ||
2167 | qlcnic_dcb_query_cee_param(struct qlcnic_adapter *adapter, char *buf, u8 type) | ||
2168 | { | ||
2169 | struct qlcnic_dcb *dcb = adapter->dcb; | ||
2170 | |||
2171 | if (dcb && dcb->ops->query_cee_param) | ||
2172 | return dcb->ops->query_cee_param(adapter, buf, type); | ||
2173 | |||
2174 | return 0; | ||
2175 | } | ||
2176 | |||
2177 | static inline int qlcnic_dcb_get_cee_cfg(struct qlcnic_adapter *adapter) | ||
2178 | { | ||
2179 | struct qlcnic_dcb *dcb = adapter->dcb; | ||
2180 | |||
2181 | if (dcb && dcb->ops->get_cee_cfg) | ||
2182 | return dcb->ops->get_cee_cfg(adapter); | ||
2183 | |||
2184 | return 0; | ||
2185 | } | ||
2186 | |||
2187 | static inline void | ||
2188 | qlcnic_dcb_register_aen(struct qlcnic_adapter *adapter, u8 flag) | ||
2189 | { | ||
2190 | struct qlcnic_dcb *dcb = adapter->dcb; | ||
2191 | |||
2192 | if (dcb && dcb->ops->register_aen) | ||
2193 | dcb->ops->register_aen(adapter, flag); | ||
2194 | } | ||
2195 | |||
2196 | static inline void qlcnic_dcb_handle_aen(struct qlcnic_adapter *adapter, | ||
2197 | void *msg) | ||
2198 | { | ||
2199 | struct qlcnic_dcb *dcb = adapter->dcb; | ||
2200 | |||
2201 | if (dcb && dcb->ops->handle_aen) | ||
2202 | dcb->ops->handle_aen(adapter, msg); | ||
2203 | } | ||
2204 | |||
2205 | static inline void qlcnic_dcb_init_dcbnl_ops(struct qlcnic_adapter *adapter) | ||
2206 | { | ||
2207 | struct qlcnic_dcb *dcb = adapter->dcb; | ||
1971 | 2208 | ||
1972 | return (device == PCI_DEVICE_ID_QLOGIC_VF_QLE834X) ? true : false; | 2209 | if (dcb && dcb->ops->init_dcbnl_ops) |
2210 | dcb->ops->init_dcbnl_ops(adapter); | ||
1973 | } | 2211 | } |
1974 | #endif /* __QLCNIC_H_ */ | 2212 | #endif /* __QLCNIC_H_ */ |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c index 9d4bb7f83904..a1818dae47b6 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/ipv6.h> | 11 | #include <linux/ipv6.h> |
12 | #include <linux/ethtool.h> | 12 | #include <linux/ethtool.h> |
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include <linux/aer.h> | ||
14 | 15 | ||
15 | #define QLCNIC_MAX_TX_QUEUES 1 | 16 | #define QLCNIC_MAX_TX_QUEUES 1 |
16 | #define RSS_HASHTYPE_IP_TCP 0x3 | 17 | #define RSS_HASHTYPE_IP_TCP 0x3 |
@@ -67,6 +68,8 @@ static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = { | |||
67 | {QLCNIC_CMD_ADD_RCV_RINGS, 130, 26}, | 68 | {QLCNIC_CMD_ADD_RCV_RINGS, 130, 26}, |
68 | {QLCNIC_CMD_CONFIG_VPORT, 4, 4}, | 69 | {QLCNIC_CMD_CONFIG_VPORT, 4, 4}, |
69 | {QLCNIC_CMD_BC_EVENT_SETUP, 2, 1}, | 70 | {QLCNIC_CMD_BC_EVENT_SETUP, 2, 1}, |
71 | {QLCNIC_CMD_DCB_QUERY_CAP, 1, 2}, | ||
72 | {QLCNIC_CMD_DCB_QUERY_PARAM, 2, 50}, | ||
70 | }; | 73 | }; |
71 | 74 | ||
72 | const u32 qlcnic_83xx_ext_reg_tbl[] = { | 75 | const u32 qlcnic_83xx_ext_reg_tbl[] = { |
@@ -149,7 +152,7 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = { | |||
149 | .get_mac_address = qlcnic_83xx_get_mac_address, | 152 | .get_mac_address = qlcnic_83xx_get_mac_address, |
150 | .setup_intr = qlcnic_83xx_setup_intr, | 153 | .setup_intr = qlcnic_83xx_setup_intr, |
151 | .alloc_mbx_args = qlcnic_83xx_alloc_mbx_args, | 154 | .alloc_mbx_args = qlcnic_83xx_alloc_mbx_args, |
152 | .mbx_cmd = qlcnic_83xx_mbx_op, | 155 | .mbx_cmd = qlcnic_83xx_issue_cmd, |
153 | .get_func_no = qlcnic_83xx_get_func_no, | 156 | .get_func_no = qlcnic_83xx_get_func_no, |
154 | .api_lock = qlcnic_83xx_cam_lock, | 157 | .api_lock = qlcnic_83xx_cam_lock, |
155 | .api_unlock = qlcnic_83xx_cam_unlock, | 158 | .api_unlock = qlcnic_83xx_cam_unlock, |
@@ -175,6 +178,10 @@ static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = { | |||
175 | .get_board_info = qlcnic_83xx_get_port_info, | 178 | .get_board_info = qlcnic_83xx_get_port_info, |
176 | .set_mac_filter_count = qlcnic_83xx_set_mac_filter_count, | 179 | .set_mac_filter_count = qlcnic_83xx_set_mac_filter_count, |
177 | .free_mac_list = qlcnic_82xx_free_mac_list, | 180 | .free_mac_list = qlcnic_82xx_free_mac_list, |
181 | .io_error_detected = qlcnic_83xx_io_error_detected, | ||
182 | .io_slot_reset = qlcnic_83xx_io_slot_reset, | ||
183 | .io_resume = qlcnic_83xx_io_resume, | ||
184 | |||
178 | }; | 185 | }; |
179 | 186 | ||
180 | static struct qlcnic_nic_template qlcnic_83xx_ops = { | 187 | static struct qlcnic_nic_template qlcnic_83xx_ops = { |
@@ -261,7 +268,7 @@ int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *adapter, ulong addr, | |||
261 | } | 268 | } |
262 | } | 269 | } |
263 | 270 | ||
264 | int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr) | 271 | int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr, int txq) |
265 | { | 272 | { |
266 | int err, i, num_msix; | 273 | int err, i, num_msix; |
267 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 274 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
@@ -362,6 +369,10 @@ static inline void qlcnic_83xx_get_mbx_data(struct qlcnic_adapter *adapter, | |||
362 | struct qlcnic_cmd_args *cmd) | 369 | struct qlcnic_cmd_args *cmd) |
363 | { | 370 | { |
364 | int i; | 371 | int i; |
372 | |||
373 | if (cmd->op_type == QLC_83XX_MBX_POST_BC_OP) | ||
374 | return; | ||
375 | |||
365 | for (i = 0; i < cmd->rsp.num; i++) | 376 | for (i = 0; i < cmd->rsp.num; i++) |
366 | cmd->rsp.arg[i] = readl(QLCNIC_MBX_FW(adapter->ahw, i)); | 377 | cmd->rsp.arg[i] = readl(QLCNIC_MBX_FW(adapter->ahw, i)); |
367 | } | 378 | } |
@@ -398,24 +409,33 @@ irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *adapter) | |||
398 | return IRQ_HANDLED; | 409 | return IRQ_HANDLED; |
399 | } | 410 | } |
400 | 411 | ||
412 | static inline void qlcnic_83xx_notify_mbx_response(struct qlcnic_mailbox *mbx) | ||
413 | { | ||
414 | atomic_set(&mbx->rsp_status, QLC_83XX_MBX_RESPONSE_ARRIVED); | ||
415 | complete(&mbx->completion); | ||
416 | } | ||
417 | |||
401 | static void qlcnic_83xx_poll_process_aen(struct qlcnic_adapter *adapter) | 418 | static void qlcnic_83xx_poll_process_aen(struct qlcnic_adapter *adapter) |
402 | { | 419 | { |
403 | u32 resp, event; | 420 | u32 resp, event, rsp_status = QLC_83XX_MBX_RESPONSE_ARRIVED; |
421 | struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; | ||
404 | unsigned long flags; | 422 | unsigned long flags; |
405 | 423 | ||
406 | spin_lock_irqsave(&adapter->ahw->mbx_lock, flags); | 424 | spin_lock_irqsave(&mbx->aen_lock, flags); |
407 | |||
408 | resp = QLCRDX(adapter->ahw, QLCNIC_FW_MBX_CTRL); | 425 | resp = QLCRDX(adapter->ahw, QLCNIC_FW_MBX_CTRL); |
409 | if (!(resp & QLCNIC_SET_OWNER)) | 426 | if (!(resp & QLCNIC_SET_OWNER)) |
410 | goto out; | 427 | goto out; |
411 | 428 | ||
412 | event = readl(QLCNIC_MBX_FW(adapter->ahw, 0)); | 429 | event = readl(QLCNIC_MBX_FW(adapter->ahw, 0)); |
413 | if (event & QLCNIC_MBX_ASYNC_EVENT) | 430 | if (event & QLCNIC_MBX_ASYNC_EVENT) { |
414 | __qlcnic_83xx_process_aen(adapter); | 431 | __qlcnic_83xx_process_aen(adapter); |
415 | 432 | } else { | |
433 | if (atomic_read(&mbx->rsp_status) != rsp_status) | ||
434 | qlcnic_83xx_notify_mbx_response(mbx); | ||
435 | } | ||
416 | out: | 436 | out: |
417 | qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter); | 437 | qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter); |
418 | spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags); | 438 | spin_unlock_irqrestore(&mbx->aen_lock, flags); |
419 | } | 439 | } |
420 | 440 | ||
421 | irqreturn_t qlcnic_83xx_intr(int irq, void *data) | 441 | irqreturn_t qlcnic_83xx_intr(int irq, void *data) |
@@ -515,7 +535,7 @@ int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter) | |||
515 | } | 535 | } |
516 | 536 | ||
517 | /* Enable mailbox interrupt */ | 537 | /* Enable mailbox interrupt */ |
518 | qlcnic_83xx_enable_mbx_intrpt(adapter); | 538 | qlcnic_83xx_enable_mbx_interrupt(adapter); |
519 | 539 | ||
520 | return err; | 540 | return err; |
521 | } | 541 | } |
@@ -628,7 +648,7 @@ void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *adapter) | |||
628 | ahw->max_uc_count = count; | 648 | ahw->max_uc_count = count; |
629 | } | 649 | } |
630 | 650 | ||
631 | void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *adapter) | 651 | void qlcnic_83xx_enable_mbx_interrupt(struct qlcnic_adapter *adapter) |
632 | { | 652 | { |
633 | u32 val; | 653 | u32 val; |
634 | 654 | ||
@@ -682,11 +702,14 @@ static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter, | |||
682 | static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter, | 702 | static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter, |
683 | u32 data[]); | 703 | u32 data[]); |
684 | 704 | ||
685 | static void qlcnic_dump_mbx(struct qlcnic_adapter *adapter, | 705 | void qlcnic_dump_mbx(struct qlcnic_adapter *adapter, |
686 | struct qlcnic_cmd_args *cmd) | 706 | struct qlcnic_cmd_args *cmd) |
687 | { | 707 | { |
688 | int i; | 708 | int i; |
689 | 709 | ||
710 | if (cmd->op_type == QLC_83XX_MBX_POST_BC_OP) | ||
711 | return; | ||
712 | |||
690 | dev_info(&adapter->pdev->dev, | 713 | dev_info(&adapter->pdev->dev, |
691 | "Host MBX regs(%d)\n", cmd->req.num); | 714 | "Host MBX regs(%d)\n", cmd->req.num); |
692 | for (i = 0; i < cmd->req.num; i++) { | 715 | for (i = 0; i < cmd->req.num; i++) { |
@@ -705,120 +728,73 @@ static void qlcnic_dump_mbx(struct qlcnic_adapter *adapter, | |||
705 | pr_info("\n"); | 728 | pr_info("\n"); |
706 | } | 729 | } |
707 | 730 | ||
708 | /* Mailbox response for mac rcode */ | 731 | static void qlcnic_83xx_poll_for_mbx_completion(struct qlcnic_adapter *adapter, |
709 | u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *adapter) | 732 | struct qlcnic_cmd_args *cmd) |
710 | { | 733 | { |
711 | u32 fw_data; | 734 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
712 | u8 mac_cmd_rcode; | 735 | int opcode = LSW(cmd->req.arg[0]); |
736 | unsigned long max_loops; | ||
713 | 737 | ||
714 | fw_data = readl(QLCNIC_MBX_FW(adapter->ahw, 2)); | 738 | max_loops = cmd->total_cmds * QLC_83XX_MBX_CMD_LOOP; |
715 | mac_cmd_rcode = (u8)fw_data; | ||
716 | if (mac_cmd_rcode == QLC_83XX_NO_NIC_RESOURCE || | ||
717 | mac_cmd_rcode == QLC_83XX_MAC_PRESENT || | ||
718 | mac_cmd_rcode == QLC_83XX_MAC_ABSENT) | ||
719 | return QLCNIC_RCODE_SUCCESS; | ||
720 | return 1; | ||
721 | } | ||
722 | 739 | ||
723 | u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *adapter, u32 *wait_time) | 740 | for (; max_loops; max_loops--) { |
724 | { | 741 | if (atomic_read(&cmd->rsp_status) == |
725 | u32 data; | 742 | QLC_83XX_MBX_RESPONSE_ARRIVED) |
726 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 743 | return; |
727 | /* wait for mailbox completion */ | 744 | |
728 | do { | 745 | udelay(1); |
729 | data = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL); | 746 | } |
730 | if (++(*wait_time) > QLCNIC_MBX_TIMEOUT) { | 747 | |
731 | data = QLCNIC_RCODE_TIMEOUT; | 748 | dev_err(&adapter->pdev->dev, |
732 | break; | 749 | "%s: Mailbox command timed out, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n", |
733 | } | 750 | __func__, opcode, cmd->type, ahw->pci_func, ahw->op_mode); |
734 | mdelay(1); | 751 | flush_workqueue(ahw->mailbox->work_q); |
735 | } while (!data); | 752 | return; |
736 | return data; | ||
737 | } | 753 | } |
738 | 754 | ||
739 | int qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter, | 755 | int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *adapter, |
740 | struct qlcnic_cmd_args *cmd) | 756 | struct qlcnic_cmd_args *cmd) |
741 | { | 757 | { |
742 | int i; | 758 | struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; |
743 | u16 opcode; | ||
744 | u8 mbx_err_code; | ||
745 | unsigned long flags; | ||
746 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 759 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
747 | u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, wait_time = 0; | 760 | int cmd_type, err, opcode; |
761 | unsigned long timeout; | ||
748 | 762 | ||
749 | opcode = LSW(cmd->req.arg[0]); | 763 | opcode = LSW(cmd->req.arg[0]); |
750 | if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) { | 764 | cmd_type = cmd->type; |
751 | dev_info(&adapter->pdev->dev, | 765 | err = mbx->ops->enqueue_cmd(adapter, cmd, &timeout); |
752 | "Mailbox cmd attempted, 0x%x\n", opcode); | 766 | if (err) { |
753 | dev_info(&adapter->pdev->dev, "Mailbox detached\n"); | 767 | dev_err(&adapter->pdev->dev, |
754 | return 0; | 768 | "%s: Mailbox not available, cmd_op=0x%x, cmd_context=0x%x, pci_func=0x%x, op_mode=0x%x\n", |
769 | __func__, opcode, cmd->type, ahw->pci_func, | ||
770 | ahw->op_mode); | ||
771 | return err; | ||
755 | } | 772 | } |
756 | 773 | ||
757 | spin_lock_irqsave(&adapter->ahw->mbx_lock, flags); | 774 | switch (cmd_type) { |
758 | mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL); | 775 | case QLC_83XX_MBX_CMD_WAIT: |
759 | 776 | if (!wait_for_completion_timeout(&cmd->completion, timeout)) { | |
760 | if (mbx_val) { | ||
761 | QLCDB(adapter, DRV, | ||
762 | "Mailbox cmd attempted, 0x%x\n", opcode); | ||
763 | QLCDB(adapter, DRV, | ||
764 | "Mailbox not available, 0x%x, collect FW dump\n", | ||
765 | mbx_val); | ||
766 | cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT; | ||
767 | spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags); | ||
768 | return cmd->rsp.arg[0]; | ||
769 | } | ||
770 | |||
771 | /* Fill in mailbox registers */ | ||
772 | mbx_cmd = cmd->req.arg[0]; | ||
773 | writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0)); | ||
774 | for (i = 1; i < cmd->req.num; i++) | ||
775 | writel(cmd->req.arg[i], QLCNIC_MBX_HOST(ahw, i)); | ||
776 | |||
777 | /* Signal FW about the impending command */ | ||
778 | QLCWRX(ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER); | ||
779 | poll: | ||
780 | rsp = qlcnic_83xx_mbx_poll(adapter, &wait_time); | ||
781 | if (rsp != QLCNIC_RCODE_TIMEOUT) { | ||
782 | /* Get the FW response data */ | ||
783 | fw_data = readl(QLCNIC_MBX_FW(ahw, 0)); | ||
784 | if (fw_data & QLCNIC_MBX_ASYNC_EVENT) { | ||
785 | __qlcnic_83xx_process_aen(adapter); | ||
786 | goto poll; | ||
787 | } | ||
788 | mbx_err_code = QLCNIC_MBX_STATUS(fw_data); | ||
789 | rsp_num = QLCNIC_MBX_NUM_REGS(fw_data); | ||
790 | opcode = QLCNIC_MBX_RSP(fw_data); | ||
791 | qlcnic_83xx_get_mbx_data(adapter, cmd); | ||
792 | |||
793 | switch (mbx_err_code) { | ||
794 | case QLCNIC_MBX_RSP_OK: | ||
795 | case QLCNIC_MBX_PORT_RSP_OK: | ||
796 | rsp = QLCNIC_RCODE_SUCCESS; | ||
797 | break; | ||
798 | default: | ||
799 | if (opcode == QLCNIC_CMD_CONFIG_MAC_VLAN) { | ||
800 | rsp = qlcnic_83xx_mac_rcode(adapter); | ||
801 | if (!rsp) | ||
802 | goto out; | ||
803 | } | ||
804 | dev_err(&adapter->pdev->dev, | 777 | dev_err(&adapter->pdev->dev, |
805 | "MBX command 0x%x failed with err:0x%x\n", | 778 | "%s: Mailbox command timed out, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n", |
806 | opcode, mbx_err_code); | 779 | __func__, opcode, cmd_type, ahw->pci_func, |
807 | rsp = mbx_err_code; | 780 | ahw->op_mode); |
808 | qlcnic_dump_mbx(adapter, cmd); | 781 | flush_workqueue(mbx->work_q); |
809 | break; | ||
810 | } | 782 | } |
811 | goto out; | 783 | break; |
784 | case QLC_83XX_MBX_CMD_NO_WAIT: | ||
785 | return 0; | ||
786 | case QLC_83XX_MBX_CMD_BUSY_WAIT: | ||
787 | qlcnic_83xx_poll_for_mbx_completion(adapter, cmd); | ||
788 | break; | ||
789 | default: | ||
790 | dev_err(&adapter->pdev->dev, | ||
791 | "%s: Invalid mailbox command, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n", | ||
792 | __func__, opcode, cmd_type, ahw->pci_func, | ||
793 | ahw->op_mode); | ||
794 | qlcnic_83xx_detach_mailbox_work(adapter); | ||
812 | } | 795 | } |
813 | 796 | ||
814 | dev_err(&adapter->pdev->dev, "MBX command 0x%x timed out\n", | 797 | return cmd->rsp_opcode; |
815 | QLCNIC_MBX_RSP(mbx_cmd)); | ||
816 | rsp = QLCNIC_RCODE_TIMEOUT; | ||
817 | out: | ||
818 | /* clear fw mbx control register */ | ||
819 | QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER); | ||
820 | spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags); | ||
821 | return rsp; | ||
822 | } | 798 | } |
823 | 799 | ||
824 | int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx, | 800 | int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx, |
@@ -828,6 +804,7 @@ int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx, | |||
828 | u32 temp; | 804 | u32 temp; |
829 | const struct qlcnic_mailbox_metadata *mbx_tbl; | 805 | const struct qlcnic_mailbox_metadata *mbx_tbl; |
830 | 806 | ||
807 | memset(mbx, 0, sizeof(struct qlcnic_cmd_args)); | ||
831 | mbx_tbl = qlcnic_83xx_mbx_tbl; | 808 | mbx_tbl = qlcnic_83xx_mbx_tbl; |
832 | size = ARRAY_SIZE(qlcnic_83xx_mbx_tbl); | 809 | size = ARRAY_SIZE(qlcnic_83xx_mbx_tbl); |
833 | for (i = 0; i < size; i++) { | 810 | for (i = 0; i < size; i++) { |
@@ -850,6 +827,7 @@ int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx, | |||
850 | memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num); | 827 | memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num); |
851 | temp = adapter->ahw->fw_hal_version << 29; | 828 | temp = adapter->ahw->fw_hal_version << 29; |
852 | mbx->req.arg[0] = (type | (mbx->req.num << 16) | temp); | 829 | mbx->req.arg[0] = (type | (mbx->req.num << 16) | temp); |
830 | mbx->cmd_op = type; | ||
853 | return 0; | 831 | return 0; |
854 | } | 832 | } |
855 | } | 833 | } |
@@ -888,9 +866,9 @@ static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter, | |||
888 | 866 | ||
889 | void __qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter) | 867 | void __qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter) |
890 | { | 868 | { |
869 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
891 | u32 event[QLC_83XX_MBX_AEN_CNT]; | 870 | u32 event[QLC_83XX_MBX_AEN_CNT]; |
892 | int i; | 871 | int i; |
893 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
894 | 872 | ||
895 | for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++) | 873 | for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++) |
896 | event[i] = readl(QLCNIC_MBX_FW(ahw, i)); | 874 | event[i] = readl(QLCNIC_MBX_FW(ahw, i)); |
@@ -910,6 +888,7 @@ void __qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter) | |||
910 | &adapter->idc_aen_work, 0); | 888 | &adapter->idc_aen_work, 0); |
911 | break; | 889 | break; |
912 | case QLCNIC_MBX_TIME_EXTEND_EVENT: | 890 | case QLCNIC_MBX_TIME_EXTEND_EVENT: |
891 | ahw->extend_lb_time = event[1] >> 8 & 0xf; | ||
913 | break; | 892 | break; |
914 | case QLCNIC_MBX_BC_EVENT: | 893 | case QLCNIC_MBX_BC_EVENT: |
915 | qlcnic_sriov_handle_bc_event(adapter, event[1]); | 894 | qlcnic_sriov_handle_bc_event(adapter, event[1]); |
@@ -922,6 +901,9 @@ void __qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter) | |||
922 | dev_info(&adapter->pdev->dev, "SFP Removed AEN:0x%x.\n", | 901 | dev_info(&adapter->pdev->dev, "SFP Removed AEN:0x%x.\n", |
923 | QLCNIC_MBX_RSP(event[0])); | 902 | QLCNIC_MBX_RSP(event[0])); |
924 | break; | 903 | break; |
904 | case QLCNIC_MBX_DCBX_CONFIG_CHANGE_EVENT: | ||
905 | qlcnic_dcb_handle_aen(adapter, (void *)&event[1]); | ||
906 | break; | ||
925 | default: | 907 | default: |
926 | dev_dbg(&adapter->pdev->dev, "Unsupported AEN:0x%x.\n", | 908 | dev_dbg(&adapter->pdev->dev, "Unsupported AEN:0x%x.\n", |
927 | QLCNIC_MBX_RSP(event[0])); | 909 | QLCNIC_MBX_RSP(event[0])); |
@@ -933,20 +915,23 @@ void __qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter) | |||
933 | 915 | ||
934 | static void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter) | 916 | static void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter) |
935 | { | 917 | { |
918 | u32 resp, event, rsp_status = QLC_83XX_MBX_RESPONSE_ARRIVED; | ||
936 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 919 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
937 | u32 resp, event; | 920 | struct qlcnic_mailbox *mbx = ahw->mailbox; |
938 | unsigned long flags; | 921 | unsigned long flags; |
939 | 922 | ||
940 | spin_lock_irqsave(&ahw->mbx_lock, flags); | 923 | spin_lock_irqsave(&mbx->aen_lock, flags); |
941 | |||
942 | resp = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL); | 924 | resp = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL); |
943 | if (resp & QLCNIC_SET_OWNER) { | 925 | if (resp & QLCNIC_SET_OWNER) { |
944 | event = readl(QLCNIC_MBX_FW(ahw, 0)); | 926 | event = readl(QLCNIC_MBX_FW(ahw, 0)); |
945 | if (event & QLCNIC_MBX_ASYNC_EVENT) | 927 | if (event & QLCNIC_MBX_ASYNC_EVENT) { |
946 | __qlcnic_83xx_process_aen(adapter); | 928 | __qlcnic_83xx_process_aen(adapter); |
929 | } else { | ||
930 | if (atomic_read(&mbx->rsp_status) != rsp_status) | ||
931 | qlcnic_83xx_notify_mbx_response(mbx); | ||
932 | } | ||
947 | } | 933 | } |
948 | 934 | spin_unlock_irqrestore(&mbx->aen_lock, flags); | |
949 | spin_unlock_irqrestore(&ahw->mbx_lock, flags); | ||
950 | } | 935 | } |
951 | 936 | ||
952 | static void qlcnic_83xx_mbx_poll_work(struct work_struct *work) | 937 | static void qlcnic_83xx_mbx_poll_work(struct work_struct *work) |
@@ -969,6 +954,7 @@ void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *adapter) | |||
969 | return; | 954 | return; |
970 | 955 | ||
971 | INIT_DELAYED_WORK(&adapter->mbx_poll_work, qlcnic_83xx_mbx_poll_work); | 956 | INIT_DELAYED_WORK(&adapter->mbx_poll_work, qlcnic_83xx_mbx_poll_work); |
957 | queue_delayed_work(adapter->qlcnic_wq, &adapter->mbx_poll_work, 0); | ||
972 | } | 958 | } |
973 | 959 | ||
974 | void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *adapter) | 960 | void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *adapter) |
@@ -1355,8 +1341,10 @@ static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test, | |||
1355 | 1341 | ||
1356 | if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) { | 1342 | if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) { |
1357 | /* disable and free mailbox interrupt */ | 1343 | /* disable and free mailbox interrupt */ |
1358 | if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) | 1344 | if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) { |
1345 | qlcnic_83xx_enable_mbx_poll(adapter); | ||
1359 | qlcnic_83xx_free_mbx_intr(adapter); | 1346 | qlcnic_83xx_free_mbx_intr(adapter); |
1347 | } | ||
1360 | adapter->ahw->loopback_state = 0; | 1348 | adapter->ahw->loopback_state = 0; |
1361 | adapter->ahw->hw_ops->setup_link_event(adapter, 1); | 1349 | adapter->ahw->hw_ops->setup_link_event(adapter, 1); |
1362 | } | 1350 | } |
@@ -1377,6 +1365,8 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev, | |||
1377 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | 1365 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
1378 | sds_ring = &adapter->recv_ctx->sds_rings[ring]; | 1366 | sds_ring = &adapter->recv_ctx->sds_rings[ring]; |
1379 | qlcnic_83xx_disable_intr(adapter, sds_ring); | 1367 | qlcnic_83xx_disable_intr(adapter, sds_ring); |
1368 | if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) | ||
1369 | qlcnic_83xx_enable_mbx_poll(adapter); | ||
1380 | } | 1370 | } |
1381 | } | 1371 | } |
1382 | 1372 | ||
@@ -1386,6 +1376,7 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev, | |||
1386 | if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) { | 1376 | if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) { |
1387 | if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) { | 1377 | if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) { |
1388 | err = qlcnic_83xx_setup_mbx_intr(adapter); | 1378 | err = qlcnic_83xx_setup_mbx_intr(adapter); |
1379 | qlcnic_83xx_disable_mbx_poll(adapter); | ||
1389 | if (err) { | 1380 | if (err) { |
1390 | dev_err(&adapter->pdev->dev, | 1381 | dev_err(&adapter->pdev->dev, |
1391 | "%s: failed to setup mbx interrupt\n", | 1382 | "%s: failed to setup mbx interrupt\n", |
@@ -1402,6 +1393,10 @@ static void qlcnic_83xx_diag_free_res(struct net_device *netdev, | |||
1402 | 1393 | ||
1403 | if (netif_running(netdev)) | 1394 | if (netif_running(netdev)) |
1404 | __qlcnic_up(adapter, netdev); | 1395 | __qlcnic_up(adapter, netdev); |
1396 | |||
1397 | if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST && | ||
1398 | !(adapter->flags & QLCNIC_MSIX_ENABLED)) | ||
1399 | qlcnic_83xx_disable_mbx_poll(adapter); | ||
1405 | out: | 1400 | out: |
1406 | netif_device_attach(netdev); | 1401 | netif_device_attach(netdev); |
1407 | } | 1402 | } |
@@ -1619,26 +1614,33 @@ static void qlcnic_83xx_set_interface_id_promisc(struct qlcnic_adapter *adapter, | |||
1619 | 1614 | ||
1620 | int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) | 1615 | int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) |
1621 | { | 1616 | { |
1622 | int err; | 1617 | struct qlcnic_cmd_args *cmd = NULL; |
1623 | u32 temp = 0; | 1618 | u32 temp = 0; |
1624 | struct qlcnic_cmd_args cmd; | 1619 | int err; |
1625 | 1620 | ||
1626 | if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED) | 1621 | if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED) |
1627 | return -EIO; | 1622 | return -EIO; |
1628 | 1623 | ||
1629 | err = qlcnic_alloc_mbx_args(&cmd, adapter, | 1624 | cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC); |
1625 | if (!cmd) | ||
1626 | return -ENOMEM; | ||
1627 | |||
1628 | err = qlcnic_alloc_mbx_args(cmd, adapter, | ||
1630 | QLCNIC_CMD_CONFIGURE_MAC_RX_MODE); | 1629 | QLCNIC_CMD_CONFIGURE_MAC_RX_MODE); |
1631 | if (err) | 1630 | if (err) |
1632 | return err; | 1631 | goto out; |
1633 | 1632 | ||
1633 | cmd->type = QLC_83XX_MBX_CMD_NO_WAIT; | ||
1634 | qlcnic_83xx_set_interface_id_promisc(adapter, &temp); | 1634 | qlcnic_83xx_set_interface_id_promisc(adapter, &temp); |
1635 | cmd.req.arg[1] = (mode ? 1 : 0) | temp; | 1635 | cmd->req.arg[1] = (mode ? 1 : 0) | temp; |
1636 | err = qlcnic_issue_cmd(adapter, &cmd); | 1636 | err = qlcnic_issue_cmd(adapter, cmd); |
1637 | if (err) | 1637 | if (!err) |
1638 | dev_info(&adapter->pdev->dev, | 1638 | return err; |
1639 | "Promiscous mode config failed\n"); | ||
1640 | 1639 | ||
1641 | qlcnic_free_mbx_args(&cmd); | 1640 | qlcnic_free_mbx_args(cmd); |
1641 | |||
1642 | out: | ||
1643 | kfree(cmd); | ||
1642 | return err; | 1644 | return err; |
1643 | } | 1645 | } |
1644 | 1646 | ||
@@ -1651,7 +1653,7 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode) | |||
1651 | if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { | 1653 | if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { |
1652 | netdev_warn(netdev, | 1654 | netdev_warn(netdev, |
1653 | "Loopback test not supported in non privileged mode\n"); | 1655 | "Loopback test not supported in non privileged mode\n"); |
1654 | return ret; | 1656 | return -ENOTSUPP; |
1655 | } | 1657 | } |
1656 | 1658 | ||
1657 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { | 1659 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { |
@@ -1679,19 +1681,17 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode) | |||
1679 | /* Poll for link up event before running traffic */ | 1681 | /* Poll for link up event before running traffic */ |
1680 | do { | 1682 | do { |
1681 | msleep(QLC_83XX_LB_MSLEEP_COUNT); | 1683 | msleep(QLC_83XX_LB_MSLEEP_COUNT); |
1682 | if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) | ||
1683 | qlcnic_83xx_process_aen(adapter); | ||
1684 | 1684 | ||
1685 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { | 1685 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { |
1686 | netdev_info(netdev, | 1686 | netdev_info(netdev, |
1687 | "Device is resetting, free LB test resources\n"); | 1687 | "Device is resetting, free LB test resources\n"); |
1688 | ret = -EIO; | 1688 | ret = -EBUSY; |
1689 | goto free_diag_res; | 1689 | goto free_diag_res; |
1690 | } | 1690 | } |
1691 | if (loop++ > QLC_83XX_LB_WAIT_COUNT) { | 1691 | if (loop++ > QLC_83XX_LB_WAIT_COUNT) { |
1692 | netdev_info(netdev, | 1692 | netdev_info(netdev, |
1693 | "Firmware didn't sent link up event to loopback request\n"); | 1693 | "Firmware didn't sent link up event to loopback request\n"); |
1694 | ret = -QLCNIC_FW_NOT_RESPOND; | 1694 | ret = -ETIMEDOUT; |
1695 | qlcnic_83xx_clear_lb_mode(adapter, mode); | 1695 | qlcnic_83xx_clear_lb_mode(adapter, mode); |
1696 | goto free_diag_res; | 1696 | goto free_diag_res; |
1697 | } | 1697 | } |
@@ -1700,7 +1700,7 @@ int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode) | |||
1700 | /* Make sure carrier is off and queue is stopped during loopback */ | 1700 | /* Make sure carrier is off and queue is stopped during loopback */ |
1701 | if (netif_running(netdev)) { | 1701 | if (netif_running(netdev)) { |
1702 | netif_carrier_off(netdev); | 1702 | netif_carrier_off(netdev); |
1703 | netif_stop_queue(netdev); | 1703 | netif_tx_stop_all_queues(netdev); |
1704 | } | 1704 | } |
1705 | 1705 | ||
1706 | ret = qlcnic_do_lb_test(adapter, mode); | 1706 | ret = qlcnic_do_lb_test(adapter, mode); |
@@ -1716,18 +1716,42 @@ fail_diag_alloc: | |||
1716 | return ret; | 1716 | return ret; |
1717 | } | 1717 | } |
1718 | 1718 | ||
1719 | static void qlcnic_extend_lb_idc_cmpltn_wait(struct qlcnic_adapter *adapter, | ||
1720 | u32 *max_wait_count) | ||
1721 | { | ||
1722 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
1723 | int temp; | ||
1724 | |||
1725 | netdev_info(adapter->netdev, "Recieved loopback IDC time extend event for 0x%x seconds\n", | ||
1726 | ahw->extend_lb_time); | ||
1727 | temp = ahw->extend_lb_time * 1000; | ||
1728 | *max_wait_count += temp / QLC_83XX_LB_MSLEEP_COUNT; | ||
1729 | ahw->extend_lb_time = 0; | ||
1730 | } | ||
1731 | |||
1719 | int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode) | 1732 | int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode) |
1720 | { | 1733 | { |
1721 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 1734 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
1722 | struct net_device *netdev = adapter->netdev; | 1735 | struct net_device *netdev = adapter->netdev; |
1736 | u32 config, max_wait_count; | ||
1723 | int status = 0, loop = 0; | 1737 | int status = 0, loop = 0; |
1724 | u32 config; | ||
1725 | 1738 | ||
1739 | ahw->extend_lb_time = 0; | ||
1740 | max_wait_count = QLC_83XX_LB_WAIT_COUNT; | ||
1726 | status = qlcnic_83xx_get_port_config(adapter); | 1741 | status = qlcnic_83xx_get_port_config(adapter); |
1727 | if (status) | 1742 | if (status) |
1728 | return status; | 1743 | return status; |
1729 | 1744 | ||
1730 | config = ahw->port_config; | 1745 | config = ahw->port_config; |
1746 | |||
1747 | /* Check if port is already in loopback mode */ | ||
1748 | if ((config & QLC_83XX_CFG_LOOPBACK_HSS) || | ||
1749 | (config & QLC_83XX_CFG_LOOPBACK_EXT)) { | ||
1750 | netdev_err(netdev, | ||
1751 | "Port already in Loopback mode.\n"); | ||
1752 | return -EINPROGRESS; | ||
1753 | } | ||
1754 | |||
1731 | set_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); | 1755 | set_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); |
1732 | 1756 | ||
1733 | if (mode == QLCNIC_ILB_MODE) | 1757 | if (mode == QLCNIC_ILB_MODE) |
@@ -1748,21 +1772,24 @@ int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode) | |||
1748 | /* Wait for Link and IDC Completion AEN */ | 1772 | /* Wait for Link and IDC Completion AEN */ |
1749 | do { | 1773 | do { |
1750 | msleep(QLC_83XX_LB_MSLEEP_COUNT); | 1774 | msleep(QLC_83XX_LB_MSLEEP_COUNT); |
1751 | if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) | ||
1752 | qlcnic_83xx_process_aen(adapter); | ||
1753 | 1775 | ||
1754 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { | 1776 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { |
1755 | netdev_info(netdev, | 1777 | netdev_info(netdev, |
1756 | "Device is resetting, free LB test resources\n"); | 1778 | "Device is resetting, free LB test resources\n"); |
1757 | clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); | 1779 | clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); |
1758 | return -EIO; | 1780 | return -EBUSY; |
1759 | } | 1781 | } |
1760 | if (loop++ > QLC_83XX_LB_WAIT_COUNT) { | 1782 | |
1761 | netdev_err(netdev, | 1783 | if (ahw->extend_lb_time) |
1762 | "Did not receive IDC completion AEN\n"); | 1784 | qlcnic_extend_lb_idc_cmpltn_wait(adapter, |
1785 | &max_wait_count); | ||
1786 | |||
1787 | if (loop++ > max_wait_count) { | ||
1788 | netdev_err(netdev, "%s: Did not receive loopback IDC completion AEN\n", | ||
1789 | __func__); | ||
1763 | clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); | 1790 | clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); |
1764 | qlcnic_83xx_clear_lb_mode(adapter, mode); | 1791 | qlcnic_83xx_clear_lb_mode(adapter, mode); |
1765 | return -EIO; | 1792 | return -ETIMEDOUT; |
1766 | } | 1793 | } |
1767 | } while (test_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status)); | 1794 | } while (test_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status)); |
1768 | 1795 | ||
@@ -1774,10 +1801,12 @@ int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode) | |||
1774 | int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode) | 1801 | int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode) |
1775 | { | 1802 | { |
1776 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 1803 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
1804 | u32 config = ahw->port_config, max_wait_count; | ||
1777 | struct net_device *netdev = adapter->netdev; | 1805 | struct net_device *netdev = adapter->netdev; |
1778 | int status = 0, loop = 0; | 1806 | int status = 0, loop = 0; |
1779 | u32 config = ahw->port_config; | ||
1780 | 1807 | ||
1808 | ahw->extend_lb_time = 0; | ||
1809 | max_wait_count = QLC_83XX_LB_WAIT_COUNT; | ||
1781 | set_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); | 1810 | set_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); |
1782 | if (mode == QLCNIC_ILB_MODE) | 1811 | if (mode == QLCNIC_ILB_MODE) |
1783 | ahw->port_config &= ~QLC_83XX_CFG_LOOPBACK_HSS; | 1812 | ahw->port_config &= ~QLC_83XX_CFG_LOOPBACK_HSS; |
@@ -1797,21 +1826,23 @@ int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode) | |||
1797 | /* Wait for Link and IDC Completion AEN */ | 1826 | /* Wait for Link and IDC Completion AEN */ |
1798 | do { | 1827 | do { |
1799 | msleep(QLC_83XX_LB_MSLEEP_COUNT); | 1828 | msleep(QLC_83XX_LB_MSLEEP_COUNT); |
1800 | if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) | ||
1801 | qlcnic_83xx_process_aen(adapter); | ||
1802 | 1829 | ||
1803 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { | 1830 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) { |
1804 | netdev_info(netdev, | 1831 | netdev_info(netdev, |
1805 | "Device is resetting, free LB test resources\n"); | 1832 | "Device is resetting, free LB test resources\n"); |
1806 | clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); | 1833 | clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); |
1807 | return -EIO; | 1834 | return -EBUSY; |
1808 | } | 1835 | } |
1809 | 1836 | ||
1810 | if (loop++ > QLC_83XX_LB_WAIT_COUNT) { | 1837 | if (ahw->extend_lb_time) |
1811 | netdev_err(netdev, | 1838 | qlcnic_extend_lb_idc_cmpltn_wait(adapter, |
1812 | "Did not receive IDC completion AEN\n"); | 1839 | &max_wait_count); |
1840 | |||
1841 | if (loop++ > max_wait_count) { | ||
1842 | netdev_err(netdev, "%s: Did not receive loopback IDC completion AEN\n", | ||
1843 | __func__); | ||
1813 | clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); | 1844 | clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); |
1814 | return -EIO; | 1845 | return -ETIMEDOUT; |
1815 | } | 1846 | } |
1816 | } while (test_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status)); | 1847 | } while (test_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status)); |
1817 | 1848 | ||
@@ -1950,25 +1981,31 @@ static void qlcnic_83xx_set_interface_id_macaddr(struct qlcnic_adapter *adapter, | |||
1950 | int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, | 1981 | int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, |
1951 | u16 vlan_id, u8 op) | 1982 | u16 vlan_id, u8 op) |
1952 | { | 1983 | { |
1953 | int err; | 1984 | struct qlcnic_cmd_args *cmd = NULL; |
1954 | u32 *buf, temp = 0; | ||
1955 | struct qlcnic_cmd_args cmd; | ||
1956 | struct qlcnic_macvlan_mbx mv; | 1985 | struct qlcnic_macvlan_mbx mv; |
1986 | u32 *buf, temp = 0; | ||
1987 | int err; | ||
1957 | 1988 | ||
1958 | if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED) | 1989 | if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED) |
1959 | return -EIO; | 1990 | return -EIO; |
1960 | 1991 | ||
1961 | err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN); | 1992 | cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC); |
1993 | if (!cmd) | ||
1994 | return -ENOMEM; | ||
1995 | |||
1996 | err = qlcnic_alloc_mbx_args(cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN); | ||
1962 | if (err) | 1997 | if (err) |
1963 | return err; | 1998 | goto out; |
1999 | |||
2000 | cmd->type = QLC_83XX_MBX_CMD_NO_WAIT; | ||
1964 | 2001 | ||
1965 | if (vlan_id) | 2002 | if (vlan_id) |
1966 | op = (op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ? | 2003 | op = (op == QLCNIC_MAC_ADD || op == QLCNIC_MAC_VLAN_ADD) ? |
1967 | QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL; | 2004 | QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_VLAN_DEL; |
1968 | 2005 | ||
1969 | cmd.req.arg[1] = op | (1 << 8); | 2006 | cmd->req.arg[1] = op | (1 << 8); |
1970 | qlcnic_83xx_set_interface_id_macaddr(adapter, &temp); | 2007 | qlcnic_83xx_set_interface_id_macaddr(adapter, &temp); |
1971 | cmd.req.arg[1] |= temp; | 2008 | cmd->req.arg[1] |= temp; |
1972 | mv.vlan = vlan_id; | 2009 | mv.vlan = vlan_id; |
1973 | mv.mac_addr0 = addr[0]; | 2010 | mv.mac_addr0 = addr[0]; |
1974 | mv.mac_addr1 = addr[1]; | 2011 | mv.mac_addr1 = addr[1]; |
@@ -1976,14 +2013,15 @@ int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, | |||
1976 | mv.mac_addr3 = addr[3]; | 2013 | mv.mac_addr3 = addr[3]; |
1977 | mv.mac_addr4 = addr[4]; | 2014 | mv.mac_addr4 = addr[4]; |
1978 | mv.mac_addr5 = addr[5]; | 2015 | mv.mac_addr5 = addr[5]; |
1979 | buf = &cmd.req.arg[2]; | 2016 | buf = &cmd->req.arg[2]; |
1980 | memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx)); | 2017 | memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx)); |
1981 | err = qlcnic_issue_cmd(adapter, &cmd); | 2018 | err = qlcnic_issue_cmd(adapter, cmd); |
1982 | if (err) | 2019 | if (!err) |
1983 | dev_err(&adapter->pdev->dev, | 2020 | return err; |
1984 | "MAC-VLAN %s to CAM failed, err=%d.\n", | 2021 | |
1985 | ((op == 1) ? "add " : "delete "), err); | 2022 | qlcnic_free_mbx_args(cmd); |
1986 | qlcnic_free_mbx_args(&cmd); | 2023 | out: |
2024 | kfree(cmd); | ||
1987 | return err; | 2025 | return err; |
1988 | } | 2026 | } |
1989 | 2027 | ||
@@ -2008,12 +2046,14 @@ void qlcnic_83xx_configure_mac(struct qlcnic_adapter *adapter, u8 *mac, | |||
2008 | cmd->req.arg[1] = type; | 2046 | cmd->req.arg[1] = type; |
2009 | } | 2047 | } |
2010 | 2048 | ||
2011 | int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac) | 2049 | int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac, |
2050 | u8 function) | ||
2012 | { | 2051 | { |
2013 | int err, i; | 2052 | int err, i; |
2014 | struct qlcnic_cmd_args cmd; | 2053 | struct qlcnic_cmd_args cmd; |
2015 | u32 mac_low, mac_high; | 2054 | u32 mac_low, mac_high; |
2016 | 2055 | ||
2056 | function = 0; | ||
2017 | err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS); | 2057 | err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS); |
2018 | if (err) | 2058 | if (err) |
2019 | return err; | 2059 | return err; |
@@ -2099,10 +2139,12 @@ static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter, | |||
2099 | irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data) | 2139 | irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data) |
2100 | { | 2140 | { |
2101 | struct qlcnic_adapter *adapter = data; | 2141 | struct qlcnic_adapter *adapter = data; |
2102 | unsigned long flags; | 2142 | struct qlcnic_mailbox *mbx; |
2103 | u32 mask, resp, event; | 2143 | u32 mask, resp, event; |
2144 | unsigned long flags; | ||
2104 | 2145 | ||
2105 | spin_lock_irqsave(&adapter->ahw->mbx_lock, flags); | 2146 | mbx = adapter->ahw->mailbox; |
2147 | spin_lock_irqsave(&mbx->aen_lock, flags); | ||
2106 | resp = QLCRDX(adapter->ahw, QLCNIC_FW_MBX_CTRL); | 2148 | resp = QLCRDX(adapter->ahw, QLCNIC_FW_MBX_CTRL); |
2107 | if (!(resp & QLCNIC_SET_OWNER)) | 2149 | if (!(resp & QLCNIC_SET_OWNER)) |
2108 | goto out; | 2150 | goto out; |
@@ -2110,11 +2152,13 @@ irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data) | |||
2110 | event = readl(QLCNIC_MBX_FW(adapter->ahw, 0)); | 2152 | event = readl(QLCNIC_MBX_FW(adapter->ahw, 0)); |
2111 | if (event & QLCNIC_MBX_ASYNC_EVENT) | 2153 | if (event & QLCNIC_MBX_ASYNC_EVENT) |
2112 | __qlcnic_83xx_process_aen(adapter); | 2154 | __qlcnic_83xx_process_aen(adapter); |
2155 | else | ||
2156 | qlcnic_83xx_notify_mbx_response(mbx); | ||
2157 | |||
2113 | out: | 2158 | out: |
2114 | mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK); | 2159 | mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK); |
2115 | writel(0, adapter->ahw->pci_base0 + mask); | 2160 | writel(0, adapter->ahw->pci_base0 + mask); |
2116 | spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags); | 2161 | spin_unlock_irqrestore(&mbx->aen_lock, flags); |
2117 | |||
2118 | return IRQ_HANDLED; | 2162 | return IRQ_HANDLED; |
2119 | } | 2163 | } |
2120 | 2164 | ||
@@ -2287,7 +2331,7 @@ int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter, | |||
2287 | pci_info->tx_max_bw, pci_info->mac); | 2331 | pci_info->tx_max_bw, pci_info->mac); |
2288 | } | 2332 | } |
2289 | if (ahw->op_mode == QLCNIC_MGMT_FUNC) | 2333 | if (ahw->op_mode == QLCNIC_MGMT_FUNC) |
2290 | dev_info(dev, "Max vNIC functions = %d, active vNIC functions = %d\n", | 2334 | dev_info(dev, "Max functions = %d, active functions = %d\n", |
2291 | ahw->max_pci_func, ahw->act_pci_func); | 2335 | ahw->max_pci_func, ahw->act_pci_func); |
2292 | 2336 | ||
2293 | } else { | 2337 | } else { |
@@ -3477,3 +3521,360 @@ int qlcnic_83xx_resume(struct qlcnic_adapter *adapter) | |||
3477 | idc->delay); | 3521 | idc->delay); |
3478 | return err; | 3522 | return err; |
3479 | } | 3523 | } |
3524 | |||
3525 | void qlcnic_83xx_reinit_mbx_work(struct qlcnic_mailbox *mbx) | ||
3526 | { | ||
3527 | INIT_COMPLETION(mbx->completion); | ||
3528 | set_bit(QLC_83XX_MBX_READY, &mbx->status); | ||
3529 | } | ||
3530 | |||
3531 | void qlcnic_83xx_free_mailbox(struct qlcnic_mailbox *mbx) | ||
3532 | { | ||
3533 | destroy_workqueue(mbx->work_q); | ||
3534 | kfree(mbx); | ||
3535 | } | ||
3536 | |||
3537 | static inline void | ||
3538 | qlcnic_83xx_notify_cmd_completion(struct qlcnic_adapter *adapter, | ||
3539 | struct qlcnic_cmd_args *cmd) | ||
3540 | { | ||
3541 | atomic_set(&cmd->rsp_status, QLC_83XX_MBX_RESPONSE_ARRIVED); | ||
3542 | |||
3543 | if (cmd->type == QLC_83XX_MBX_CMD_NO_WAIT) { | ||
3544 | qlcnic_free_mbx_args(cmd); | ||
3545 | kfree(cmd); | ||
3546 | return; | ||
3547 | } | ||
3548 | complete(&cmd->completion); | ||
3549 | } | ||
3550 | |||
3551 | static void qlcnic_83xx_flush_mbx_queue(struct qlcnic_adapter *adapter) | ||
3552 | { | ||
3553 | struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; | ||
3554 | struct list_head *head = &mbx->cmd_q; | ||
3555 | struct qlcnic_cmd_args *cmd = NULL; | ||
3556 | |||
3557 | spin_lock(&mbx->queue_lock); | ||
3558 | |||
3559 | while (!list_empty(head)) { | ||
3560 | cmd = list_entry(head->next, struct qlcnic_cmd_args, list); | ||
3561 | dev_info(&adapter->pdev->dev, "%s: Mailbox command 0x%x\n", | ||
3562 | __func__, cmd->cmd_op); | ||
3563 | list_del(&cmd->list); | ||
3564 | mbx->num_cmds--; | ||
3565 | qlcnic_83xx_notify_cmd_completion(adapter, cmd); | ||
3566 | } | ||
3567 | |||
3568 | spin_unlock(&mbx->queue_lock); | ||
3569 | } | ||
3570 | |||
3571 | static int qlcnic_83xx_check_mbx_status(struct qlcnic_adapter *adapter) | ||
3572 | { | ||
3573 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
3574 | struct qlcnic_mailbox *mbx = ahw->mailbox; | ||
3575 | u32 host_mbx_ctrl; | ||
3576 | |||
3577 | if (!test_bit(QLC_83XX_MBX_READY, &mbx->status)) | ||
3578 | return -EBUSY; | ||
3579 | |||
3580 | host_mbx_ctrl = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL); | ||
3581 | if (host_mbx_ctrl) { | ||
3582 | clear_bit(QLC_83XX_MBX_READY, &mbx->status); | ||
3583 | ahw->idc.collect_dump = 1; | ||
3584 | return -EIO; | ||
3585 | } | ||
3586 | |||
3587 | return 0; | ||
3588 | } | ||
3589 | |||
3590 | static inline void qlcnic_83xx_signal_mbx_cmd(struct qlcnic_adapter *adapter, | ||
3591 | u8 issue_cmd) | ||
3592 | { | ||
3593 | if (issue_cmd) | ||
3594 | QLCWRX(adapter->ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER); | ||
3595 | else | ||
3596 | QLCWRX(adapter->ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER); | ||
3597 | } | ||
3598 | |||
3599 | static void qlcnic_83xx_dequeue_mbx_cmd(struct qlcnic_adapter *adapter, | ||
3600 | struct qlcnic_cmd_args *cmd) | ||
3601 | { | ||
3602 | struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; | ||
3603 | |||
3604 | spin_lock(&mbx->queue_lock); | ||
3605 | |||
3606 | list_del(&cmd->list); | ||
3607 | mbx->num_cmds--; | ||
3608 | |||
3609 | spin_unlock(&mbx->queue_lock); | ||
3610 | |||
3611 | qlcnic_83xx_notify_cmd_completion(adapter, cmd); | ||
3612 | } | ||
3613 | |||
3614 | static void qlcnic_83xx_encode_mbx_cmd(struct qlcnic_adapter *adapter, | ||
3615 | struct qlcnic_cmd_args *cmd) | ||
3616 | { | ||
3617 | u32 mbx_cmd, fw_hal_version, hdr_size, total_size, tmp; | ||
3618 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
3619 | int i, j; | ||
3620 | |||
3621 | if (cmd->op_type != QLC_83XX_MBX_POST_BC_OP) { | ||
3622 | mbx_cmd = cmd->req.arg[0]; | ||
3623 | writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0)); | ||
3624 | for (i = 1; i < cmd->req.num; i++) | ||
3625 | writel(cmd->req.arg[i], QLCNIC_MBX_HOST(ahw, i)); | ||
3626 | } else { | ||
3627 | fw_hal_version = ahw->fw_hal_version; | ||
3628 | hdr_size = sizeof(struct qlcnic_bc_hdr) / sizeof(u32); | ||
3629 | total_size = cmd->pay_size + hdr_size; | ||
3630 | tmp = QLCNIC_CMD_BC_EVENT_SETUP | total_size << 16; | ||
3631 | mbx_cmd = tmp | fw_hal_version << 29; | ||
3632 | writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0)); | ||
3633 | |||
3634 | /* Back channel specific operations bits */ | ||
3635 | mbx_cmd = 0x1 | 1 << 4; | ||
3636 | |||
3637 | if (qlcnic_sriov_pf_check(adapter)) | ||
3638 | mbx_cmd |= cmd->func_num << 5; | ||
3639 | |||
3640 | writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 1)); | ||
3641 | |||
3642 | for (i = 2, j = 0; j < hdr_size; i++, j++) | ||
3643 | writel(*(cmd->hdr++), QLCNIC_MBX_HOST(ahw, i)); | ||
3644 | for (j = 0; j < cmd->pay_size; j++, i++) | ||
3645 | writel(*(cmd->pay++), QLCNIC_MBX_HOST(ahw, i)); | ||
3646 | } | ||
3647 | } | ||
3648 | |||
3649 | void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *adapter) | ||
3650 | { | ||
3651 | struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; | ||
3652 | |||
3653 | clear_bit(QLC_83XX_MBX_READY, &mbx->status); | ||
3654 | complete(&mbx->completion); | ||
3655 | cancel_work_sync(&mbx->work); | ||
3656 | flush_workqueue(mbx->work_q); | ||
3657 | qlcnic_83xx_flush_mbx_queue(adapter); | ||
3658 | } | ||
3659 | |||
3660 | static int qlcnic_83xx_enqueue_mbx_cmd(struct qlcnic_adapter *adapter, | ||
3661 | struct qlcnic_cmd_args *cmd, | ||
3662 | unsigned long *timeout) | ||
3663 | { | ||
3664 | struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; | ||
3665 | |||
3666 | if (test_bit(QLC_83XX_MBX_READY, &mbx->status)) { | ||
3667 | atomic_set(&cmd->rsp_status, QLC_83XX_MBX_RESPONSE_WAIT); | ||
3668 | init_completion(&cmd->completion); | ||
3669 | cmd->rsp_opcode = QLC_83XX_MBX_RESPONSE_UNKNOWN; | ||
3670 | |||
3671 | spin_lock(&mbx->queue_lock); | ||
3672 | |||
3673 | list_add_tail(&cmd->list, &mbx->cmd_q); | ||
3674 | mbx->num_cmds++; | ||
3675 | cmd->total_cmds = mbx->num_cmds; | ||
3676 | *timeout = cmd->total_cmds * QLC_83XX_MBX_TIMEOUT; | ||
3677 | queue_work(mbx->work_q, &mbx->work); | ||
3678 | |||
3679 | spin_unlock(&mbx->queue_lock); | ||
3680 | |||
3681 | return 0; | ||
3682 | } | ||
3683 | |||
3684 | return -EBUSY; | ||
3685 | } | ||
3686 | |||
3687 | static int qlcnic_83xx_check_mac_rcode(struct qlcnic_adapter *adapter, | ||
3688 | struct qlcnic_cmd_args *cmd) | ||
3689 | { | ||
3690 | u8 mac_cmd_rcode; | ||
3691 | u32 fw_data; | ||
3692 | |||
3693 | if (cmd->cmd_op == QLCNIC_CMD_CONFIG_MAC_VLAN) { | ||
3694 | fw_data = readl(QLCNIC_MBX_FW(adapter->ahw, 2)); | ||
3695 | mac_cmd_rcode = (u8)fw_data; | ||
3696 | if (mac_cmd_rcode == QLC_83XX_NO_NIC_RESOURCE || | ||
3697 | mac_cmd_rcode == QLC_83XX_MAC_PRESENT || | ||
3698 | mac_cmd_rcode == QLC_83XX_MAC_ABSENT) { | ||
3699 | cmd->rsp_opcode = QLCNIC_RCODE_SUCCESS; | ||
3700 | return QLCNIC_RCODE_SUCCESS; | ||
3701 | } | ||
3702 | } | ||
3703 | |||
3704 | return -EINVAL; | ||
3705 | } | ||
3706 | |||
3707 | static void qlcnic_83xx_decode_mbx_rsp(struct qlcnic_adapter *adapter, | ||
3708 | struct qlcnic_cmd_args *cmd) | ||
3709 | { | ||
3710 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
3711 | struct device *dev = &adapter->pdev->dev; | ||
3712 | u8 mbx_err_code; | ||
3713 | u32 fw_data; | ||
3714 | |||
3715 | fw_data = readl(QLCNIC_MBX_FW(ahw, 0)); | ||
3716 | mbx_err_code = QLCNIC_MBX_STATUS(fw_data); | ||
3717 | qlcnic_83xx_get_mbx_data(adapter, cmd); | ||
3718 | |||
3719 | switch (mbx_err_code) { | ||
3720 | case QLCNIC_MBX_RSP_OK: | ||
3721 | case QLCNIC_MBX_PORT_RSP_OK: | ||
3722 | cmd->rsp_opcode = QLCNIC_RCODE_SUCCESS; | ||
3723 | break; | ||
3724 | default: | ||
3725 | if (!qlcnic_83xx_check_mac_rcode(adapter, cmd)) | ||
3726 | break; | ||
3727 | |||
3728 | dev_err(dev, "%s: Mailbox command failed, opcode=0x%x, cmd_type=0x%x, func=0x%x, op_mode=0x%x, error=0x%x\n", | ||
3729 | __func__, cmd->cmd_op, cmd->type, ahw->pci_func, | ||
3730 | ahw->op_mode, mbx_err_code); | ||
3731 | cmd->rsp_opcode = QLC_83XX_MBX_RESPONSE_FAILED; | ||
3732 | qlcnic_dump_mbx(adapter, cmd); | ||
3733 | } | ||
3734 | |||
3735 | return; | ||
3736 | } | ||
3737 | |||
3738 | static void qlcnic_83xx_mailbox_worker(struct work_struct *work) | ||
3739 | { | ||
3740 | struct qlcnic_mailbox *mbx = container_of(work, struct qlcnic_mailbox, | ||
3741 | work); | ||
3742 | struct qlcnic_adapter *adapter = mbx->adapter; | ||
3743 | struct qlcnic_mbx_ops *mbx_ops = mbx->ops; | ||
3744 | struct device *dev = &adapter->pdev->dev; | ||
3745 | atomic_t *rsp_status = &mbx->rsp_status; | ||
3746 | struct list_head *head = &mbx->cmd_q; | ||
3747 | struct qlcnic_hardware_context *ahw; | ||
3748 | struct qlcnic_cmd_args *cmd = NULL; | ||
3749 | |||
3750 | ahw = adapter->ahw; | ||
3751 | |||
3752 | while (true) { | ||
3753 | if (qlcnic_83xx_check_mbx_status(adapter)) { | ||
3754 | qlcnic_83xx_flush_mbx_queue(adapter); | ||
3755 | return; | ||
3756 | } | ||
3757 | |||
3758 | atomic_set(rsp_status, QLC_83XX_MBX_RESPONSE_WAIT); | ||
3759 | |||
3760 | spin_lock(&mbx->queue_lock); | ||
3761 | |||
3762 | if (list_empty(head)) { | ||
3763 | spin_unlock(&mbx->queue_lock); | ||
3764 | return; | ||
3765 | } | ||
3766 | cmd = list_entry(head->next, struct qlcnic_cmd_args, list); | ||
3767 | |||
3768 | spin_unlock(&mbx->queue_lock); | ||
3769 | |||
3770 | mbx_ops->encode_cmd(adapter, cmd); | ||
3771 | mbx_ops->nofity_fw(adapter, QLC_83XX_MBX_REQUEST); | ||
3772 | |||
3773 | if (wait_for_completion_timeout(&mbx->completion, | ||
3774 | QLC_83XX_MBX_TIMEOUT)) { | ||
3775 | mbx_ops->decode_resp(adapter, cmd); | ||
3776 | mbx_ops->nofity_fw(adapter, QLC_83XX_MBX_COMPLETION); | ||
3777 | } else { | ||
3778 | dev_err(dev, "%s: Mailbox command timeout, opcode=0x%x, cmd_type=0x%x, func=0x%x, op_mode=0x%x\n", | ||
3779 | __func__, cmd->cmd_op, cmd->type, ahw->pci_func, | ||
3780 | ahw->op_mode); | ||
3781 | clear_bit(QLC_83XX_MBX_READY, &mbx->status); | ||
3782 | qlcnic_dump_mbx(adapter, cmd); | ||
3783 | qlcnic_83xx_idc_request_reset(adapter, | ||
3784 | QLCNIC_FORCE_FW_DUMP_KEY); | ||
3785 | cmd->rsp_opcode = QLCNIC_RCODE_TIMEOUT; | ||
3786 | } | ||
3787 | mbx_ops->dequeue_cmd(adapter, cmd); | ||
3788 | } | ||
3789 | } | ||
3790 | |||
3791 | static struct qlcnic_mbx_ops qlcnic_83xx_mbx_ops = { | ||
3792 | .enqueue_cmd = qlcnic_83xx_enqueue_mbx_cmd, | ||
3793 | .dequeue_cmd = qlcnic_83xx_dequeue_mbx_cmd, | ||
3794 | .decode_resp = qlcnic_83xx_decode_mbx_rsp, | ||
3795 | .encode_cmd = qlcnic_83xx_encode_mbx_cmd, | ||
3796 | .nofity_fw = qlcnic_83xx_signal_mbx_cmd, | ||
3797 | }; | ||
3798 | |||
3799 | int qlcnic_83xx_init_mailbox_work(struct qlcnic_adapter *adapter) | ||
3800 | { | ||
3801 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
3802 | struct qlcnic_mailbox *mbx; | ||
3803 | |||
3804 | ahw->mailbox = kzalloc(sizeof(*mbx), GFP_KERNEL); | ||
3805 | if (!ahw->mailbox) | ||
3806 | return -ENOMEM; | ||
3807 | |||
3808 | mbx = ahw->mailbox; | ||
3809 | mbx->ops = &qlcnic_83xx_mbx_ops; | ||
3810 | mbx->adapter = adapter; | ||
3811 | |||
3812 | spin_lock_init(&mbx->queue_lock); | ||
3813 | spin_lock_init(&mbx->aen_lock); | ||
3814 | INIT_LIST_HEAD(&mbx->cmd_q); | ||
3815 | init_completion(&mbx->completion); | ||
3816 | |||
3817 | mbx->work_q = create_singlethread_workqueue("qlcnic_mailbox"); | ||
3818 | if (mbx->work_q == NULL) { | ||
3819 | kfree(mbx); | ||
3820 | return -ENOMEM; | ||
3821 | } | ||
3822 | |||
3823 | INIT_WORK(&mbx->work, qlcnic_83xx_mailbox_worker); | ||
3824 | set_bit(QLC_83XX_MBX_READY, &mbx->status); | ||
3825 | return 0; | ||
3826 | } | ||
3827 | |||
3828 | pci_ers_result_t qlcnic_83xx_io_error_detected(struct pci_dev *pdev, | ||
3829 | pci_channel_state_t state) | ||
3830 | { | ||
3831 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | ||
3832 | |||
3833 | if (state == pci_channel_io_perm_failure) | ||
3834 | return PCI_ERS_RESULT_DISCONNECT; | ||
3835 | |||
3836 | if (state == pci_channel_io_normal) | ||
3837 | return PCI_ERS_RESULT_RECOVERED; | ||
3838 | |||
3839 | set_bit(__QLCNIC_AER, &adapter->state); | ||
3840 | set_bit(__QLCNIC_RESETTING, &adapter->state); | ||
3841 | |||
3842 | qlcnic_83xx_aer_stop_poll_work(adapter); | ||
3843 | |||
3844 | pci_save_state(pdev); | ||
3845 | pci_disable_device(pdev); | ||
3846 | |||
3847 | return PCI_ERS_RESULT_NEED_RESET; | ||
3848 | } | ||
3849 | |||
3850 | pci_ers_result_t qlcnic_83xx_io_slot_reset(struct pci_dev *pdev) | ||
3851 | { | ||
3852 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | ||
3853 | int err = 0; | ||
3854 | |||
3855 | pdev->error_state = pci_channel_io_normal; | ||
3856 | err = pci_enable_device(pdev); | ||
3857 | if (err) | ||
3858 | goto disconnect; | ||
3859 | |||
3860 | pci_set_power_state(pdev, PCI_D0); | ||
3861 | pci_set_master(pdev); | ||
3862 | pci_restore_state(pdev); | ||
3863 | |||
3864 | err = qlcnic_83xx_aer_reset(adapter); | ||
3865 | if (err == 0) | ||
3866 | return PCI_ERS_RESULT_RECOVERED; | ||
3867 | disconnect: | ||
3868 | clear_bit(__QLCNIC_AER, &adapter->state); | ||
3869 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
3870 | return PCI_ERS_RESULT_DISCONNECT; | ||
3871 | } | ||
3872 | |||
3873 | void qlcnic_83xx_io_resume(struct pci_dev *pdev) | ||
3874 | { | ||
3875 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | ||
3876 | |||
3877 | pci_cleanup_aer_uncorrect_error_status(pdev); | ||
3878 | if (test_and_clear_bit(__QLCNIC_AER, &adapter->state)) | ||
3879 | qlcnic_83xx_aer_start_poll_work(adapter); | ||
3880 | } | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h index 272f56a2e14b..533e150503af 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | |||
@@ -84,11 +84,20 @@ | |||
84 | /* Firmware image definitions */ | 84 | /* Firmware image definitions */ |
85 | #define QLC_83XX_BOOTLOADER_FLASH_ADDR 0x10000 | 85 | #define QLC_83XX_BOOTLOADER_FLASH_ADDR 0x10000 |
86 | #define QLC_83XX_FW_FILE_NAME "83xx_fw.bin" | 86 | #define QLC_83XX_FW_FILE_NAME "83xx_fw.bin" |
87 | #define QLC_84XX_FW_FILE_NAME "84xx_fw.bin" | ||
87 | #define QLC_83XX_BOOT_FROM_FLASH 0 | 88 | #define QLC_83XX_BOOT_FROM_FLASH 0 |
88 | #define QLC_83XX_BOOT_FROM_FILE 0x12345678 | 89 | #define QLC_83XX_BOOT_FROM_FILE 0x12345678 |
89 | 90 | ||
91 | #define QLC_FW_FILE_NAME_LEN 20 | ||
90 | #define QLC_83XX_MAX_RESET_SEQ_ENTRIES 16 | 92 | #define QLC_83XX_MAX_RESET_SEQ_ENTRIES 16 |
91 | 93 | ||
94 | #define QLC_83XX_MBX_POST_BC_OP 0x1 | ||
95 | #define QLC_83XX_MBX_COMPLETION 0x0 | ||
96 | #define QLC_83XX_MBX_REQUEST 0x1 | ||
97 | |||
98 | #define QLC_83XX_MBX_TIMEOUT (5 * HZ) | ||
99 | #define QLC_83XX_MBX_CMD_LOOP 5000000 | ||
100 | |||
92 | /* status descriptor mailbox data | 101 | /* status descriptor mailbox data |
93 | * @phy_addr_{low|high}: physical address of buffer | 102 | * @phy_addr_{low|high}: physical address of buffer |
94 | * @sds_ring_size: buffer size | 103 | * @sds_ring_size: buffer size |
@@ -265,11 +274,7 @@ struct qlcnic_macvlan_mbx { | |||
265 | 274 | ||
266 | struct qlc_83xx_fw_info { | 275 | struct qlc_83xx_fw_info { |
267 | const struct firmware *fw; | 276 | const struct firmware *fw; |
268 | u16 major_fw_version; | 277 | char fw_file_name[QLC_FW_FILE_NAME_LEN]; |
269 | u8 minor_fw_version; | ||
270 | u8 sub_fw_version; | ||
271 | u8 fw_build_num; | ||
272 | u8 load_from_file; | ||
273 | }; | 278 | }; |
274 | 279 | ||
275 | struct qlc_83xx_reset { | 280 | struct qlc_83xx_reset { |
@@ -288,6 +293,7 @@ struct qlc_83xx_reset { | |||
288 | 293 | ||
289 | #define QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY 0x1 | 294 | #define QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY 0x1 |
290 | #define QLC_83XX_IDC_GRACEFULL_RESET 0x2 | 295 | #define QLC_83XX_IDC_GRACEFULL_RESET 0x2 |
296 | #define QLC_83XX_IDC_DISABLE_FW_DUMP 0x4 | ||
291 | #define QLC_83XX_IDC_TIMESTAMP 0 | 297 | #define QLC_83XX_IDC_TIMESTAMP 0 |
292 | #define QLC_83XX_IDC_DURATION 1 | 298 | #define QLC_83XX_IDC_DURATION 1 |
293 | #define QLC_83XX_IDC_INIT_TIMEOUT_SECS 30 | 299 | #define QLC_83XX_IDC_INIT_TIMEOUT_SECS 30 |
@@ -397,6 +403,7 @@ enum qlcnic_83xx_states { | |||
397 | #define QLC_83XX_MAX_MC_COUNT 38 | 403 | #define QLC_83XX_MAX_MC_COUNT 38 |
398 | #define QLC_83XX_MAX_UC_COUNT 4096 | 404 | #define QLC_83XX_MAX_UC_COUNT 4096 |
399 | 405 | ||
406 | #define QLC_83XX_PVID_STRIP_CAPABILITY BIT_22 | ||
400 | #define QLC_83XX_GET_FUNC_MODE_FROM_NPAR_INFO(val) (val & 0x80000000) | 407 | #define QLC_83XX_GET_FUNC_MODE_FROM_NPAR_INFO(val) (val & 0x80000000) |
401 | #define QLC_83XX_GET_LRO_CAPABILITY(val) (val & 0x20) | 408 | #define QLC_83XX_GET_LRO_CAPABILITY(val) (val & 0x20) |
402 | #define QLC_83XX_GET_LSO_CAPABILITY(val) (val & 0x40) | 409 | #define QLC_83XX_GET_LSO_CAPABILITY(val) (val & 0x40) |
@@ -404,6 +411,7 @@ enum qlcnic_83xx_states { | |||
404 | #define QLC_83XX_GET_HW_LRO_CAPABILITY(val) (val & 0x400) | 411 | #define QLC_83XX_GET_HW_LRO_CAPABILITY(val) (val & 0x400) |
405 | #define QLC_83XX_GET_VLAN_ALIGN_CAPABILITY(val) (val & 0x4000) | 412 | #define QLC_83XX_GET_VLAN_ALIGN_CAPABILITY(val) (val & 0x4000) |
406 | #define QLC_83XX_GET_FW_LRO_MSS_CAPABILITY(val) (val & 0x20000) | 413 | #define QLC_83XX_GET_FW_LRO_MSS_CAPABILITY(val) (val & 0x20000) |
414 | #define QLC_83XX_ESWITCH_CAPABILITY BIT_23 | ||
407 | #define QLC_83XX_VIRTUAL_NIC_MODE 0xFF | 415 | #define QLC_83XX_VIRTUAL_NIC_MODE 0xFF |
408 | #define QLC_83XX_DEFAULT_MODE 0x0 | 416 | #define QLC_83XX_DEFAULT_MODE 0x0 |
409 | #define QLC_83XX_SRIOV_MODE 0x1 | 417 | #define QLC_83XX_SRIOV_MODE 0x1 |
@@ -449,6 +457,20 @@ enum qlcnic_83xx_states { | |||
449 | #define QLC_83xx_FLASH_MAX_WAIT_USEC 100 | 457 | #define QLC_83xx_FLASH_MAX_WAIT_USEC 100 |
450 | #define QLC_83XX_FLASH_LOCK_TIMEOUT 10000 | 458 | #define QLC_83XX_FLASH_LOCK_TIMEOUT 10000 |
451 | 459 | ||
460 | enum qlc_83xx_mbx_cmd_type { | ||
461 | QLC_83XX_MBX_CMD_WAIT = 0, | ||
462 | QLC_83XX_MBX_CMD_NO_WAIT, | ||
463 | QLC_83XX_MBX_CMD_BUSY_WAIT, | ||
464 | }; | ||
465 | |||
466 | enum qlc_83xx_mbx_response_states { | ||
467 | QLC_83XX_MBX_RESPONSE_WAIT = 0, | ||
468 | QLC_83XX_MBX_RESPONSE_ARRIVED, | ||
469 | }; | ||
470 | |||
471 | #define QLC_83XX_MBX_RESPONSE_FAILED 0x2 | ||
472 | #define QLC_83XX_MBX_RESPONSE_UNKNOWN 0x3 | ||
473 | |||
452 | /* Additional registers in 83xx */ | 474 | /* Additional registers in 83xx */ |
453 | enum qlc_83xx_ext_regs { | 475 | enum qlc_83xx_ext_regs { |
454 | QLCNIC_GLOBAL_RESET = 0, | 476 | QLCNIC_GLOBAL_RESET = 0, |
@@ -498,8 +520,8 @@ enum qlc_83xx_ext_regs { | |||
498 | 520 | ||
499 | /* 83xx funcitons */ | 521 | /* 83xx funcitons */ |
500 | int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *); | 522 | int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *); |
501 | int qlcnic_83xx_mbx_op(struct qlcnic_adapter *, struct qlcnic_cmd_args *); | 523 | int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *, struct qlcnic_cmd_args *); |
502 | int qlcnic_83xx_setup_intr(struct qlcnic_adapter *, u8); | 524 | int qlcnic_83xx_setup_intr(struct qlcnic_adapter *, u8, int); |
503 | void qlcnic_83xx_get_func_no(struct qlcnic_adapter *); | 525 | void qlcnic_83xx_get_func_no(struct qlcnic_adapter *); |
504 | int qlcnic_83xx_cam_lock(struct qlcnic_adapter *); | 526 | int qlcnic_83xx_cam_lock(struct qlcnic_adapter *); |
505 | void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *); | 527 | void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *); |
@@ -540,7 +562,7 @@ int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *, int); | |||
540 | void qlcnic_83xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *); | 562 | void qlcnic_83xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *); |
541 | int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *, bool); | 563 | int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *, bool); |
542 | int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *, u8 *, u16, u8); | 564 | int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *, u8 *, u16, u8); |
543 | int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *, u8 *); | 565 | int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *, u8 *, u8); |
544 | void qlcnic_83xx_configure_mac(struct qlcnic_adapter *, u8 *, u8, | 566 | void qlcnic_83xx_configure_mac(struct qlcnic_adapter *, u8 *, u8, |
545 | struct qlcnic_cmd_args *); | 567 | struct qlcnic_cmd_args *); |
546 | int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *, | 568 | int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *, |
@@ -551,7 +573,7 @@ void qlcnic_set_npar_data(struct qlcnic_adapter *, const struct qlcnic_info *, | |||
551 | void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *); | 573 | void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *); |
552 | irqreturn_t qlcnic_83xx_handle_aen(int, void *); | 574 | irqreturn_t qlcnic_83xx_handle_aen(int, void *); |
553 | int qlcnic_83xx_get_port_info(struct qlcnic_adapter *); | 575 | int qlcnic_83xx_get_port_info(struct qlcnic_adapter *); |
554 | void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *); | 576 | void qlcnic_83xx_enable_mbx_interrupt(struct qlcnic_adapter *); |
555 | void qlcnic_83xx_disable_mbx_intr(struct qlcnic_adapter *); | 577 | void qlcnic_83xx_disable_mbx_intr(struct qlcnic_adapter *); |
556 | irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *); | 578 | irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *); |
557 | irqreturn_t qlcnic_83xx_intr(int, void *); | 579 | irqreturn_t qlcnic_83xx_intr(int, void *); |
@@ -604,6 +626,7 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *); | |||
604 | int qlcnic_83xx_get_vnic_vport_info(struct qlcnic_adapter *, | 626 | int qlcnic_83xx_get_vnic_vport_info(struct qlcnic_adapter *, |
605 | struct qlcnic_info *, u8); | 627 | struct qlcnic_info *, u8); |
606 | int qlcnic_83xx_get_vnic_pf_info(struct qlcnic_adapter *, struct qlcnic_info *); | 628 | int qlcnic_83xx_get_vnic_pf_info(struct qlcnic_adapter *, struct qlcnic_info *); |
629 | int qlcnic_83xx_enable_port_eswitch(struct qlcnic_adapter *, int); | ||
607 | 630 | ||
608 | void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *); | 631 | void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *); |
609 | void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data); | 632 | void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data); |
@@ -623,8 +646,6 @@ int qlcnic_83xx_set_led(struct net_device *, enum ethtool_phys_id_state); | |||
623 | int qlcnic_83xx_flash_test(struct qlcnic_adapter *); | 646 | int qlcnic_83xx_flash_test(struct qlcnic_adapter *); |
624 | int qlcnic_83xx_enable_flash_write(struct qlcnic_adapter *); | 647 | int qlcnic_83xx_enable_flash_write(struct qlcnic_adapter *); |
625 | int qlcnic_83xx_disable_flash_write(struct qlcnic_adapter *); | 648 | int qlcnic_83xx_disable_flash_write(struct qlcnic_adapter *); |
626 | u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *); | ||
627 | u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *, u32 *); | ||
628 | void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *); | 649 | void qlcnic_83xx_enable_mbx_poll(struct qlcnic_adapter *); |
629 | void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *); | 650 | void qlcnic_83xx_disable_mbx_poll(struct qlcnic_adapter *); |
630 | void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *); | 651 | void qlcnic_83xx_set_mac_filter_count(struct qlcnic_adapter *); |
@@ -634,4 +655,11 @@ int qlcnic_83xx_idc_init(struct qlcnic_adapter *); | |||
634 | int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *); | 655 | int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *); |
635 | int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *); | 656 | int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *); |
636 | int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *); | 657 | int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *); |
658 | void qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter *); | ||
659 | int qlcnic_83xx_aer_reset(struct qlcnic_adapter *); | ||
660 | void qlcnic_83xx_aer_start_poll_work(struct qlcnic_adapter *); | ||
661 | pci_ers_result_t qlcnic_83xx_io_error_detected(struct pci_dev *, | ||
662 | pci_channel_state_t); | ||
663 | pci_ers_result_t qlcnic_83xx_io_slot_reset(struct pci_dev *); | ||
664 | void qlcnic_83xx_io_resume(struct pci_dev *); | ||
637 | #endif | 665 | #endif |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index 345d987aede4..f09e787af0b2 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | |||
@@ -399,6 +399,7 @@ static void qlcnic_83xx_idc_detach_driver(struct qlcnic_adapter *adapter) | |||
399 | struct net_device *netdev = adapter->netdev; | 399 | struct net_device *netdev = adapter->netdev; |
400 | 400 | ||
401 | netif_device_detach(netdev); | 401 | netif_device_detach(netdev); |
402 | qlcnic_83xx_detach_mailbox_work(adapter); | ||
402 | 403 | ||
403 | /* Disable mailbox interrupt */ | 404 | /* Disable mailbox interrupt */ |
404 | qlcnic_83xx_disable_mbx_intr(adapter); | 405 | qlcnic_83xx_disable_mbx_intr(adapter); |
@@ -610,6 +611,9 @@ int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter) | |||
610 | { | 611 | { |
611 | int err; | 612 | int err; |
612 | 613 | ||
614 | qlcnic_83xx_reinit_mbx_work(adapter->ahw->mailbox); | ||
615 | qlcnic_83xx_enable_mbx_interrupt(adapter); | ||
616 | |||
613 | /* register for NIC IDC AEN Events */ | 617 | /* register for NIC IDC AEN Events */ |
614 | qlcnic_83xx_register_nic_idc_func(adapter, 1); | 618 | qlcnic_83xx_register_nic_idc_func(adapter, 1); |
615 | 619 | ||
@@ -617,7 +621,7 @@ int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter) | |||
617 | if (err) | 621 | if (err) |
618 | return err; | 622 | return err; |
619 | 623 | ||
620 | qlcnic_83xx_enable_mbx_intrpt(adapter); | 624 | qlcnic_83xx_enable_mbx_interrupt(adapter); |
621 | 625 | ||
622 | if (qlcnic_83xx_configure_opmode(adapter)) { | 626 | if (qlcnic_83xx_configure_opmode(adapter)) { |
623 | qlcnic_83xx_idc_enter_failed_state(adapter, 1); | 627 | qlcnic_83xx_idc_enter_failed_state(adapter, 1); |
@@ -631,6 +635,8 @@ int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter) | |||
631 | 635 | ||
632 | if (adapter->portnum == 0) | 636 | if (adapter->portnum == 0) |
633 | qlcnic_set_drv_version(adapter); | 637 | qlcnic_set_drv_version(adapter); |
638 | |||
639 | qlcnic_dcb_get_info(adapter); | ||
634 | qlcnic_83xx_idc_attach_driver(adapter); | 640 | qlcnic_83xx_idc_attach_driver(adapter); |
635 | 641 | ||
636 | return 0; | 642 | return 0; |
@@ -641,7 +647,6 @@ static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter) | |||
641 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 647 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
642 | 648 | ||
643 | qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 1); | 649 | qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 1); |
644 | set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); | ||
645 | qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1); | 650 | qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1); |
646 | set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status); | 651 | set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status); |
647 | 652 | ||
@@ -792,7 +797,6 @@ static int qlcnic_83xx_idc_init_state(struct qlcnic_adapter *adapter) | |||
792 | ret = qlcnic_83xx_idc_restart_hw(adapter, 1); | 797 | ret = qlcnic_83xx_idc_restart_hw(adapter, 1); |
793 | } else { | 798 | } else { |
794 | ret = qlcnic_83xx_idc_check_timeout(adapter, timeout); | 799 | ret = qlcnic_83xx_idc_check_timeout(adapter, timeout); |
795 | return ret; | ||
796 | } | 800 | } |
797 | 801 | ||
798 | return ret; | 802 | return ret; |
@@ -811,9 +815,10 @@ static int qlcnic_83xx_idc_init_state(struct qlcnic_adapter *adapter) | |||
811 | **/ | 815 | **/ |
812 | static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter) | 816 | static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter) |
813 | { | 817 | { |
814 | u32 val; | ||
815 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 818 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
819 | struct qlcnic_mailbox *mbx = ahw->mailbox; | ||
816 | int ret = 0; | 820 | int ret = 0; |
821 | u32 val; | ||
817 | 822 | ||
818 | /* Perform NIC configuration based ready state entry actions */ | 823 | /* Perform NIC configuration based ready state entry actions */ |
819 | if (ahw->idc.state_entry(adapter)) | 824 | if (ahw->idc.state_entry(adapter)) |
@@ -825,7 +830,7 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter) | |||
825 | dev_err(&adapter->pdev->dev, | 830 | dev_err(&adapter->pdev->dev, |
826 | "Error: device temperature %d above limits\n", | 831 | "Error: device temperature %d above limits\n", |
827 | adapter->ahw->temp); | 832 | adapter->ahw->temp); |
828 | clear_bit(QLC_83XX_MBX_READY, &ahw->idc.status); | 833 | clear_bit(QLC_83XX_MBX_READY, &mbx->status); |
829 | set_bit(__QLCNIC_RESETTING, &adapter->state); | 834 | set_bit(__QLCNIC_RESETTING, &adapter->state); |
830 | qlcnic_83xx_idc_detach_driver(adapter); | 835 | qlcnic_83xx_idc_detach_driver(adapter); |
831 | qlcnic_83xx_idc_enter_failed_state(adapter, 1); | 836 | qlcnic_83xx_idc_enter_failed_state(adapter, 1); |
@@ -838,7 +843,7 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter) | |||
838 | if (ret) { | 843 | if (ret) { |
839 | adapter->flags |= QLCNIC_FW_HANG; | 844 | adapter->flags |= QLCNIC_FW_HANG; |
840 | if (!(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) { | 845 | if (!(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) { |
841 | clear_bit(QLC_83XX_MBX_READY, &ahw->idc.status); | 846 | clear_bit(QLC_83XX_MBX_READY, &mbx->status); |
842 | set_bit(__QLCNIC_RESETTING, &adapter->state); | 847 | set_bit(__QLCNIC_RESETTING, &adapter->state); |
843 | qlcnic_83xx_idc_enter_need_reset_state(adapter, 1); | 848 | qlcnic_83xx_idc_enter_need_reset_state(adapter, 1); |
844 | } | 849 | } |
@@ -846,6 +851,8 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter) | |||
846 | } | 851 | } |
847 | 852 | ||
848 | if ((val & QLC_83XX_IDC_GRACEFULL_RESET) || ahw->idc.collect_dump) { | 853 | if ((val & QLC_83XX_IDC_GRACEFULL_RESET) || ahw->idc.collect_dump) { |
854 | clear_bit(QLC_83XX_MBX_READY, &mbx->status); | ||
855 | |||
849 | /* Move to need reset state and prepare for reset */ | 856 | /* Move to need reset state and prepare for reset */ |
850 | qlcnic_83xx_idc_enter_need_reset_state(adapter, 1); | 857 | qlcnic_83xx_idc_enter_need_reset_state(adapter, 1); |
851 | return ret; | 858 | return ret; |
@@ -883,12 +890,13 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter) | |||
883 | **/ | 890 | **/ |
884 | static int qlcnic_83xx_idc_need_reset_state(struct qlcnic_adapter *adapter) | 891 | static int qlcnic_83xx_idc_need_reset_state(struct qlcnic_adapter *adapter) |
885 | { | 892 | { |
893 | struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; | ||
886 | int ret = 0; | 894 | int ret = 0; |
887 | 895 | ||
888 | if (adapter->ahw->idc.prev_state != QLC_83XX_IDC_DEV_NEED_RESET) { | 896 | if (adapter->ahw->idc.prev_state != QLC_83XX_IDC_DEV_NEED_RESET) { |
889 | qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1); | 897 | qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1); |
890 | set_bit(__QLCNIC_RESETTING, &adapter->state); | 898 | set_bit(__QLCNIC_RESETTING, &adapter->state); |
891 | clear_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); | 899 | clear_bit(QLC_83XX_MBX_READY, &mbx->status); |
892 | if (adapter->ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE) | 900 | if (adapter->ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE) |
893 | qlcnic_83xx_disable_vnic_mode(adapter, 1); | 901 | qlcnic_83xx_disable_vnic_mode(adapter, 1); |
894 | 902 | ||
@@ -1080,7 +1088,6 @@ static void qlcnic_83xx_setup_idc_parameters(struct qlcnic_adapter *adapter) | |||
1080 | adapter->ahw->idc.name = (char **)qlc_83xx_idc_states; | 1088 | adapter->ahw->idc.name = (char **)qlc_83xx_idc_states; |
1081 | 1089 | ||
1082 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 1090 | clear_bit(__QLCNIC_RESETTING, &adapter->state); |
1083 | set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); | ||
1084 | set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status); | 1091 | set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status); |
1085 | 1092 | ||
1086 | /* Check if reset recovery is disabled */ | 1093 | /* Check if reset recovery is disabled */ |
@@ -1191,6 +1198,9 @@ void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *adapter, u32 key) | |||
1191 | { | 1198 | { |
1192 | u32 val; | 1199 | u32 val; |
1193 | 1200 | ||
1201 | if (qlcnic_sriov_vf_check(adapter)) | ||
1202 | return; | ||
1203 | |||
1194 | if (qlcnic_83xx_lock_driver(adapter)) { | 1204 | if (qlcnic_83xx_lock_driver(adapter)) { |
1195 | dev_err(&adapter->pdev->dev, | 1205 | dev_err(&adapter->pdev->dev, |
1196 | "%s:failed, please retry\n", __func__); | 1206 | "%s:failed, please retry\n", __func__); |
@@ -1257,31 +1267,33 @@ static int qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter) | |||
1257 | 1267 | ||
1258 | static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter) | 1268 | static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter) |
1259 | { | 1269 | { |
1270 | struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info; | ||
1271 | const struct firmware *fw = fw_info->fw; | ||
1260 | u32 dest, *p_cache; | 1272 | u32 dest, *p_cache; |
1261 | u64 addr; | 1273 | int i, ret = -EIO; |
1262 | u8 data[16]; | 1274 | u8 data[16]; |
1263 | size_t size; | 1275 | size_t size; |
1264 | int i, ret = -EIO; | 1276 | u64 addr; |
1265 | 1277 | ||
1266 | dest = QLCRDX(adapter->ahw, QLCNIC_FW_IMAGE_ADDR); | 1278 | dest = QLCRDX(adapter->ahw, QLCNIC_FW_IMAGE_ADDR); |
1267 | size = (adapter->ahw->fw_info.fw->size & ~0xF); | 1279 | size = (fw->size & ~0xF); |
1268 | p_cache = (u32 *)adapter->ahw->fw_info.fw->data; | 1280 | p_cache = (u32 *)fw->data; |
1269 | addr = (u64)dest; | 1281 | addr = (u64)dest; |
1270 | 1282 | ||
1271 | ret = qlcnic_83xx_ms_mem_write128(adapter, addr, | 1283 | ret = qlcnic_83xx_ms_mem_write128(adapter, addr, |
1272 | (u32 *)p_cache, size / 16); | 1284 | (u32 *)p_cache, size / 16); |
1273 | if (ret) { | 1285 | if (ret) { |
1274 | dev_err(&adapter->pdev->dev, "MS memory write failed\n"); | 1286 | dev_err(&adapter->pdev->dev, "MS memory write failed\n"); |
1275 | release_firmware(adapter->ahw->fw_info.fw); | 1287 | release_firmware(fw); |
1276 | adapter->ahw->fw_info.fw = NULL; | 1288 | fw_info->fw = NULL; |
1277 | return -EIO; | 1289 | return -EIO; |
1278 | } | 1290 | } |
1279 | 1291 | ||
1280 | /* alignment check */ | 1292 | /* alignment check */ |
1281 | if (adapter->ahw->fw_info.fw->size & 0xF) { | 1293 | if (fw->size & 0xF) { |
1282 | addr = dest + size; | 1294 | addr = dest + size; |
1283 | for (i = 0; i < (adapter->ahw->fw_info.fw->size & 0xF); i++) | 1295 | for (i = 0; i < (fw->size & 0xF); i++) |
1284 | data[i] = adapter->ahw->fw_info.fw->data[size + i]; | 1296 | data[i] = fw->data[size + i]; |
1285 | for (; i < 16; i++) | 1297 | for (; i < 16; i++) |
1286 | data[i] = 0; | 1298 | data[i] = 0; |
1287 | ret = qlcnic_83xx_ms_mem_write128(adapter, addr, | 1299 | ret = qlcnic_83xx_ms_mem_write128(adapter, addr, |
@@ -1289,13 +1301,13 @@ static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter) | |||
1289 | if (ret) { | 1301 | if (ret) { |
1290 | dev_err(&adapter->pdev->dev, | 1302 | dev_err(&adapter->pdev->dev, |
1291 | "MS memory write failed\n"); | 1303 | "MS memory write failed\n"); |
1292 | release_firmware(adapter->ahw->fw_info.fw); | 1304 | release_firmware(fw); |
1293 | adapter->ahw->fw_info.fw = NULL; | 1305 | fw_info->fw = NULL; |
1294 | return -EIO; | 1306 | return -EIO; |
1295 | } | 1307 | } |
1296 | } | 1308 | } |
1297 | release_firmware(adapter->ahw->fw_info.fw); | 1309 | release_firmware(fw); |
1298 | adapter->ahw->fw_info.fw = NULL; | 1310 | fw_info->fw = NULL; |
1299 | 1311 | ||
1300 | return 0; | 1312 | return 0; |
1301 | } | 1313 | } |
@@ -1941,10 +1953,11 @@ static void qlcnic_83xx_init_hw(struct qlcnic_adapter *p_dev) | |||
1941 | 1953 | ||
1942 | static int qlcnic_83xx_load_fw_image_from_host(struct qlcnic_adapter *adapter) | 1954 | static int qlcnic_83xx_load_fw_image_from_host(struct qlcnic_adapter *adapter) |
1943 | { | 1955 | { |
1956 | struct qlc_83xx_fw_info *fw_info = adapter->ahw->fw_info; | ||
1944 | int err = -EIO; | 1957 | int err = -EIO; |
1945 | 1958 | ||
1946 | if (request_firmware(&adapter->ahw->fw_info.fw, | 1959 | if (request_firmware(&fw_info->fw, fw_info->fw_file_name, |
1947 | QLC_83XX_FW_FILE_NAME, &(adapter->pdev->dev))) { | 1960 | &(adapter->pdev->dev))) { |
1948 | dev_err(&adapter->pdev->dev, | 1961 | dev_err(&adapter->pdev->dev, |
1949 | "No file FW image, loading flash FW image.\n"); | 1962 | "No file FW image, loading flash FW image.\n"); |
1950 | QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID, | 1963 | QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID, |
@@ -1990,36 +2003,6 @@ static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter) | |||
1990 | return 0; | 2003 | return 0; |
1991 | } | 2004 | } |
1992 | 2005 | ||
1993 | /** | ||
1994 | * qlcnic_83xx_config_default_opmode | ||
1995 | * | ||
1996 | * @adapter: adapter structure | ||
1997 | * | ||
1998 | * Configure default driver operating mode | ||
1999 | * | ||
2000 | * Returns: Error code or Success(0) | ||
2001 | * */ | ||
2002 | int qlcnic_83xx_config_default_opmode(struct qlcnic_adapter *adapter) | ||
2003 | { | ||
2004 | u32 op_mode; | ||
2005 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2006 | |||
2007 | qlcnic_get_func_no(adapter); | ||
2008 | op_mode = QLCRDX(ahw, QLC_83XX_DRV_OP_MODE); | ||
2009 | |||
2010 | if (test_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state)) | ||
2011 | op_mode = QLC_83XX_DEFAULT_OPMODE; | ||
2012 | |||
2013 | if (op_mode == QLC_83XX_DEFAULT_OPMODE) { | ||
2014 | adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver; | ||
2015 | ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; | ||
2016 | } else { | ||
2017 | return -EIO; | ||
2018 | } | ||
2019 | |||
2020 | return 0; | ||
2021 | } | ||
2022 | |||
2023 | int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter) | 2006 | int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter) |
2024 | { | 2007 | { |
2025 | int err; | 2008 | int err; |
@@ -2039,26 +2022,26 @@ int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter) | |||
2039 | ahw->max_mac_filters = nic_info.max_mac_filters; | 2022 | ahw->max_mac_filters = nic_info.max_mac_filters; |
2040 | ahw->max_mtu = nic_info.max_mtu; | 2023 | ahw->max_mtu = nic_info.max_mtu; |
2041 | 2024 | ||
2042 | /* VNIC mode is detected by BIT_23 in capabilities. This bit is also | 2025 | /* eSwitch capability indicates vNIC mode. |
2043 | * set in case device is SRIOV capable. VNIC and SRIOV are mutually | 2026 | * vNIC and SRIOV are mutually exclusive operational modes. |
2044 | * exclusive. So in case of sriov capable device load driver in | 2027 | * If SR-IOV capability is detected, SR-IOV physical function |
2045 | * default mode | 2028 | * will get initialized in default mode. |
2029 | * SR-IOV virtual function initialization follows a | ||
2030 | * different code path and opmode. | ||
2031 | * SRIOV mode has precedence over vNIC mode. | ||
2046 | */ | 2032 | */ |
2047 | if (test_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state)) { | 2033 | if (test_bit(__QLCNIC_SRIOV_CAPABLE, &adapter->state)) |
2048 | ahw->nic_mode = QLC_83XX_DEFAULT_MODE; | 2034 | return QLC_83XX_DEFAULT_OPMODE; |
2049 | return ahw->nic_mode; | ||
2050 | } | ||
2051 | 2035 | ||
2052 | if (ahw->capabilities & BIT_23) | 2036 | if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY) |
2053 | ahw->nic_mode = QLC_83XX_VIRTUAL_NIC_MODE; | 2037 | return QLC_83XX_VIRTUAL_NIC_MODE; |
2054 | else | ||
2055 | ahw->nic_mode = QLC_83XX_DEFAULT_MODE; | ||
2056 | 2038 | ||
2057 | return ahw->nic_mode; | 2039 | return QLC_83XX_DEFAULT_OPMODE; |
2058 | } | 2040 | } |
2059 | 2041 | ||
2060 | int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter) | 2042 | int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter) |
2061 | { | 2043 | { |
2044 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2062 | int ret; | 2045 | int ret; |
2063 | 2046 | ||
2064 | ret = qlcnic_83xx_get_nic_configuration(adapter); | 2047 | ret = qlcnic_83xx_get_nic_configuration(adapter); |
@@ -2066,11 +2049,16 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter) | |||
2066 | return -EIO; | 2049 | return -EIO; |
2067 | 2050 | ||
2068 | if (ret == QLC_83XX_VIRTUAL_NIC_MODE) { | 2051 | if (ret == QLC_83XX_VIRTUAL_NIC_MODE) { |
2052 | ahw->nic_mode = QLC_83XX_VIRTUAL_NIC_MODE; | ||
2069 | if (qlcnic_83xx_config_vnic_opmode(adapter)) | 2053 | if (qlcnic_83xx_config_vnic_opmode(adapter)) |
2070 | return -EIO; | 2054 | return -EIO; |
2071 | } else if (ret == QLC_83XX_DEFAULT_MODE) { | 2055 | |
2072 | if (qlcnic_83xx_config_default_opmode(adapter)) | 2056 | } else if (ret == QLC_83XX_DEFAULT_OPMODE) { |
2073 | return -EIO; | 2057 | ahw->nic_mode = QLC_83XX_DEFAULT_MODE; |
2058 | adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver; | ||
2059 | ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; | ||
2060 | } else { | ||
2061 | return -EIO; | ||
2074 | } | 2062 | } |
2075 | 2063 | ||
2076 | return 0; | 2064 | return 0; |
@@ -2139,20 +2127,82 @@ static void qlcnic_83xx_clear_function_resources(struct qlcnic_adapter *adapter) | |||
2139 | } | 2127 | } |
2140 | } | 2128 | } |
2141 | 2129 | ||
2130 | static int qlcnic_83xx_get_fw_info(struct qlcnic_adapter *adapter) | ||
2131 | { | ||
2132 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2133 | struct pci_dev *pdev = adapter->pdev; | ||
2134 | struct qlc_83xx_fw_info *fw_info; | ||
2135 | int err = 0; | ||
2136 | |||
2137 | ahw->fw_info = kzalloc(sizeof(*fw_info), GFP_KERNEL); | ||
2138 | if (!ahw->fw_info) { | ||
2139 | err = -ENOMEM; | ||
2140 | } else { | ||
2141 | fw_info = ahw->fw_info; | ||
2142 | switch (pdev->device) { | ||
2143 | case PCI_DEVICE_ID_QLOGIC_QLE834X: | ||
2144 | strncpy(fw_info->fw_file_name, QLC_83XX_FW_FILE_NAME, | ||
2145 | QLC_FW_FILE_NAME_LEN); | ||
2146 | break; | ||
2147 | case PCI_DEVICE_ID_QLOGIC_QLE844X: | ||
2148 | strncpy(fw_info->fw_file_name, QLC_84XX_FW_FILE_NAME, | ||
2149 | QLC_FW_FILE_NAME_LEN); | ||
2150 | break; | ||
2151 | default: | ||
2152 | dev_err(&pdev->dev, "%s: Invalid device id\n", | ||
2153 | __func__); | ||
2154 | err = -EINVAL; | ||
2155 | break; | ||
2156 | } | ||
2157 | } | ||
2158 | |||
2159 | return err; | ||
2160 | } | ||
2161 | |||
2162 | |||
2142 | int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) | 2163 | int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) |
2143 | { | 2164 | { |
2144 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 2165 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
2166 | int err = 0; | ||
2145 | 2167 | ||
2146 | if (qlcnic_sriov_vf_check(adapter)) | 2168 | ahw->msix_supported = !!qlcnic_use_msi_x; |
2147 | return qlcnic_sriov_vf_init(adapter, pci_using_dac); | 2169 | err = qlcnic_83xx_init_mailbox_work(adapter); |
2170 | if (err) | ||
2171 | goto exit; | ||
2148 | 2172 | ||
2149 | if (qlcnic_83xx_check_hw_status(adapter)) | 2173 | if (qlcnic_sriov_vf_check(adapter)) { |
2150 | return -EIO; | 2174 | err = qlcnic_sriov_vf_init(adapter, pci_using_dac); |
2175 | if (err) | ||
2176 | goto detach_mbx; | ||
2177 | else | ||
2178 | return err; | ||
2179 | } | ||
2180 | |||
2181 | err = qlcnic_83xx_check_hw_status(adapter); | ||
2182 | if (err) | ||
2183 | goto detach_mbx; | ||
2184 | |||
2185 | if (!qlcnic_83xx_read_flash_descriptor_table(adapter)) | ||
2186 | qlcnic_83xx_read_flash_mfg_id(adapter); | ||
2187 | |||
2188 | err = qlcnic_83xx_get_fw_info(adapter); | ||
2189 | if (err) | ||
2190 | goto detach_mbx; | ||
2151 | 2191 | ||
2152 | /* Initilaize 83xx mailbox spinlock */ | 2192 | err = qlcnic_83xx_idc_init(adapter); |
2153 | spin_lock_init(&ahw->mbx_lock); | 2193 | if (err) |
2194 | goto clear_fw_info; | ||
2195 | |||
2196 | err = qlcnic_setup_intr(adapter, 0, 0); | ||
2197 | if (err) { | ||
2198 | dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n"); | ||
2199 | goto disable_intr; | ||
2200 | } | ||
2201 | |||
2202 | err = qlcnic_83xx_setup_mbx_intr(adapter); | ||
2203 | if (err) | ||
2204 | goto disable_mbx_intr; | ||
2154 | 2205 | ||
2155 | set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); | ||
2156 | qlcnic_83xx_clear_function_resources(adapter); | 2206 | qlcnic_83xx_clear_function_resources(adapter); |
2157 | 2207 | ||
2158 | INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work); | 2208 | INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work); |
@@ -2160,22 +2210,90 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) | |||
2160 | /* register for NIC IDC AEN Events */ | 2210 | /* register for NIC IDC AEN Events */ |
2161 | qlcnic_83xx_register_nic_idc_func(adapter, 1); | 2211 | qlcnic_83xx_register_nic_idc_func(adapter, 1); |
2162 | 2212 | ||
2163 | if (!qlcnic_83xx_read_flash_descriptor_table(adapter)) | ||
2164 | qlcnic_83xx_read_flash_mfg_id(adapter); | ||
2165 | |||
2166 | if (qlcnic_83xx_idc_init(adapter)) | ||
2167 | return -EIO; | ||
2168 | |||
2169 | /* Configure default, SR-IOV or Virtual NIC mode of operation */ | 2213 | /* Configure default, SR-IOV or Virtual NIC mode of operation */ |
2170 | if (qlcnic_83xx_configure_opmode(adapter)) | 2214 | err = qlcnic_83xx_configure_opmode(adapter); |
2171 | return -EIO; | 2215 | if (err) |
2216 | goto disable_mbx_intr; | ||
2172 | 2217 | ||
2173 | /* Perform operating mode specific initialization */ | 2218 | /* Perform operating mode specific initialization */ |
2174 | if (adapter->nic_ops->init_driver(adapter)) | 2219 | err = adapter->nic_ops->init_driver(adapter); |
2175 | return -EIO; | 2220 | if (err) |
2221 | goto disable_mbx_intr; | ||
2222 | |||
2223 | if (adapter->dcb && qlcnic_dcb_attach(adapter)) | ||
2224 | qlcnic_clear_dcb_ops(adapter); | ||
2176 | 2225 | ||
2177 | /* Periodically monitor device status */ | 2226 | /* Periodically monitor device status */ |
2178 | qlcnic_83xx_idc_poll_dev_state(&adapter->fw_work.work); | 2227 | qlcnic_83xx_idc_poll_dev_state(&adapter->fw_work.work); |
2228 | return 0; | ||
2229 | |||
2230 | disable_mbx_intr: | ||
2231 | qlcnic_83xx_free_mbx_intr(adapter); | ||
2232 | |||
2233 | disable_intr: | ||
2234 | qlcnic_teardown_intr(adapter); | ||
2235 | |||
2236 | clear_fw_info: | ||
2237 | kfree(ahw->fw_info); | ||
2238 | |||
2239 | detach_mbx: | ||
2240 | qlcnic_83xx_detach_mailbox_work(adapter); | ||
2241 | qlcnic_83xx_free_mailbox(ahw->mailbox); | ||
2242 | exit: | ||
2243 | return err; | ||
2244 | } | ||
2245 | |||
2246 | void qlcnic_83xx_aer_stop_poll_work(struct qlcnic_adapter *adapter) | ||
2247 | { | ||
2248 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2249 | struct qlc_83xx_idc *idc = &ahw->idc; | ||
2250 | |||
2251 | clear_bit(QLC_83XX_MBX_READY, &idc->status); | ||
2252 | cancel_delayed_work_sync(&adapter->fw_work); | ||
2253 | |||
2254 | if (ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE) | ||
2255 | qlcnic_83xx_disable_vnic_mode(adapter, 1); | ||
2256 | |||
2257 | qlcnic_83xx_idc_detach_driver(adapter); | ||
2258 | qlcnic_83xx_register_nic_idc_func(adapter, 0); | ||
2259 | |||
2260 | cancel_delayed_work_sync(&adapter->idc_aen_work); | ||
2261 | } | ||
2262 | |||
2263 | int qlcnic_83xx_aer_reset(struct qlcnic_adapter *adapter) | ||
2264 | { | ||
2265 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2266 | struct qlc_83xx_idc *idc = &ahw->idc; | ||
2267 | int ret = 0; | ||
2268 | u32 owner; | ||
2269 | |||
2270 | /* Mark the previous IDC state as NEED_RESET so | ||
2271 | * that state_entry() will perform the reattachment | ||
2272 | * and bringup the device | ||
2273 | */ | ||
2274 | idc->prev_state = QLC_83XX_IDC_DEV_NEED_RESET; | ||
2275 | owner = qlcnic_83xx_idc_find_reset_owner_id(adapter); | ||
2276 | if (ahw->pci_func == owner) { | ||
2277 | ret = qlcnic_83xx_restart_hw(adapter); | ||
2278 | if (ret < 0) | ||
2279 | return ret; | ||
2280 | qlcnic_83xx_idc_clear_registers(adapter, 0); | ||
2281 | } | ||
2282 | |||
2283 | ret = idc->state_entry(adapter); | ||
2284 | return ret; | ||
2285 | } | ||
2286 | |||
2287 | void qlcnic_83xx_aer_start_poll_work(struct qlcnic_adapter *adapter) | ||
2288 | { | ||
2289 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2290 | struct qlc_83xx_idc *idc = &ahw->idc; | ||
2291 | u32 owner; | ||
2292 | |||
2293 | idc->prev_state = QLC_83XX_IDC_DEV_READY; | ||
2294 | owner = qlcnic_83xx_idc_find_reset_owner_id(adapter); | ||
2295 | if (ahw->pci_func == owner) | ||
2296 | qlcnic_83xx_idc_enter_ready_state(adapter, 0); | ||
2179 | 2297 | ||
2180 | return adapter->ahw->idc.err_code; | 2298 | qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state, 0); |
2181 | } | 2299 | } |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c index 599d1fda52f2..0248a4c2f5dd 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c | |||
@@ -208,7 +208,7 @@ int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter) | |||
208 | return -EIO; | 208 | return -EIO; |
209 | } | 209 | } |
210 | 210 | ||
211 | if (ahw->capabilities & BIT_23) | 211 | if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY) |
212 | adapter->flags |= QLCNIC_ESWITCH_ENABLED; | 212 | adapter->flags |= QLCNIC_ESWITCH_ENABLED; |
213 | else | 213 | else |
214 | adapter->flags &= ~QLCNIC_ESWITCH_ENABLED; | 214 | adapter->flags &= ~QLCNIC_ESWITCH_ENABLED; |
@@ -239,3 +239,41 @@ int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *adapter) | |||
239 | 239 | ||
240 | return 0; | 240 | return 0; |
241 | } | 241 | } |
242 | |||
243 | static int qlcnic_83xx_get_eswitch_port_info(struct qlcnic_adapter *adapter, | ||
244 | int func, int *port_id) | ||
245 | { | ||
246 | struct qlcnic_info nic_info; | ||
247 | int err = 0; | ||
248 | |||
249 | memset(&nic_info, 0, sizeof(struct qlcnic_info)); | ||
250 | |||
251 | err = qlcnic_get_nic_info(adapter, &nic_info, func); | ||
252 | if (err) | ||
253 | return err; | ||
254 | |||
255 | if (nic_info.capabilities & QLC_83XX_ESWITCH_CAPABILITY) | ||
256 | *port_id = nic_info.phys_port; | ||
257 | else | ||
258 | err = -EIO; | ||
259 | |||
260 | return err; | ||
261 | } | ||
262 | |||
263 | int qlcnic_83xx_enable_port_eswitch(struct qlcnic_adapter *adapter, int func) | ||
264 | { | ||
265 | int id, err = 0; | ||
266 | |||
267 | err = qlcnic_83xx_get_eswitch_port_info(adapter, func, &id); | ||
268 | if (err) | ||
269 | return err; | ||
270 | |||
271 | if (!(adapter->eswitch[id].flags & QLCNIC_SWITCH_ENABLE)) { | ||
272 | if (!qlcnic_enable_eswitch(adapter, id, 1)) | ||
273 | adapter->eswitch[id].flags |= QLCNIC_SWITCH_ENABLE; | ||
274 | else | ||
275 | err = -EIO; | ||
276 | } | ||
277 | |||
278 | return err; | ||
279 | } | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index d09389b33474..86850dd633a1 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | |||
@@ -38,6 +38,9 @@ static const struct qlcnic_mailbox_metadata qlcnic_mbx_tbl[] = { | |||
38 | {QLCNIC_CMD_GET_TEMP_HDR, 4, 1}, | 38 | {QLCNIC_CMD_GET_TEMP_HDR, 4, 1}, |
39 | {QLCNIC_CMD_82XX_SET_DRV_VER, 4, 1}, | 39 | {QLCNIC_CMD_82XX_SET_DRV_VER, 4, 1}, |
40 | {QLCNIC_CMD_GET_LED_STATUS, 4, 2}, | 40 | {QLCNIC_CMD_GET_LED_STATUS, 4, 2}, |
41 | {QLCNIC_CMD_MQ_TX_CONFIG_INTR, 2, 3}, | ||
42 | {QLCNIC_CMD_DCB_QUERY_CAP, 1, 2}, | ||
43 | {QLCNIC_CMD_DCB_QUERY_PARAM, 4, 1}, | ||
41 | }; | 44 | }; |
42 | 45 | ||
43 | static inline u32 qlcnic_get_cmd_signature(struct qlcnic_hardware_context *ahw) | 46 | static inline u32 qlcnic_get_cmd_signature(struct qlcnic_hardware_context *ahw) |
@@ -171,6 +174,7 @@ int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter, | |||
171 | break; | 174 | break; |
172 | } | 175 | } |
173 | dev_err(&pdev->dev, fmt, cmd->rsp.arg[0]); | 176 | dev_err(&pdev->dev, fmt, cmd->rsp.arg[0]); |
177 | qlcnic_dump_mbx(adapter, cmd); | ||
174 | } else if (rsp == QLCNIC_CDRP_RSP_OK) | 178 | } else if (rsp == QLCNIC_CDRP_RSP_OK) |
175 | cmd->rsp.arg[0] = QLCNIC_RCODE_SUCCESS; | 179 | cmd->rsp.arg[0] = QLCNIC_RCODE_SUCCESS; |
176 | 180 | ||
@@ -243,40 +247,38 @@ qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu) | |||
243 | 247 | ||
244 | int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | 248 | int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) |
245 | { | 249 | { |
246 | void *addr; | 250 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; |
247 | struct qlcnic_hostrq_rx_ctx *prq; | 251 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
248 | struct qlcnic_cardrsp_rx_ctx *prsp; | 252 | dma_addr_t hostrq_phys_addr, cardrsp_phys_addr; |
249 | struct qlcnic_hostrq_rds_ring *prq_rds; | 253 | struct net_device *netdev = adapter->netdev; |
250 | struct qlcnic_hostrq_sds_ring *prq_sds; | 254 | u32 temp_intr_crb_mode, temp_rds_crb_mode; |
251 | struct qlcnic_cardrsp_rds_ring *prsp_rds; | 255 | struct qlcnic_cardrsp_rds_ring *prsp_rds; |
252 | struct qlcnic_cardrsp_sds_ring *prsp_sds; | 256 | struct qlcnic_cardrsp_sds_ring *prsp_sds; |
257 | struct qlcnic_hostrq_rds_ring *prq_rds; | ||
258 | struct qlcnic_hostrq_sds_ring *prq_sds; | ||
253 | struct qlcnic_host_rds_ring *rds_ring; | 259 | struct qlcnic_host_rds_ring *rds_ring; |
254 | struct qlcnic_host_sds_ring *sds_ring; | 260 | struct qlcnic_host_sds_ring *sds_ring; |
255 | struct qlcnic_cmd_args cmd; | 261 | struct qlcnic_cardrsp_rx_ctx *prsp; |
256 | 262 | struct qlcnic_hostrq_rx_ctx *prq; | |
257 | dma_addr_t hostrq_phys_addr, cardrsp_phys_addr; | ||
258 | u64 phys_addr; | ||
259 | |||
260 | u8 i, nrds_rings, nsds_rings; | 263 | u8 i, nrds_rings, nsds_rings; |
261 | u16 temp_u16; | 264 | struct qlcnic_cmd_args cmd; |
262 | size_t rq_size, rsp_size; | 265 | size_t rq_size, rsp_size; |
263 | u32 cap, reg, val, reg2; | 266 | u32 cap, reg, val, reg2; |
267 | u64 phys_addr; | ||
268 | u16 temp_u16; | ||
269 | void *addr; | ||
264 | int err; | 270 | int err; |
265 | 271 | ||
266 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
267 | |||
268 | nrds_rings = adapter->max_rds_rings; | 272 | nrds_rings = adapter->max_rds_rings; |
269 | nsds_rings = adapter->max_sds_rings; | 273 | nsds_rings = adapter->max_sds_rings; |
270 | 274 | ||
271 | rq_size = | 275 | rq_size = SIZEOF_HOSTRQ_RX(struct qlcnic_hostrq_rx_ctx, nrds_rings, |
272 | SIZEOF_HOSTRQ_RX(struct qlcnic_hostrq_rx_ctx, nrds_rings, | 276 | nsds_rings); |
273 | nsds_rings); | 277 | rsp_size = SIZEOF_CARDRSP_RX(struct qlcnic_cardrsp_rx_ctx, nrds_rings, |
274 | rsp_size = | 278 | nsds_rings); |
275 | SIZEOF_CARDRSP_RX(struct qlcnic_cardrsp_rx_ctx, nrds_rings, | ||
276 | nsds_rings); | ||
277 | 279 | ||
278 | addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size, | 280 | addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size, |
279 | &hostrq_phys_addr, GFP_KERNEL); | 281 | &hostrq_phys_addr, GFP_KERNEL); |
280 | if (addr == NULL) | 282 | if (addr == NULL) |
281 | return -ENOMEM; | 283 | return -ENOMEM; |
282 | prq = addr; | 284 | prq = addr; |
@@ -295,15 +297,20 @@ int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
295 | | QLCNIC_CAP0_VALIDOFF); | 297 | | QLCNIC_CAP0_VALIDOFF); |
296 | cap |= (QLCNIC_CAP0_JUMBO_CONTIGUOUS | QLCNIC_CAP0_LRO_CONTIGUOUS); | 298 | cap |= (QLCNIC_CAP0_JUMBO_CONTIGUOUS | QLCNIC_CAP0_LRO_CONTIGUOUS); |
297 | 299 | ||
298 | temp_u16 = offsetof(struct qlcnic_hostrq_rx_ctx, msix_handler); | 300 | if (qlcnic_check_multi_tx(adapter) && |
299 | prq->valid_field_offset = cpu_to_le16(temp_u16); | 301 | !adapter->ahw->diag_test) { |
300 | prq->txrx_sds_binding = nsds_rings - 1; | 302 | cap |= QLCNIC_CAP0_TX_MULTI; |
303 | } else { | ||
304 | temp_u16 = offsetof(struct qlcnic_hostrq_rx_ctx, msix_handler); | ||
305 | prq->valid_field_offset = cpu_to_le16(temp_u16); | ||
306 | prq->txrx_sds_binding = nsds_rings - 1; | ||
307 | temp_intr_crb_mode = QLCNIC_HOST_INT_CRB_MODE_SHARED; | ||
308 | prq->host_int_crb_mode = cpu_to_le32(temp_intr_crb_mode); | ||
309 | temp_rds_crb_mode = QLCNIC_HOST_RDS_CRB_MODE_UNIQUE; | ||
310 | prq->host_rds_crb_mode = cpu_to_le32(temp_rds_crb_mode); | ||
311 | } | ||
301 | 312 | ||
302 | prq->capabilities[0] = cpu_to_le32(cap); | 313 | prq->capabilities[0] = cpu_to_le32(cap); |
303 | prq->host_int_crb_mode = | ||
304 | cpu_to_le32(QLCNIC_HOST_INT_CRB_MODE_SHARED); | ||
305 | prq->host_rds_crb_mode = | ||
306 | cpu_to_le32(QLCNIC_HOST_RDS_CRB_MODE_UNIQUE); | ||
307 | 314 | ||
308 | prq->num_rds_rings = cpu_to_le16(nrds_rings); | 315 | prq->num_rds_rings = cpu_to_le16(nrds_rings); |
309 | prq->num_sds_rings = cpu_to_le16(nsds_rings); | 316 | prq->num_sds_rings = cpu_to_le16(nsds_rings); |
@@ -317,10 +324,8 @@ int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
317 | le32_to_cpu(prq->rds_ring_offset)); | 324 | le32_to_cpu(prq->rds_ring_offset)); |
318 | 325 | ||
319 | for (i = 0; i < nrds_rings; i++) { | 326 | for (i = 0; i < nrds_rings; i++) { |
320 | |||
321 | rds_ring = &recv_ctx->rds_rings[i]; | 327 | rds_ring = &recv_ctx->rds_rings[i]; |
322 | rds_ring->producer = 0; | 328 | rds_ring->producer = 0; |
323 | |||
324 | prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr); | 329 | prq_rds[i].host_phys_addr = cpu_to_le64(rds_ring->phys_addr); |
325 | prq_rds[i].ring_size = cpu_to_le32(rds_ring->num_desc); | 330 | prq_rds[i].ring_size = cpu_to_le32(rds_ring->num_desc); |
326 | prq_rds[i].ring_kind = cpu_to_le32(i); | 331 | prq_rds[i].ring_kind = cpu_to_le32(i); |
@@ -331,14 +336,16 @@ int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
331 | le32_to_cpu(prq->sds_ring_offset)); | 336 | le32_to_cpu(prq->sds_ring_offset)); |
332 | 337 | ||
333 | for (i = 0; i < nsds_rings; i++) { | 338 | for (i = 0; i < nsds_rings; i++) { |
334 | |||
335 | sds_ring = &recv_ctx->sds_rings[i]; | 339 | sds_ring = &recv_ctx->sds_rings[i]; |
336 | sds_ring->consumer = 0; | 340 | sds_ring->consumer = 0; |
337 | memset(sds_ring->desc_head, 0, STATUS_DESC_RINGSIZE(sds_ring)); | 341 | memset(sds_ring->desc_head, 0, STATUS_DESC_RINGSIZE(sds_ring)); |
338 | |||
339 | prq_sds[i].host_phys_addr = cpu_to_le64(sds_ring->phys_addr); | 342 | prq_sds[i].host_phys_addr = cpu_to_le64(sds_ring->phys_addr); |
340 | prq_sds[i].ring_size = cpu_to_le32(sds_ring->num_desc); | 343 | prq_sds[i].ring_size = cpu_to_le32(sds_ring->num_desc); |
341 | prq_sds[i].msi_index = cpu_to_le16(i); | 344 | if (qlcnic_check_multi_tx(adapter) && |
345 | !adapter->ahw->diag_test) | ||
346 | prq_sds[i].msi_index = cpu_to_le16(ahw->intr_tbl[i].id); | ||
347 | else | ||
348 | prq_sds[i].msi_index = cpu_to_le16(i); | ||
342 | } | 349 | } |
343 | 350 | ||
344 | phys_addr = hostrq_phys_addr; | 351 | phys_addr = hostrq_phys_addr; |
@@ -361,9 +368,8 @@ int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
361 | 368 | ||
362 | for (i = 0; i < le16_to_cpu(prsp->num_rds_rings); i++) { | 369 | for (i = 0; i < le16_to_cpu(prsp->num_rds_rings); i++) { |
363 | rds_ring = &recv_ctx->rds_rings[i]; | 370 | rds_ring = &recv_ctx->rds_rings[i]; |
364 | |||
365 | reg = le32_to_cpu(prsp_rds[i].host_producer_crb); | 371 | reg = le32_to_cpu(prsp_rds[i].host_producer_crb); |
366 | rds_ring->crb_rcv_producer = adapter->ahw->pci_base0 + reg; | 372 | rds_ring->crb_rcv_producer = ahw->pci_base0 + reg; |
367 | } | 373 | } |
368 | 374 | ||
369 | prsp_sds = ((struct qlcnic_cardrsp_sds_ring *) | 375 | prsp_sds = ((struct qlcnic_cardrsp_sds_ring *) |
@@ -371,24 +377,30 @@ int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
371 | 377 | ||
372 | for (i = 0; i < le16_to_cpu(prsp->num_sds_rings); i++) { | 378 | for (i = 0; i < le16_to_cpu(prsp->num_sds_rings); i++) { |
373 | sds_ring = &recv_ctx->sds_rings[i]; | 379 | sds_ring = &recv_ctx->sds_rings[i]; |
374 | |||
375 | reg = le32_to_cpu(prsp_sds[i].host_consumer_crb); | 380 | reg = le32_to_cpu(prsp_sds[i].host_consumer_crb); |
376 | reg2 = le32_to_cpu(prsp_sds[i].interrupt_crb); | 381 | if (qlcnic_check_multi_tx(adapter) && !adapter->ahw->diag_test) |
382 | reg2 = ahw->intr_tbl[i].src; | ||
383 | else | ||
384 | reg2 = le32_to_cpu(prsp_sds[i].interrupt_crb); | ||
377 | 385 | ||
378 | sds_ring->crb_sts_consumer = adapter->ahw->pci_base0 + reg; | 386 | sds_ring->crb_intr_mask = ahw->pci_base0 + reg2; |
379 | sds_ring->crb_intr_mask = adapter->ahw->pci_base0 + reg2; | 387 | sds_ring->crb_sts_consumer = ahw->pci_base0 + reg; |
380 | } | 388 | } |
381 | 389 | ||
382 | recv_ctx->state = le32_to_cpu(prsp->host_ctx_state); | 390 | recv_ctx->state = le32_to_cpu(prsp->host_ctx_state); |
383 | recv_ctx->context_id = le16_to_cpu(prsp->context_id); | 391 | recv_ctx->context_id = le16_to_cpu(prsp->context_id); |
384 | recv_ctx->virt_port = prsp->virt_port; | 392 | recv_ctx->virt_port = prsp->virt_port; |
385 | 393 | ||
394 | netdev_info(netdev, "Rx Context[%d] Created, state 0x%x\n", | ||
395 | recv_ctx->context_id, recv_ctx->state); | ||
386 | qlcnic_free_mbx_args(&cmd); | 396 | qlcnic_free_mbx_args(&cmd); |
397 | |||
387 | out_free_rsp: | 398 | out_free_rsp: |
388 | dma_free_coherent(&adapter->pdev->dev, rsp_size, prsp, | 399 | dma_free_coherent(&adapter->pdev->dev, rsp_size, prsp, |
389 | cardrsp_phys_addr); | 400 | cardrsp_phys_addr); |
390 | out_free_rq: | 401 | out_free_rq: |
391 | dma_free_coherent(&adapter->pdev->dev, rq_size, prq, hostrq_phys_addr); | 402 | dma_free_coherent(&adapter->pdev->dev, rq_size, prq, hostrq_phys_addr); |
403 | |||
392 | return err; | 404 | return err; |
393 | } | 405 | } |
394 | 406 | ||
@@ -416,16 +428,19 @@ int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter, | |||
416 | struct qlcnic_host_tx_ring *tx_ring, | 428 | struct qlcnic_host_tx_ring *tx_ring, |
417 | int ring) | 429 | int ring) |
418 | { | 430 | { |
431 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
432 | struct net_device *netdev = adapter->netdev; | ||
419 | struct qlcnic_hostrq_tx_ctx *prq; | 433 | struct qlcnic_hostrq_tx_ctx *prq; |
420 | struct qlcnic_hostrq_cds_ring *prq_cds; | 434 | struct qlcnic_hostrq_cds_ring *prq_cds; |
421 | struct qlcnic_cardrsp_tx_ctx *prsp; | 435 | struct qlcnic_cardrsp_tx_ctx *prsp; |
422 | void *rq_addr, *rsp_addr; | ||
423 | size_t rq_size, rsp_size; | ||
424 | u32 temp; | ||
425 | struct qlcnic_cmd_args cmd; | 436 | struct qlcnic_cmd_args cmd; |
426 | int err; | 437 | u32 temp, intr_mask, temp_int_crb_mode; |
427 | u64 phys_addr; | 438 | dma_addr_t rq_phys_addr, rsp_phys_addr; |
428 | dma_addr_t rq_phys_addr, rsp_phys_addr; | 439 | int temp_nsds_rings, index, err; |
440 | void *rq_addr, *rsp_addr; | ||
441 | size_t rq_size, rsp_size; | ||
442 | u64 phys_addr; | ||
443 | u16 msix_id; | ||
429 | 444 | ||
430 | /* reset host resources */ | 445 | /* reset host resources */ |
431 | tx_ring->producer = 0; | 446 | tx_ring->producer = 0; |
@@ -433,32 +448,42 @@ int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter, | |||
433 | *(tx_ring->hw_consumer) = 0; | 448 | *(tx_ring->hw_consumer) = 0; |
434 | 449 | ||
435 | rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx); | 450 | rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx); |
436 | rq_addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size, | 451 | rq_addr = dma_zalloc_coherent(&adapter->pdev->dev, rq_size, |
437 | &rq_phys_addr, GFP_KERNEL | __GFP_ZERO); | 452 | &rq_phys_addr, GFP_KERNEL); |
438 | if (!rq_addr) | 453 | if (!rq_addr) |
439 | return -ENOMEM; | 454 | return -ENOMEM; |
440 | 455 | ||
441 | rsp_size = SIZEOF_CARDRSP_TX(struct qlcnic_cardrsp_tx_ctx); | 456 | rsp_size = SIZEOF_CARDRSP_TX(struct qlcnic_cardrsp_tx_ctx); |
442 | rsp_addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size, | 457 | rsp_addr = dma_zalloc_coherent(&adapter->pdev->dev, rsp_size, |
443 | &rsp_phys_addr, GFP_KERNEL | __GFP_ZERO); | 458 | &rsp_phys_addr, GFP_KERNEL); |
444 | if (!rsp_addr) { | 459 | if (!rsp_addr) { |
445 | err = -ENOMEM; | 460 | err = -ENOMEM; |
446 | goto out_free_rq; | 461 | goto out_free_rq; |
447 | } | 462 | } |
448 | 463 | ||
449 | prq = rq_addr; | 464 | prq = rq_addr; |
450 | |||
451 | prsp = rsp_addr; | 465 | prsp = rsp_addr; |
452 | 466 | ||
453 | prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr); | 467 | prq->host_rsp_dma_addr = cpu_to_le64(rsp_phys_addr); |
454 | 468 | ||
455 | temp = (QLCNIC_CAP0_LEGACY_CONTEXT | QLCNIC_CAP0_LEGACY_MN | | 469 | temp = (QLCNIC_CAP0_LEGACY_CONTEXT | QLCNIC_CAP0_LEGACY_MN | |
456 | QLCNIC_CAP0_LSO); | 470 | QLCNIC_CAP0_LSO); |
471 | if (qlcnic_check_multi_tx(adapter) && !adapter->ahw->diag_test) | ||
472 | temp |= QLCNIC_CAP0_TX_MULTI; | ||
473 | |||
457 | prq->capabilities[0] = cpu_to_le32(temp); | 474 | prq->capabilities[0] = cpu_to_le32(temp); |
458 | 475 | ||
459 | prq->host_int_crb_mode = | 476 | if (qlcnic_check_multi_tx(adapter) && |
460 | cpu_to_le32(QLCNIC_HOST_INT_CRB_MODE_SHARED); | 477 | !adapter->ahw->diag_test) { |
461 | prq->msi_index = 0; | 478 | temp_nsds_rings = adapter->max_sds_rings; |
479 | index = temp_nsds_rings + ring; | ||
480 | msix_id = ahw->intr_tbl[index].id; | ||
481 | prq->msi_index = cpu_to_le16(msix_id); | ||
482 | } else { | ||
483 | temp_int_crb_mode = QLCNIC_HOST_INT_CRB_MODE_SHARED; | ||
484 | prq->host_int_crb_mode = cpu_to_le32(temp_int_crb_mode); | ||
485 | prq->msi_index = 0; | ||
486 | } | ||
462 | 487 | ||
463 | prq->interrupt_ctl = 0; | 488 | prq->interrupt_ctl = 0; |
464 | prq->cmd_cons_dma_addr = cpu_to_le64(tx_ring->hw_cons_phys_addr); | 489 | prq->cmd_cons_dma_addr = cpu_to_le64(tx_ring->hw_cons_phys_addr); |
@@ -480,15 +505,25 @@ int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter, | |||
480 | err = qlcnic_issue_cmd(adapter, &cmd); | 505 | err = qlcnic_issue_cmd(adapter, &cmd); |
481 | 506 | ||
482 | if (err == QLCNIC_RCODE_SUCCESS) { | 507 | if (err == QLCNIC_RCODE_SUCCESS) { |
508 | tx_ring->state = le32_to_cpu(prsp->host_ctx_state); | ||
483 | temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); | 509 | temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); |
484 | tx_ring->crb_cmd_producer = adapter->ahw->pci_base0 + temp; | 510 | tx_ring->crb_cmd_producer = adapter->ahw->pci_base0 + temp; |
485 | tx_ring->ctx_id = le16_to_cpu(prsp->context_id); | 511 | tx_ring->ctx_id = le16_to_cpu(prsp->context_id); |
512 | if (qlcnic_check_multi_tx(adapter) && | ||
513 | !adapter->ahw->diag_test && | ||
514 | (adapter->flags & QLCNIC_MSIX_ENABLED)) { | ||
515 | index = adapter->max_sds_rings + ring; | ||
516 | intr_mask = ahw->intr_tbl[index].src; | ||
517 | tx_ring->crb_intr_mask = ahw->pci_base0 + intr_mask; | ||
518 | } | ||
519 | |||
520 | netdev_info(netdev, "Tx Context[0x%x] Created, state 0x%x\n", | ||
521 | tx_ring->ctx_id, tx_ring->state); | ||
486 | } else { | 522 | } else { |
487 | dev_err(&adapter->pdev->dev, | 523 | netdev_err(netdev, "Failed to create tx ctx in firmware%d\n", |
488 | "Failed to create tx ctx in firmware%d\n", err); | 524 | err); |
489 | err = -EIO; | 525 | err = -EIO; |
490 | } | 526 | } |
491 | |||
492 | qlcnic_free_mbx_args(&cmd); | 527 | qlcnic_free_mbx_args(&cmd); |
493 | 528 | ||
494 | out_free_rsp: | 529 | out_free_rsp: |
@@ -618,6 +653,13 @@ int qlcnic_fw_create_ctx(struct qlcnic_adapter *dev) | |||
618 | } | 653 | } |
619 | } | 654 | } |
620 | 655 | ||
656 | if (qlcnic_82xx_check(dev) && (dev->flags & QLCNIC_MSIX_ENABLED) && | ||
657 | qlcnic_check_multi_tx(dev) && !dev->ahw->diag_test) { | ||
658 | err = qlcnic_82xx_mq_intrpt(dev, 1); | ||
659 | if (err) | ||
660 | return err; | ||
661 | } | ||
662 | |||
621 | err = qlcnic_fw_cmd_create_rx_ctx(dev); | 663 | err = qlcnic_fw_cmd_create_rx_ctx(dev); |
622 | if (err) | 664 | if (err) |
623 | goto err_out; | 665 | goto err_out; |
@@ -639,13 +681,19 @@ int qlcnic_fw_create_ctx(struct qlcnic_adapter *dev) | |||
639 | } | 681 | } |
640 | 682 | ||
641 | set_bit(__QLCNIC_FW_ATTACHED, &dev->state); | 683 | set_bit(__QLCNIC_FW_ATTACHED, &dev->state); |
684 | |||
642 | return 0; | 685 | return 0; |
643 | 686 | ||
644 | err_out: | 687 | err_out: |
688 | if (qlcnic_82xx_check(dev) && (dev->flags & QLCNIC_MSIX_ENABLED) && | ||
689 | qlcnic_check_multi_tx(dev) && !dev->ahw->diag_test) | ||
690 | qlcnic_82xx_config_intrpt(dev, 0); | ||
691 | |||
645 | if (qlcnic_83xx_check(dev) && (dev->flags & QLCNIC_MSIX_ENABLED)) { | 692 | if (qlcnic_83xx_check(dev) && (dev->flags & QLCNIC_MSIX_ENABLED)) { |
646 | if (dev->ahw->diag_test != QLCNIC_LOOPBACK_TEST) | 693 | if (dev->ahw->diag_test != QLCNIC_LOOPBACK_TEST) |
647 | qlcnic_83xx_config_intrpt(dev, 0); | 694 | qlcnic_83xx_config_intrpt(dev, 0); |
648 | } | 695 | } |
696 | |||
649 | return err; | 697 | return err; |
650 | } | 698 | } |
651 | 699 | ||
@@ -659,6 +707,12 @@ void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter) | |||
659 | qlcnic_fw_cmd_del_tx_ctx(adapter, | 707 | qlcnic_fw_cmd_del_tx_ctx(adapter, |
660 | &adapter->tx_ring[ring]); | 708 | &adapter->tx_ring[ring]); |
661 | 709 | ||
710 | if (qlcnic_82xx_check(adapter) && | ||
711 | (adapter->flags & QLCNIC_MSIX_ENABLED) && | ||
712 | qlcnic_check_multi_tx(adapter) && | ||
713 | !adapter->ahw->diag_test) | ||
714 | qlcnic_82xx_config_intrpt(adapter, 0); | ||
715 | |||
662 | if (qlcnic_83xx_check(adapter) && | 716 | if (qlcnic_83xx_check(adapter) && |
663 | (adapter->flags & QLCNIC_MSIX_ENABLED)) { | 717 | (adapter->flags & QLCNIC_MSIX_ENABLED)) { |
664 | if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) | 718 | if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) |
@@ -723,8 +777,54 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) | |||
723 | } | 777 | } |
724 | } | 778 | } |
725 | 779 | ||
780 | int qlcnic_82xx_config_intrpt(struct qlcnic_adapter *adapter, u8 op_type) | ||
781 | { | ||
782 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
783 | struct net_device *netdev = adapter->netdev; | ||
784 | struct qlcnic_cmd_args cmd; | ||
785 | u32 type, val; | ||
786 | int i, err = 0; | ||
787 | |||
788 | for (i = 0; i < ahw->num_msix; i++) { | ||
789 | qlcnic_alloc_mbx_args(&cmd, adapter, | ||
790 | QLCNIC_CMD_MQ_TX_CONFIG_INTR); | ||
791 | type = op_type ? QLCNIC_INTRPT_ADD : QLCNIC_INTRPT_DEL; | ||
792 | val = type | (ahw->intr_tbl[i].type << 4); | ||
793 | if (ahw->intr_tbl[i].type == QLCNIC_INTRPT_MSIX) | ||
794 | val |= (ahw->intr_tbl[i].id << 16); | ||
795 | cmd.req.arg[1] = val; | ||
796 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
797 | if (err) { | ||
798 | netdev_err(netdev, "Failed to %s interrupts %d\n", | ||
799 | op_type == QLCNIC_INTRPT_ADD ? "Add" : | ||
800 | "Delete", err); | ||
801 | qlcnic_free_mbx_args(&cmd); | ||
802 | return err; | ||
803 | } | ||
804 | val = cmd.rsp.arg[1]; | ||
805 | if (LSB(val)) { | ||
806 | netdev_info(netdev, | ||
807 | "failed to configure interrupt for %d\n", | ||
808 | ahw->intr_tbl[i].id); | ||
809 | continue; | ||
810 | } | ||
811 | if (op_type) { | ||
812 | ahw->intr_tbl[i].id = MSW(val); | ||
813 | ahw->intr_tbl[i].enabled = 1; | ||
814 | ahw->intr_tbl[i].src = cmd.rsp.arg[2]; | ||
815 | } else { | ||
816 | ahw->intr_tbl[i].id = i; | ||
817 | ahw->intr_tbl[i].enabled = 0; | ||
818 | ahw->intr_tbl[i].src = 0; | ||
819 | } | ||
820 | qlcnic_free_mbx_args(&cmd); | ||
821 | } | ||
822 | |||
823 | return err; | ||
824 | } | ||
726 | 825 | ||
727 | int qlcnic_82xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac) | 826 | int qlcnic_82xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac, |
827 | u8 function) | ||
728 | { | 828 | { |
729 | int err, i; | 829 | int err, i; |
730 | struct qlcnic_cmd_args cmd; | 830 | struct qlcnic_cmd_args cmd; |
@@ -734,7 +834,7 @@ int qlcnic_82xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac) | |||
734 | if (err) | 834 | if (err) |
735 | return err; | 835 | return err; |
736 | 836 | ||
737 | cmd.req.arg[1] = adapter->ahw->pci_func | BIT_8; | 837 | cmd.req.arg[1] = function | BIT_8; |
738 | err = qlcnic_issue_cmd(adapter, &cmd); | 838 | err = qlcnic_issue_cmd(adapter, &cmd); |
739 | 839 | ||
740 | if (err == QLCNIC_RCODE_SUCCESS) { | 840 | if (err == QLCNIC_RCODE_SUCCESS) { |
@@ -765,8 +865,8 @@ int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter, | |||
765 | struct qlcnic_cmd_args cmd; | 865 | struct qlcnic_cmd_args cmd; |
766 | size_t nic_size = sizeof(struct qlcnic_info_le); | 866 | size_t nic_size = sizeof(struct qlcnic_info_le); |
767 | 867 | ||
768 | nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size, | 868 | nic_info_addr = dma_zalloc_coherent(&adapter->pdev->dev, nic_size, |
769 | &nic_dma_t, GFP_KERNEL | __GFP_ZERO); | 869 | &nic_dma_t, GFP_KERNEL); |
770 | if (!nic_info_addr) | 870 | if (!nic_info_addr) |
771 | return -ENOMEM; | 871 | return -ENOMEM; |
772 | 872 | ||
@@ -819,8 +919,8 @@ int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *adapter, | |||
819 | if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) | 919 | if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) |
820 | return err; | 920 | return err; |
821 | 921 | ||
822 | nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size, | 922 | nic_info_addr = dma_zalloc_coherent(&adapter->pdev->dev, nic_size, |
823 | &nic_dma_t, GFP_KERNEL | __GFP_ZERO); | 923 | &nic_dma_t, GFP_KERNEL); |
824 | if (!nic_info_addr) | 924 | if (!nic_info_addr) |
825 | return -ENOMEM; | 925 | return -ENOMEM; |
826 | 926 | ||
@@ -872,9 +972,8 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter, | |||
872 | size_t npar_size = sizeof(struct qlcnic_pci_info_le); | 972 | size_t npar_size = sizeof(struct qlcnic_pci_info_le); |
873 | size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC; | 973 | size_t pci_size = npar_size * QLCNIC_MAX_PCI_FUNC; |
874 | 974 | ||
875 | pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size, | 975 | pci_info_addr = dma_zalloc_coherent(&adapter->pdev->dev, pci_size, |
876 | &pci_info_dma_t, | 976 | &pci_info_dma_t, GFP_KERNEL); |
877 | GFP_KERNEL | __GFP_ZERO); | ||
878 | if (!pci_info_addr) | 977 | if (!pci_info_addr) |
879 | return -ENOMEM; | 978 | return -ENOMEM; |
880 | 979 | ||
@@ -974,8 +1073,8 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, | |||
974 | return -EIO; | 1073 | return -EIO; |
975 | } | 1074 | } |
976 | 1075 | ||
977 | stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size, | 1076 | stats_addr = dma_zalloc_coherent(&adapter->pdev->dev, stats_size, |
978 | &stats_dma_t, GFP_KERNEL | __GFP_ZERO); | 1077 | &stats_dma_t, GFP_KERNEL); |
979 | if (!stats_addr) | 1078 | if (!stats_addr) |
980 | return -ENOMEM; | 1079 | return -ENOMEM; |
981 | 1080 | ||
@@ -1030,8 +1129,8 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter, | |||
1030 | if (mac_stats == NULL) | 1129 | if (mac_stats == NULL) |
1031 | return -ENOMEM; | 1130 | return -ENOMEM; |
1032 | 1131 | ||
1033 | stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size, | 1132 | stats_addr = dma_zalloc_coherent(&adapter->pdev->dev, stats_size, |
1034 | &stats_dma_t, GFP_KERNEL | __GFP_ZERO); | 1133 | &stats_dma_t, GFP_KERNEL); |
1035 | if (!stats_addr) | 1134 | if (!stats_addr) |
1036 | return -ENOMEM; | 1135 | return -ENOMEM; |
1037 | 1136 | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c new file mode 100644 index 000000000000..d62d5ce432ec --- /dev/null +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.c | |||
@@ -0,0 +1,1179 @@ | |||
1 | /* | ||
2 | * QLogic qlcnic NIC Driver | ||
3 | * Copyright (c) 2009-2013 QLogic Corporation | ||
4 | * | ||
5 | * See LICENSE.qlcnic for copyright and licensing details. | ||
6 | */ | ||
7 | |||
8 | #include <linux/types.h> | ||
9 | #include "qlcnic.h" | ||
10 | |||
11 | #define QLC_DCB_NUM_PARAM 3 | ||
12 | #define QLC_DCB_LOCAL_IDX 0 | ||
13 | #define QLC_DCB_OPER_IDX 1 | ||
14 | #define QLC_DCB_PEER_IDX 2 | ||
15 | |||
16 | #define QLC_DCB_GET_MAP(V) (1 << V) | ||
17 | |||
18 | #define QLC_DCB_AEN_BIT 0x2 | ||
19 | #define QLC_DCB_FW_VER 0x2 | ||
20 | #define QLC_DCB_MAX_TC 0x8 | ||
21 | #define QLC_DCB_MAX_APP 0x8 | ||
22 | #define QLC_DCB_MAX_PRIO QLC_DCB_MAX_TC | ||
23 | #define QLC_DCB_MAX_PG QLC_DCB_MAX_TC | ||
24 | |||
25 | #define QLC_DCB_TSA_SUPPORT(V) (V & 0x1) | ||
26 | #define QLC_DCB_ETS_SUPPORT(V) ((V >> 1) & 0x1) | ||
27 | #define QLC_DCB_VERSION_SUPPORT(V) ((V >> 2) & 0xf) | ||
28 | #define QLC_DCB_MAX_NUM_TC(V) ((V >> 20) & 0xf) | ||
29 | #define QLC_DCB_MAX_NUM_ETS_TC(V) ((V >> 24) & 0xf) | ||
30 | #define QLC_DCB_MAX_NUM_PFC_TC(V) ((V >> 28) & 0xf) | ||
31 | #define QLC_DCB_GET_TC_PRIO(X, P) ((X >> (P * 3)) & 0x7) | ||
32 | #define QLC_DCB_GET_PGID_PRIO(X, P) ((X >> (P * 8)) & 0xff) | ||
33 | #define QLC_DCB_GET_BWPER_PG(X, P) ((X >> (P * 8)) & 0xff) | ||
34 | #define QLC_DCB_GET_TSA_PG(X, P) ((X >> (P * 8)) & 0xff) | ||
35 | #define QLC_DCB_GET_PFC_PRIO(X, P) (((X >> 24) >> P) & 0x1) | ||
36 | #define QLC_DCB_GET_PROTO_ID_APP(X) ((X >> 8) & 0xffff) | ||
37 | #define QLC_DCB_GET_SELECTOR_APP(X) (X & 0xff) | ||
38 | |||
39 | #define QLC_DCB_LOCAL_PARAM_FWID 0x3 | ||
40 | #define QLC_DCB_OPER_PARAM_FWID 0x1 | ||
41 | #define QLC_DCB_PEER_PARAM_FWID 0x2 | ||
42 | |||
43 | #define QLC_83XX_DCB_GET_NUMAPP(X) ((X >> 2) & 0xf) | ||
44 | #define QLC_83XX_DCB_TSA_VALID(X) (X & 0x1) | ||
45 | #define QLC_83XX_DCB_PFC_VALID(X) ((X >> 1) & 0x1) | ||
46 | #define QLC_83XX_DCB_GET_PRIOMAP_APP(X) (X >> 24) | ||
47 | |||
48 | #define QLC_82XX_DCB_GET_NUMAPP(X) ((X >> 12) & 0xf) | ||
49 | #define QLC_82XX_DCB_TSA_VALID(X) ((X >> 4) & 0x1) | ||
50 | #define QLC_82XX_DCB_PFC_VALID(X) ((X >> 5) & 0x1) | ||
51 | #define QLC_82XX_DCB_GET_PRIOVAL_APP(X) ((X >> 24) & 0x7) | ||
52 | #define QLC_82XX_DCB_GET_PRIOMAP_APP(X) (1 << X) | ||
53 | #define QLC_82XX_DCB_PRIO_TC_MAP (0x76543210) | ||
54 | |||
55 | static const struct dcbnl_rtnl_ops qlcnic_dcbnl_ops; | ||
56 | |||
57 | static void qlcnic_dcb_aen_work(struct work_struct *); | ||
58 | static void qlcnic_dcb_data_cee_param_map(struct qlcnic_adapter *); | ||
59 | |||
60 | static inline void __qlcnic_init_dcbnl_ops(struct qlcnic_adapter *); | ||
61 | static void __qlcnic_dcb_free(struct qlcnic_adapter *); | ||
62 | static int __qlcnic_dcb_attach(struct qlcnic_adapter *); | ||
63 | static int __qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *, char *); | ||
64 | static void __qlcnic_dcb_get_info(struct qlcnic_adapter *); | ||
65 | |||
66 | static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_adapter *); | ||
67 | static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_adapter *, char *, u8); | ||
68 | static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_adapter *); | ||
69 | static void qlcnic_82xx_dcb_handle_aen(struct qlcnic_adapter *, void *); | ||
70 | |||
71 | static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *); | ||
72 | static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_adapter *, char *, u8); | ||
73 | static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_adapter *); | ||
74 | static int qlcnic_83xx_dcb_register_aen(struct qlcnic_adapter *, bool); | ||
75 | static void qlcnic_83xx_dcb_handle_aen(struct qlcnic_adapter *, void *); | ||
76 | |||
77 | struct qlcnic_dcb_capability { | ||
78 | bool tsa_capability; | ||
79 | bool ets_capability; | ||
80 | u8 max_num_tc; | ||
81 | u8 max_ets_tc; | ||
82 | u8 max_pfc_tc; | ||
83 | u8 dcb_capability; | ||
84 | }; | ||
85 | |||
86 | struct qlcnic_dcb_param { | ||
87 | u32 hdr_prio_pfc_map[2]; | ||
88 | u32 prio_pg_map[2]; | ||
89 | u32 pg_bw_map[2]; | ||
90 | u32 pg_tsa_map[2]; | ||
91 | u32 app[QLC_DCB_MAX_APP]; | ||
92 | }; | ||
93 | |||
94 | struct qlcnic_dcb_mbx_params { | ||
95 | /* 1st local, 2nd operational 3rd remote */ | ||
96 | struct qlcnic_dcb_param type[3]; | ||
97 | u32 prio_tc_map; | ||
98 | }; | ||
99 | |||
100 | struct qlcnic_82xx_dcb_param_mbx_le { | ||
101 | __le32 hdr_prio_pfc_map[2]; | ||
102 | __le32 prio_pg_map[2]; | ||
103 | __le32 pg_bw_map[2]; | ||
104 | __le32 pg_tsa_map[2]; | ||
105 | __le32 app[QLC_DCB_MAX_APP]; | ||
106 | }; | ||
107 | |||
108 | enum qlcnic_dcb_selector { | ||
109 | QLC_SELECTOR_DEF = 0x0, | ||
110 | QLC_SELECTOR_ETHER, | ||
111 | QLC_SELECTOR_TCP, | ||
112 | QLC_SELECTOR_UDP, | ||
113 | }; | ||
114 | |||
115 | enum qlcnic_dcb_prio_type { | ||
116 | QLC_PRIO_NONE = 0, | ||
117 | QLC_PRIO_GROUP, | ||
118 | QLC_PRIO_LINK, | ||
119 | }; | ||
120 | |||
121 | enum qlcnic_dcb_pfc_type { | ||
122 | QLC_PFC_DISABLED = 0, | ||
123 | QLC_PFC_FULL, | ||
124 | QLC_PFC_TX, | ||
125 | QLC_PFC_RX | ||
126 | }; | ||
127 | |||
128 | struct qlcnic_dcb_prio_cfg { | ||
129 | bool valid; | ||
130 | enum qlcnic_dcb_pfc_type pfc_type; | ||
131 | }; | ||
132 | |||
133 | struct qlcnic_dcb_pg_cfg { | ||
134 | bool valid; | ||
135 | u8 total_bw_percent; /* of Link/ port BW */ | ||
136 | u8 prio_count; | ||
137 | u8 tsa_type; | ||
138 | }; | ||
139 | |||
140 | struct qlcnic_dcb_tc_cfg { | ||
141 | bool valid; | ||
142 | struct qlcnic_dcb_prio_cfg prio_cfg[QLC_DCB_MAX_PRIO]; | ||
143 | enum qlcnic_dcb_prio_type prio_type; /* always prio_link */ | ||
144 | u8 link_percent; /* % of link bandwidth */ | ||
145 | u8 bwg_percent; /* % of BWG's bandwidth */ | ||
146 | u8 up_tc_map; | ||
147 | u8 pgid; | ||
148 | }; | ||
149 | |||
150 | struct qlcnic_dcb_app { | ||
151 | bool valid; | ||
152 | enum qlcnic_dcb_selector selector; | ||
153 | u16 protocol; | ||
154 | u8 priority; | ||
155 | }; | ||
156 | |||
157 | struct qlcnic_dcb_cee { | ||
158 | struct qlcnic_dcb_tc_cfg tc_cfg[QLC_DCB_MAX_TC]; | ||
159 | struct qlcnic_dcb_pg_cfg pg_cfg[QLC_DCB_MAX_PG]; | ||
160 | struct qlcnic_dcb_app app[QLC_DCB_MAX_APP]; | ||
161 | bool tc_param_valid; | ||
162 | bool pfc_mode_enable; | ||
163 | }; | ||
164 | |||
165 | struct qlcnic_dcb_cfg { | ||
166 | /* 0 - local, 1 - operational, 2 - remote */ | ||
167 | struct qlcnic_dcb_cee type[QLC_DCB_NUM_PARAM]; | ||
168 | struct qlcnic_dcb_capability capability; | ||
169 | u32 version; | ||
170 | }; | ||
171 | |||
172 | static struct qlcnic_dcb_ops qlcnic_83xx_dcb_ops = { | ||
173 | .init_dcbnl_ops = __qlcnic_init_dcbnl_ops, | ||
174 | .free = __qlcnic_dcb_free, | ||
175 | .attach = __qlcnic_dcb_attach, | ||
176 | .query_hw_capability = __qlcnic_dcb_query_hw_capability, | ||
177 | .get_info = __qlcnic_dcb_get_info, | ||
178 | |||
179 | .get_hw_capability = qlcnic_83xx_dcb_get_hw_capability, | ||
180 | .query_cee_param = qlcnic_83xx_dcb_query_cee_param, | ||
181 | .get_cee_cfg = qlcnic_83xx_dcb_get_cee_cfg, | ||
182 | .register_aen = qlcnic_83xx_dcb_register_aen, | ||
183 | .handle_aen = qlcnic_83xx_dcb_handle_aen, | ||
184 | }; | ||
185 | |||
186 | static struct qlcnic_dcb_ops qlcnic_82xx_dcb_ops = { | ||
187 | .init_dcbnl_ops = __qlcnic_init_dcbnl_ops, | ||
188 | .free = __qlcnic_dcb_free, | ||
189 | .attach = __qlcnic_dcb_attach, | ||
190 | .query_hw_capability = __qlcnic_dcb_query_hw_capability, | ||
191 | .get_info = __qlcnic_dcb_get_info, | ||
192 | |||
193 | .get_hw_capability = qlcnic_82xx_dcb_get_hw_capability, | ||
194 | .query_cee_param = qlcnic_82xx_dcb_query_cee_param, | ||
195 | .get_cee_cfg = qlcnic_82xx_dcb_get_cee_cfg, | ||
196 | .handle_aen = qlcnic_82xx_dcb_handle_aen, | ||
197 | }; | ||
198 | |||
199 | static u8 qlcnic_dcb_get_num_app(struct qlcnic_adapter *adapter, u32 val) | ||
200 | { | ||
201 | if (qlcnic_82xx_check(adapter)) | ||
202 | return QLC_82XX_DCB_GET_NUMAPP(val); | ||
203 | else | ||
204 | return QLC_83XX_DCB_GET_NUMAPP(val); | ||
205 | } | ||
206 | |||
207 | static inline u8 qlcnic_dcb_pfc_hdr_valid(struct qlcnic_adapter *adapter, | ||
208 | u32 val) | ||
209 | { | ||
210 | if (qlcnic_82xx_check(adapter)) | ||
211 | return QLC_82XX_DCB_PFC_VALID(val); | ||
212 | else | ||
213 | return QLC_83XX_DCB_PFC_VALID(val); | ||
214 | } | ||
215 | |||
216 | static inline u8 qlcnic_dcb_tsa_hdr_valid(struct qlcnic_adapter *adapter, | ||
217 | u32 val) | ||
218 | { | ||
219 | if (qlcnic_82xx_check(adapter)) | ||
220 | return QLC_82XX_DCB_TSA_VALID(val); | ||
221 | else | ||
222 | return QLC_83XX_DCB_TSA_VALID(val); | ||
223 | } | ||
224 | |||
225 | static inline u8 qlcnic_dcb_get_prio_map_app(struct qlcnic_adapter *adapter, | ||
226 | u32 val) | ||
227 | { | ||
228 | if (qlcnic_82xx_check(adapter)) | ||
229 | return QLC_82XX_DCB_GET_PRIOMAP_APP(val); | ||
230 | else | ||
231 | return QLC_83XX_DCB_GET_PRIOMAP_APP(val); | ||
232 | } | ||
233 | |||
234 | static int qlcnic_dcb_prio_count(u8 up_tc_map) | ||
235 | { | ||
236 | int j; | ||
237 | |||
238 | for (j = 0; j < QLC_DCB_MAX_TC; j++) | ||
239 | if (up_tc_map & QLC_DCB_GET_MAP(j)) | ||
240 | break; | ||
241 | |||
242 | return j; | ||
243 | } | ||
244 | |||
245 | static inline void __qlcnic_init_dcbnl_ops(struct qlcnic_adapter *adapter) | ||
246 | { | ||
247 | if (test_bit(__QLCNIC_DCB_STATE, &adapter->state)) | ||
248 | adapter->netdev->dcbnl_ops = &qlcnic_dcbnl_ops; | ||
249 | } | ||
250 | |||
251 | static void qlcnic_set_dcb_ops(struct qlcnic_adapter *adapter) | ||
252 | { | ||
253 | if (qlcnic_82xx_check(adapter)) | ||
254 | adapter->dcb->ops = &qlcnic_82xx_dcb_ops; | ||
255 | else if (qlcnic_83xx_check(adapter)) | ||
256 | adapter->dcb->ops = &qlcnic_83xx_dcb_ops; | ||
257 | } | ||
258 | |||
259 | int __qlcnic_register_dcb(struct qlcnic_adapter *adapter) | ||
260 | { | ||
261 | struct qlcnic_dcb *dcb; | ||
262 | |||
263 | dcb = kzalloc(sizeof(struct qlcnic_dcb), GFP_ATOMIC); | ||
264 | if (!dcb) | ||
265 | return -ENOMEM; | ||
266 | |||
267 | adapter->dcb = dcb; | ||
268 | dcb->adapter = adapter; | ||
269 | qlcnic_set_dcb_ops(adapter); | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static void __qlcnic_dcb_free(struct qlcnic_adapter *adapter) | ||
275 | { | ||
276 | struct qlcnic_dcb *dcb = adapter->dcb; | ||
277 | |||
278 | if (!dcb) | ||
279 | return; | ||
280 | |||
281 | qlcnic_dcb_register_aen(adapter, 0); | ||
282 | |||
283 | while (test_bit(__QLCNIC_DCB_IN_AEN, &adapter->state)) | ||
284 | usleep_range(10000, 11000); | ||
285 | |||
286 | cancel_delayed_work_sync(&dcb->aen_work); | ||
287 | |||
288 | if (dcb->wq) { | ||
289 | destroy_workqueue(dcb->wq); | ||
290 | dcb->wq = NULL; | ||
291 | } | ||
292 | |||
293 | kfree(dcb->cfg); | ||
294 | dcb->cfg = NULL; | ||
295 | kfree(dcb->param); | ||
296 | dcb->param = NULL; | ||
297 | kfree(dcb); | ||
298 | adapter->dcb = NULL; | ||
299 | } | ||
300 | |||
301 | static void __qlcnic_dcb_get_info(struct qlcnic_adapter *adapter) | ||
302 | { | ||
303 | qlcnic_dcb_get_hw_capability(adapter); | ||
304 | qlcnic_dcb_get_cee_cfg(adapter); | ||
305 | qlcnic_dcb_register_aen(adapter, 1); | ||
306 | } | ||
307 | |||
308 | static int __qlcnic_dcb_attach(struct qlcnic_adapter *adapter) | ||
309 | { | ||
310 | struct qlcnic_dcb *dcb = adapter->dcb; | ||
311 | int err = 0; | ||
312 | |||
313 | INIT_DELAYED_WORK(&dcb->aen_work, qlcnic_dcb_aen_work); | ||
314 | |||
315 | dcb->wq = create_singlethread_workqueue("qlcnic-dcb"); | ||
316 | if (!dcb->wq) { | ||
317 | dev_err(&adapter->pdev->dev, | ||
318 | "DCB workqueue allocation failed. DCB will be disabled\n"); | ||
319 | return -1; | ||
320 | } | ||
321 | |||
322 | dcb->cfg = kzalloc(sizeof(struct qlcnic_dcb_cfg), GFP_ATOMIC); | ||
323 | if (!dcb->cfg) { | ||
324 | err = -ENOMEM; | ||
325 | goto out_free_wq; | ||
326 | } | ||
327 | |||
328 | dcb->param = kzalloc(sizeof(struct qlcnic_dcb_mbx_params), GFP_ATOMIC); | ||
329 | if (!dcb->param) { | ||
330 | err = -ENOMEM; | ||
331 | goto out_free_cfg; | ||
332 | } | ||
333 | |||
334 | qlcnic_dcb_get_info(adapter); | ||
335 | |||
336 | return 0; | ||
337 | out_free_cfg: | ||
338 | kfree(dcb->cfg); | ||
339 | dcb->cfg = NULL; | ||
340 | |||
341 | out_free_wq: | ||
342 | destroy_workqueue(dcb->wq); | ||
343 | dcb->wq = NULL; | ||
344 | |||
345 | return err; | ||
346 | } | ||
347 | |||
348 | static int __qlcnic_dcb_query_hw_capability(struct qlcnic_adapter *adapter, | ||
349 | char *buf) | ||
350 | { | ||
351 | struct qlcnic_cmd_args cmd; | ||
352 | u32 mbx_out; | ||
353 | int err; | ||
354 | |||
355 | err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_CAP); | ||
356 | if (err) | ||
357 | return err; | ||
358 | |||
359 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
360 | if (err) { | ||
361 | dev_err(&adapter->pdev->dev, | ||
362 | "Failed to query DCBX capability, err %d\n", err); | ||
363 | } else { | ||
364 | mbx_out = cmd.rsp.arg[1]; | ||
365 | if (buf) | ||
366 | memcpy(buf, &mbx_out, sizeof(u32)); | ||
367 | } | ||
368 | |||
369 | qlcnic_free_mbx_args(&cmd); | ||
370 | |||
371 | return err; | ||
372 | } | ||
373 | |||
374 | static int __qlcnic_dcb_get_capability(struct qlcnic_adapter *adapter, u32 *val) | ||
375 | { | ||
376 | struct qlcnic_dcb_capability *cap = &adapter->dcb->cfg->capability; | ||
377 | u32 mbx_out; | ||
378 | int err; | ||
379 | |||
380 | memset(cap, 0, sizeof(struct qlcnic_dcb_capability)); | ||
381 | |||
382 | err = qlcnic_dcb_query_hw_capability(adapter, (char *)val); | ||
383 | if (err) | ||
384 | return err; | ||
385 | |||
386 | mbx_out = *val; | ||
387 | if (QLC_DCB_TSA_SUPPORT(mbx_out)) | ||
388 | cap->tsa_capability = true; | ||
389 | |||
390 | if (QLC_DCB_ETS_SUPPORT(mbx_out)) | ||
391 | cap->ets_capability = true; | ||
392 | |||
393 | cap->max_num_tc = QLC_DCB_MAX_NUM_TC(mbx_out); | ||
394 | cap->max_ets_tc = QLC_DCB_MAX_NUM_ETS_TC(mbx_out); | ||
395 | cap->max_pfc_tc = QLC_DCB_MAX_NUM_PFC_TC(mbx_out); | ||
396 | |||
397 | if (cap->max_num_tc > QLC_DCB_MAX_TC || | ||
398 | cap->max_ets_tc > cap->max_num_tc || | ||
399 | cap->max_pfc_tc > cap->max_num_tc) { | ||
400 | dev_err(&adapter->pdev->dev, "Invalid DCB configuration\n"); | ||
401 | return -EINVAL; | ||
402 | } | ||
403 | |||
404 | return err; | ||
405 | } | ||
406 | |||
407 | static int qlcnic_82xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter) | ||
408 | { | ||
409 | struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg; | ||
410 | struct qlcnic_dcb_capability *cap; | ||
411 | u32 mbx_out; | ||
412 | int err; | ||
413 | |||
414 | err = __qlcnic_dcb_get_capability(adapter, &mbx_out); | ||
415 | if (err) | ||
416 | return err; | ||
417 | |||
418 | cap = &cfg->capability; | ||
419 | cap->dcb_capability = DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_LLD_MANAGED; | ||
420 | |||
421 | if (cap->dcb_capability && cap->tsa_capability && cap->ets_capability) | ||
422 | set_bit(__QLCNIC_DCB_STATE, &adapter->state); | ||
423 | |||
424 | return err; | ||
425 | } | ||
426 | |||
427 | static int qlcnic_82xx_dcb_query_cee_param(struct qlcnic_adapter *adapter, | ||
428 | char *buf, u8 type) | ||
429 | { | ||
430 | u16 size = sizeof(struct qlcnic_82xx_dcb_param_mbx_le); | ||
431 | struct qlcnic_82xx_dcb_param_mbx_le *prsp_le; | ||
432 | struct device *dev = &adapter->pdev->dev; | ||
433 | dma_addr_t cardrsp_phys_addr; | ||
434 | struct qlcnic_dcb_param rsp; | ||
435 | struct qlcnic_cmd_args cmd; | ||
436 | u64 phys_addr; | ||
437 | void *addr; | ||
438 | int err, i; | ||
439 | |||
440 | switch (type) { | ||
441 | case QLC_DCB_LOCAL_PARAM_FWID: | ||
442 | case QLC_DCB_OPER_PARAM_FWID: | ||
443 | case QLC_DCB_PEER_PARAM_FWID: | ||
444 | break; | ||
445 | default: | ||
446 | dev_err(dev, "Invalid parameter type %d\n", type); | ||
447 | return -EINVAL; | ||
448 | } | ||
449 | |||
450 | addr = dma_alloc_coherent(&adapter->pdev->dev, size, &cardrsp_phys_addr, | ||
451 | GFP_KERNEL); | ||
452 | if (addr == NULL) | ||
453 | return -ENOMEM; | ||
454 | |||
455 | prsp_le = addr; | ||
456 | |||
457 | err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_PARAM); | ||
458 | if (err) | ||
459 | goto out_free_rsp; | ||
460 | |||
461 | phys_addr = cardrsp_phys_addr; | ||
462 | cmd.req.arg[1] = size | (type << 16); | ||
463 | cmd.req.arg[2] = MSD(phys_addr); | ||
464 | cmd.req.arg[3] = LSD(phys_addr); | ||
465 | |||
466 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
467 | if (err) { | ||
468 | dev_err(dev, "Failed to query DCBX parameter, err %d\n", err); | ||
469 | goto out; | ||
470 | } | ||
471 | |||
472 | memset(&rsp, 0, sizeof(struct qlcnic_dcb_param)); | ||
473 | rsp.hdr_prio_pfc_map[0] = le32_to_cpu(prsp_le->hdr_prio_pfc_map[0]); | ||
474 | rsp.hdr_prio_pfc_map[1] = le32_to_cpu(prsp_le->hdr_prio_pfc_map[1]); | ||
475 | rsp.prio_pg_map[0] = le32_to_cpu(prsp_le->prio_pg_map[0]); | ||
476 | rsp.prio_pg_map[1] = le32_to_cpu(prsp_le->prio_pg_map[1]); | ||
477 | rsp.pg_bw_map[0] = le32_to_cpu(prsp_le->pg_bw_map[0]); | ||
478 | rsp.pg_bw_map[1] = le32_to_cpu(prsp_le->pg_bw_map[1]); | ||
479 | rsp.pg_tsa_map[0] = le32_to_cpu(prsp_le->pg_tsa_map[0]); | ||
480 | rsp.pg_tsa_map[1] = le32_to_cpu(prsp_le->pg_tsa_map[1]); | ||
481 | |||
482 | for (i = 0; i < QLC_DCB_MAX_APP; i++) | ||
483 | rsp.app[i] = le32_to_cpu(prsp_le->app[i]); | ||
484 | |||
485 | if (buf) | ||
486 | memcpy(buf, &rsp, size); | ||
487 | out: | ||
488 | qlcnic_free_mbx_args(&cmd); | ||
489 | |||
490 | out_free_rsp: | ||
491 | dma_free_coherent(&adapter->pdev->dev, size, addr, cardrsp_phys_addr); | ||
492 | |||
493 | return err; | ||
494 | } | ||
495 | |||
496 | static int qlcnic_82xx_dcb_get_cee_cfg(struct qlcnic_adapter *adapter) | ||
497 | { | ||
498 | struct qlcnic_dcb_mbx_params *mbx; | ||
499 | int err; | ||
500 | |||
501 | mbx = adapter->dcb->param; | ||
502 | if (!mbx) | ||
503 | return 0; | ||
504 | |||
505 | err = qlcnic_dcb_query_cee_param(adapter, (char *)&mbx->type[0], | ||
506 | QLC_DCB_LOCAL_PARAM_FWID); | ||
507 | if (err) | ||
508 | return err; | ||
509 | |||
510 | err = qlcnic_dcb_query_cee_param(adapter, (char *)&mbx->type[1], | ||
511 | QLC_DCB_OPER_PARAM_FWID); | ||
512 | if (err) | ||
513 | return err; | ||
514 | |||
515 | err = qlcnic_dcb_query_cee_param(adapter, (char *)&mbx->type[2], | ||
516 | QLC_DCB_PEER_PARAM_FWID); | ||
517 | if (err) | ||
518 | return err; | ||
519 | |||
520 | mbx->prio_tc_map = QLC_82XX_DCB_PRIO_TC_MAP; | ||
521 | |||
522 | qlcnic_dcb_data_cee_param_map(adapter); | ||
523 | |||
524 | return err; | ||
525 | } | ||
526 | |||
527 | static void qlcnic_dcb_aen_work(struct work_struct *work) | ||
528 | { | ||
529 | struct qlcnic_adapter *adapter; | ||
530 | struct qlcnic_dcb *dcb; | ||
531 | |||
532 | dcb = container_of(work, struct qlcnic_dcb, aen_work.work); | ||
533 | adapter = dcb->adapter; | ||
534 | |||
535 | qlcnic_dcb_get_cee_cfg(adapter); | ||
536 | clear_bit(__QLCNIC_DCB_IN_AEN, &adapter->state); | ||
537 | } | ||
538 | |||
539 | static void qlcnic_82xx_dcb_handle_aen(struct qlcnic_adapter *adapter, | ||
540 | void *data) | ||
541 | { | ||
542 | struct qlcnic_dcb *dcb = adapter->dcb; | ||
543 | |||
544 | if (test_and_set_bit(__QLCNIC_DCB_IN_AEN, &adapter->state)) | ||
545 | return; | ||
546 | |||
547 | queue_delayed_work(dcb->wq, &dcb->aen_work, 0); | ||
548 | } | ||
549 | |||
550 | static int qlcnic_83xx_dcb_get_hw_capability(struct qlcnic_adapter *adapter) | ||
551 | { | ||
552 | struct qlcnic_dcb_capability *cap = &adapter->dcb->cfg->capability; | ||
553 | u32 mbx_out; | ||
554 | int err; | ||
555 | |||
556 | err = __qlcnic_dcb_get_capability(adapter, &mbx_out); | ||
557 | if (err) | ||
558 | return err; | ||
559 | |||
560 | if (mbx_out & BIT_2) | ||
561 | cap->dcb_capability = DCB_CAP_DCBX_VER_CEE; | ||
562 | if (mbx_out & BIT_3) | ||
563 | cap->dcb_capability |= DCB_CAP_DCBX_VER_IEEE; | ||
564 | if (cap->dcb_capability) | ||
565 | cap->dcb_capability |= DCB_CAP_DCBX_LLD_MANAGED; | ||
566 | |||
567 | if (cap->dcb_capability && cap->tsa_capability && cap->ets_capability) | ||
568 | set_bit(__QLCNIC_DCB_STATE, &adapter->state); | ||
569 | |||
570 | return err; | ||
571 | } | ||
572 | |||
573 | static int qlcnic_83xx_dcb_query_cee_param(struct qlcnic_adapter *adapter, | ||
574 | char *buf, u8 idx) | ||
575 | { | ||
576 | struct qlcnic_dcb_mbx_params mbx_out; | ||
577 | int err, i, j, k, max_app, size; | ||
578 | struct qlcnic_dcb_param *each; | ||
579 | struct qlcnic_cmd_args cmd; | ||
580 | u32 val; | ||
581 | char *p; | ||
582 | |||
583 | size = 0; | ||
584 | memset(&mbx_out, 0, sizeof(struct qlcnic_dcb_mbx_params)); | ||
585 | memset(buf, 0, sizeof(struct qlcnic_dcb_mbx_params)); | ||
586 | |||
587 | err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DCB_QUERY_PARAM); | ||
588 | if (err) | ||
589 | return err; | ||
590 | |||
591 | cmd.req.arg[0] |= QLC_DCB_FW_VER << 29; | ||
592 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
593 | if (err) { | ||
594 | dev_err(&adapter->pdev->dev, | ||
595 | "Failed to query DCBX param, err %d\n", err); | ||
596 | goto out; | ||
597 | } | ||
598 | |||
599 | mbx_out.prio_tc_map = cmd.rsp.arg[1]; | ||
600 | p = memcpy(buf, &mbx_out, sizeof(u32)); | ||
601 | k = 2; | ||
602 | p += sizeof(u32); | ||
603 | |||
604 | for (j = 0; j < QLC_DCB_NUM_PARAM; j++) { | ||
605 | each = &mbx_out.type[j]; | ||
606 | |||
607 | each->hdr_prio_pfc_map[0] = cmd.rsp.arg[k++]; | ||
608 | each->hdr_prio_pfc_map[1] = cmd.rsp.arg[k++]; | ||
609 | each->prio_pg_map[0] = cmd.rsp.arg[k++]; | ||
610 | each->prio_pg_map[1] = cmd.rsp.arg[k++]; | ||
611 | each->pg_bw_map[0] = cmd.rsp.arg[k++]; | ||
612 | each->pg_bw_map[1] = cmd.rsp.arg[k++]; | ||
613 | each->pg_tsa_map[0] = cmd.rsp.arg[k++]; | ||
614 | each->pg_tsa_map[1] = cmd.rsp.arg[k++]; | ||
615 | val = each->hdr_prio_pfc_map[0]; | ||
616 | |||
617 | max_app = qlcnic_dcb_get_num_app(adapter, val); | ||
618 | for (i = 0; i < max_app; i++) | ||
619 | each->app[i] = cmd.rsp.arg[i + k]; | ||
620 | |||
621 | size = 16 * sizeof(u32); | ||
622 | memcpy(p, &each->hdr_prio_pfc_map[0], size); | ||
623 | p += size; | ||
624 | if (j == 0) | ||
625 | k = 18; | ||
626 | else | ||
627 | k = 34; | ||
628 | } | ||
629 | out: | ||
630 | qlcnic_free_mbx_args(&cmd); | ||
631 | |||
632 | return err; | ||
633 | } | ||
634 | |||
635 | static int qlcnic_83xx_dcb_get_cee_cfg(struct qlcnic_adapter *adapter) | ||
636 | { | ||
637 | struct qlcnic_dcb *dcb = adapter->dcb; | ||
638 | int err; | ||
639 | |||
640 | err = qlcnic_dcb_query_cee_param(adapter, (char *)dcb->param, 0); | ||
641 | if (err) | ||
642 | return err; | ||
643 | |||
644 | qlcnic_dcb_data_cee_param_map(adapter); | ||
645 | |||
646 | return err; | ||
647 | } | ||
648 | |||
649 | static int qlcnic_83xx_dcb_register_aen(struct qlcnic_adapter *adapter, | ||
650 | bool flag) | ||
651 | { | ||
652 | u8 val = (flag ? QLCNIC_CMD_INIT_NIC_FUNC : QLCNIC_CMD_STOP_NIC_FUNC); | ||
653 | struct qlcnic_cmd_args cmd; | ||
654 | int err; | ||
655 | |||
656 | err = qlcnic_alloc_mbx_args(&cmd, adapter, val); | ||
657 | if (err) | ||
658 | return err; | ||
659 | |||
660 | cmd.req.arg[1] = QLC_DCB_AEN_BIT; | ||
661 | |||
662 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
663 | if (err) | ||
664 | dev_err(&adapter->pdev->dev, "Failed to %s DCBX AEN, err %d\n", | ||
665 | (flag ? "register" : "unregister"), err); | ||
666 | |||
667 | qlcnic_free_mbx_args(&cmd); | ||
668 | |||
669 | return err; | ||
670 | } | ||
671 | |||
672 | static void qlcnic_83xx_dcb_handle_aen(struct qlcnic_adapter *adapter, | ||
673 | void *data) | ||
674 | { | ||
675 | struct qlcnic_dcb *dcb = adapter->dcb; | ||
676 | u32 *val = data; | ||
677 | |||
678 | if (test_and_set_bit(__QLCNIC_DCB_IN_AEN, &adapter->state)) | ||
679 | return; | ||
680 | |||
681 | if (*val & BIT_8) | ||
682 | set_bit(__QLCNIC_DCB_STATE, &adapter->state); | ||
683 | else | ||
684 | clear_bit(__QLCNIC_DCB_STATE, &adapter->state); | ||
685 | |||
686 | queue_delayed_work(dcb->wq, &dcb->aen_work, 0); | ||
687 | } | ||
688 | |||
689 | static void qlcnic_dcb_fill_cee_tc_params(struct qlcnic_dcb_mbx_params *mbx, | ||
690 | struct qlcnic_dcb_param *each, | ||
691 | struct qlcnic_dcb_cee *type) | ||
692 | { | ||
693 | struct qlcnic_dcb_tc_cfg *tc_cfg; | ||
694 | u8 i, tc, pgid; | ||
695 | |||
696 | for (i = 0; i < QLC_DCB_MAX_PRIO; i++) { | ||
697 | tc = QLC_DCB_GET_TC_PRIO(mbx->prio_tc_map, i); | ||
698 | tc_cfg = &type->tc_cfg[tc]; | ||
699 | tc_cfg->valid = true; | ||
700 | tc_cfg->up_tc_map |= QLC_DCB_GET_MAP(i); | ||
701 | |||
702 | if (QLC_DCB_GET_PFC_PRIO(each->hdr_prio_pfc_map[1], i) && | ||
703 | type->pfc_mode_enable) { | ||
704 | tc_cfg->prio_cfg[i].valid = true; | ||
705 | tc_cfg->prio_cfg[i].pfc_type = QLC_PFC_FULL; | ||
706 | } | ||
707 | |||
708 | if (i < 4) | ||
709 | pgid = QLC_DCB_GET_PGID_PRIO(each->prio_pg_map[0], i); | ||
710 | else | ||
711 | pgid = QLC_DCB_GET_PGID_PRIO(each->prio_pg_map[1], i); | ||
712 | |||
713 | tc_cfg->pgid = pgid; | ||
714 | |||
715 | tc_cfg->prio_type = QLC_PRIO_LINK; | ||
716 | type->pg_cfg[tc_cfg->pgid].prio_count++; | ||
717 | } | ||
718 | } | ||
719 | |||
720 | static void qlcnic_dcb_fill_cee_pg_params(struct qlcnic_dcb_param *each, | ||
721 | struct qlcnic_dcb_cee *type) | ||
722 | { | ||
723 | struct qlcnic_dcb_pg_cfg *pg_cfg; | ||
724 | u8 i, tsa, bw_per; | ||
725 | |||
726 | for (i = 0; i < QLC_DCB_MAX_PG; i++) { | ||
727 | pg_cfg = &type->pg_cfg[i]; | ||
728 | pg_cfg->valid = true; | ||
729 | |||
730 | if (i < 4) { | ||
731 | bw_per = QLC_DCB_GET_BWPER_PG(each->pg_bw_map[0], i); | ||
732 | tsa = QLC_DCB_GET_TSA_PG(each->pg_tsa_map[0], i); | ||
733 | } else { | ||
734 | bw_per = QLC_DCB_GET_BWPER_PG(each->pg_bw_map[1], i); | ||
735 | tsa = QLC_DCB_GET_TSA_PG(each->pg_tsa_map[1], i); | ||
736 | } | ||
737 | |||
738 | pg_cfg->total_bw_percent = bw_per; | ||
739 | pg_cfg->tsa_type = tsa; | ||
740 | } | ||
741 | } | ||
742 | |||
743 | static void | ||
744 | qlcnic_dcb_fill_cee_app_params(struct qlcnic_adapter *adapter, u8 idx, | ||
745 | struct qlcnic_dcb_param *each, | ||
746 | struct qlcnic_dcb_cee *type) | ||
747 | { | ||
748 | struct qlcnic_dcb_app *app; | ||
749 | u8 i, num_app, map, cnt; | ||
750 | struct dcb_app new_app; | ||
751 | |||
752 | num_app = qlcnic_dcb_get_num_app(adapter, each->hdr_prio_pfc_map[0]); | ||
753 | for (i = 0; i < num_app; i++) { | ||
754 | app = &type->app[i]; | ||
755 | app->valid = true; | ||
756 | |||
757 | /* Only for CEE (-1) */ | ||
758 | app->selector = QLC_DCB_GET_SELECTOR_APP(each->app[i]) - 1; | ||
759 | new_app.selector = app->selector; | ||
760 | app->protocol = QLC_DCB_GET_PROTO_ID_APP(each->app[i]); | ||
761 | new_app.protocol = app->protocol; | ||
762 | map = qlcnic_dcb_get_prio_map_app(adapter, each->app[i]); | ||
763 | cnt = qlcnic_dcb_prio_count(map); | ||
764 | |||
765 | if (cnt >= QLC_DCB_MAX_TC) | ||
766 | cnt = 0; | ||
767 | |||
768 | app->priority = cnt; | ||
769 | new_app.priority = cnt; | ||
770 | |||
771 | if (idx == QLC_DCB_OPER_IDX && adapter->netdev->dcbnl_ops) | ||
772 | dcb_setapp(adapter->netdev, &new_app); | ||
773 | } | ||
774 | } | ||
775 | |||
776 | static void qlcnic_dcb_map_cee_params(struct qlcnic_adapter *adapter, u8 idx) | ||
777 | { | ||
778 | struct qlcnic_dcb_mbx_params *mbx = adapter->dcb->param; | ||
779 | struct qlcnic_dcb_param *each = &mbx->type[idx]; | ||
780 | struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg; | ||
781 | struct qlcnic_dcb_cee *type = &cfg->type[idx]; | ||
782 | |||
783 | type->tc_param_valid = false; | ||
784 | type->pfc_mode_enable = false; | ||
785 | memset(type->tc_cfg, 0, | ||
786 | sizeof(struct qlcnic_dcb_tc_cfg) * QLC_DCB_MAX_TC); | ||
787 | memset(type->pg_cfg, 0, | ||
788 | sizeof(struct qlcnic_dcb_pg_cfg) * QLC_DCB_MAX_TC); | ||
789 | |||
790 | if (qlcnic_dcb_pfc_hdr_valid(adapter, each->hdr_prio_pfc_map[0]) && | ||
791 | cfg->capability.max_pfc_tc) | ||
792 | type->pfc_mode_enable = true; | ||
793 | |||
794 | if (qlcnic_dcb_tsa_hdr_valid(adapter, each->hdr_prio_pfc_map[0]) && | ||
795 | cfg->capability.max_ets_tc) | ||
796 | type->tc_param_valid = true; | ||
797 | |||
798 | qlcnic_dcb_fill_cee_tc_params(mbx, each, type); | ||
799 | qlcnic_dcb_fill_cee_pg_params(each, type); | ||
800 | qlcnic_dcb_fill_cee_app_params(adapter, idx, each, type); | ||
801 | } | ||
802 | |||
803 | static void qlcnic_dcb_data_cee_param_map(struct qlcnic_adapter *adapter) | ||
804 | { | ||
805 | int i; | ||
806 | |||
807 | for (i = 0; i < QLC_DCB_NUM_PARAM; i++) | ||
808 | qlcnic_dcb_map_cee_params(adapter, i); | ||
809 | |||
810 | dcbnl_cee_notify(adapter->netdev, RTM_GETDCB, DCB_CMD_CEE_GET, 0, 0); | ||
811 | } | ||
812 | |||
813 | static u8 qlcnic_dcb_get_state(struct net_device *netdev) | ||
814 | { | ||
815 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
816 | |||
817 | return test_bit(__QLCNIC_DCB_STATE, &adapter->state); | ||
818 | } | ||
819 | |||
820 | static void qlcnic_dcb_get_perm_hw_addr(struct net_device *netdev, u8 *addr) | ||
821 | { | ||
822 | memcpy(addr, netdev->dev_addr, netdev->addr_len); | ||
823 | } | ||
824 | |||
825 | static void | ||
826 | qlcnic_dcb_get_pg_tc_cfg_tx(struct net_device *netdev, int tc, u8 *prio, | ||
827 | u8 *pgid, u8 *bw_per, u8 *up_tc_map) | ||
828 | { | ||
829 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
830 | struct qlcnic_dcb_tc_cfg *tc_cfg, *temp; | ||
831 | struct qlcnic_dcb_cee *type; | ||
832 | u8 i, cnt, pg; | ||
833 | |||
834 | type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX]; | ||
835 | *prio = *pgid = *bw_per = *up_tc_map = 0; | ||
836 | |||
837 | if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state) || | ||
838 | !type->tc_param_valid) | ||
839 | return; | ||
840 | |||
841 | if (tc < 0 || (tc > QLC_DCB_MAX_TC)) | ||
842 | return; | ||
843 | |||
844 | tc_cfg = &type->tc_cfg[tc]; | ||
845 | if (!tc_cfg->valid) | ||
846 | return; | ||
847 | |||
848 | *pgid = tc_cfg->pgid; | ||
849 | *prio = tc_cfg->prio_type; | ||
850 | *up_tc_map = tc_cfg->up_tc_map; | ||
851 | pg = *pgid; | ||
852 | |||
853 | for (i = 0, cnt = 0; i < QLC_DCB_MAX_TC; i++) { | ||
854 | temp = &type->tc_cfg[i]; | ||
855 | if (temp->valid && (pg == temp->pgid)) | ||
856 | cnt++; | ||
857 | } | ||
858 | |||
859 | tc_cfg->bwg_percent = (100 / cnt); | ||
860 | *bw_per = tc_cfg->bwg_percent; | ||
861 | } | ||
862 | |||
863 | static void qlcnic_dcb_get_pg_bwg_cfg_tx(struct net_device *netdev, int pgid, | ||
864 | u8 *bw_pct) | ||
865 | { | ||
866 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
867 | struct qlcnic_dcb_pg_cfg *pgcfg; | ||
868 | struct qlcnic_dcb_cee *type; | ||
869 | |||
870 | *bw_pct = 0; | ||
871 | type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX]; | ||
872 | |||
873 | if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state) || | ||
874 | !type->tc_param_valid) | ||
875 | return; | ||
876 | |||
877 | if (pgid < 0 || pgid > QLC_DCB_MAX_PG) | ||
878 | return; | ||
879 | |||
880 | pgcfg = &type->pg_cfg[pgid]; | ||
881 | if (!pgcfg->valid) | ||
882 | return; | ||
883 | |||
884 | *bw_pct = pgcfg->total_bw_percent; | ||
885 | } | ||
886 | |||
887 | static void qlcnic_dcb_get_pfc_cfg(struct net_device *netdev, int prio, | ||
888 | u8 *setting) | ||
889 | { | ||
890 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
891 | struct qlcnic_dcb_tc_cfg *tc_cfg; | ||
892 | u8 val = QLC_DCB_GET_MAP(prio); | ||
893 | struct qlcnic_dcb_cee *type; | ||
894 | u8 i; | ||
895 | |||
896 | *setting = 0; | ||
897 | type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX]; | ||
898 | |||
899 | if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state) || | ||
900 | !type->pfc_mode_enable) | ||
901 | return; | ||
902 | |||
903 | for (i = 0; i < QLC_DCB_MAX_TC; i++) { | ||
904 | tc_cfg = &type->tc_cfg[i]; | ||
905 | if (!tc_cfg->valid) | ||
906 | continue; | ||
907 | |||
908 | if ((val & tc_cfg->up_tc_map) && (tc_cfg->prio_cfg[prio].valid)) | ||
909 | *setting = tc_cfg->prio_cfg[prio].pfc_type; | ||
910 | } | ||
911 | } | ||
912 | |||
913 | static u8 qlcnic_dcb_get_capability(struct net_device *netdev, int capid, | ||
914 | u8 *cap) | ||
915 | { | ||
916 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
917 | |||
918 | if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state)) | ||
919 | return 0; | ||
920 | |||
921 | switch (capid) { | ||
922 | case DCB_CAP_ATTR_PG: | ||
923 | case DCB_CAP_ATTR_UP2TC: | ||
924 | case DCB_CAP_ATTR_PFC: | ||
925 | case DCB_CAP_ATTR_GSP: | ||
926 | *cap = true; | ||
927 | break; | ||
928 | case DCB_CAP_ATTR_PG_TCS: | ||
929 | case DCB_CAP_ATTR_PFC_TCS: | ||
930 | *cap = 0x80; /* 8 priorities for PGs */ | ||
931 | break; | ||
932 | case DCB_CAP_ATTR_DCBX: | ||
933 | *cap = adapter->dcb->cfg->capability.dcb_capability; | ||
934 | break; | ||
935 | default: | ||
936 | *cap = false; | ||
937 | } | ||
938 | |||
939 | return 0; | ||
940 | } | ||
941 | |||
942 | static int qlcnic_dcb_get_num_tcs(struct net_device *netdev, int attr, u8 *num) | ||
943 | { | ||
944 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
945 | struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg; | ||
946 | |||
947 | if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state)) | ||
948 | return -EINVAL; | ||
949 | |||
950 | switch (attr) { | ||
951 | case DCB_NUMTCS_ATTR_PG: | ||
952 | *num = cfg->capability.max_ets_tc; | ||
953 | return 0; | ||
954 | case DCB_NUMTCS_ATTR_PFC: | ||
955 | *num = cfg->capability.max_pfc_tc; | ||
956 | return 0; | ||
957 | default: | ||
958 | return -EINVAL; | ||
959 | } | ||
960 | } | ||
961 | |||
962 | static u8 qlcnic_dcb_get_app(struct net_device *netdev, u8 idtype, u16 id) | ||
963 | { | ||
964 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
965 | struct dcb_app app = { | ||
966 | .selector = idtype, | ||
967 | .protocol = id, | ||
968 | }; | ||
969 | |||
970 | if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state)) | ||
971 | return 0; | ||
972 | |||
973 | return dcb_getapp(netdev, &app); | ||
974 | } | ||
975 | |||
976 | static u8 qlcnic_dcb_get_pfc_state(struct net_device *netdev) | ||
977 | { | ||
978 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
979 | struct qlcnic_dcb *dcb = adapter->dcb; | ||
980 | |||
981 | if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state)) | ||
982 | return 0; | ||
983 | |||
984 | return dcb->cfg->type[QLC_DCB_OPER_IDX].pfc_mode_enable; | ||
985 | } | ||
986 | |||
987 | static u8 qlcnic_dcb_get_dcbx(struct net_device *netdev) | ||
988 | { | ||
989 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
990 | struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg; | ||
991 | |||
992 | if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state)) | ||
993 | return 0; | ||
994 | |||
995 | return cfg->capability.dcb_capability; | ||
996 | } | ||
997 | |||
998 | static u8 qlcnic_dcb_get_feat_cfg(struct net_device *netdev, int fid, u8 *flag) | ||
999 | { | ||
1000 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
1001 | struct qlcnic_dcb_cee *type; | ||
1002 | |||
1003 | if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state)) | ||
1004 | return 1; | ||
1005 | |||
1006 | type = &adapter->dcb->cfg->type[QLC_DCB_OPER_IDX]; | ||
1007 | *flag = 0; | ||
1008 | |||
1009 | switch (fid) { | ||
1010 | case DCB_FEATCFG_ATTR_PG: | ||
1011 | if (type->tc_param_valid) | ||
1012 | *flag |= DCB_FEATCFG_ENABLE; | ||
1013 | else | ||
1014 | *flag |= DCB_FEATCFG_ERROR; | ||
1015 | break; | ||
1016 | case DCB_FEATCFG_ATTR_PFC: | ||
1017 | if (type->pfc_mode_enable) { | ||
1018 | if (type->tc_cfg[0].prio_cfg[0].pfc_type) | ||
1019 | *flag |= DCB_FEATCFG_ENABLE; | ||
1020 | } else { | ||
1021 | *flag |= DCB_FEATCFG_ERROR; | ||
1022 | } | ||
1023 | break; | ||
1024 | case DCB_FEATCFG_ATTR_APP: | ||
1025 | *flag |= DCB_FEATCFG_ENABLE; | ||
1026 | break; | ||
1027 | default: | ||
1028 | netdev_err(netdev, "Invalid Feature ID %d\n", fid); | ||
1029 | return 1; | ||
1030 | } | ||
1031 | |||
1032 | return 0; | ||
1033 | } | ||
1034 | |||
1035 | static inline void | ||
1036 | qlcnic_dcb_get_pg_tc_cfg_rx(struct net_device *netdev, int prio, u8 *prio_type, | ||
1037 | u8 *pgid, u8 *bw_pct, u8 *up_map) | ||
1038 | { | ||
1039 | *prio_type = *pgid = *bw_pct = *up_map = 0; | ||
1040 | } | ||
1041 | |||
1042 | static inline void | ||
1043 | qlcnic_dcb_get_pg_bwg_cfg_rx(struct net_device *netdev, int pgid, u8 *bw_pct) | ||
1044 | { | ||
1045 | *bw_pct = 0; | ||
1046 | } | ||
1047 | |||
1048 | static int qlcnic_dcb_peer_app_info(struct net_device *netdev, | ||
1049 | struct dcb_peer_app_info *info, | ||
1050 | u16 *app_count) | ||
1051 | { | ||
1052 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
1053 | struct qlcnic_dcb_cee *peer; | ||
1054 | int i; | ||
1055 | |||
1056 | *app_count = 0; | ||
1057 | |||
1058 | if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state)) | ||
1059 | return 0; | ||
1060 | |||
1061 | peer = &adapter->dcb->cfg->type[QLC_DCB_PEER_IDX]; | ||
1062 | |||
1063 | for (i = 0; i < QLC_DCB_MAX_APP; i++) { | ||
1064 | if (peer->app[i].valid) | ||
1065 | (*app_count)++; | ||
1066 | } | ||
1067 | |||
1068 | return 0; | ||
1069 | } | ||
1070 | |||
1071 | static int qlcnic_dcb_peer_app_table(struct net_device *netdev, | ||
1072 | struct dcb_app *table) | ||
1073 | { | ||
1074 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
1075 | struct qlcnic_dcb_cee *peer; | ||
1076 | struct qlcnic_dcb_app *app; | ||
1077 | int i, j; | ||
1078 | |||
1079 | if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state)) | ||
1080 | return 0; | ||
1081 | |||
1082 | peer = &adapter->dcb->cfg->type[QLC_DCB_PEER_IDX]; | ||
1083 | |||
1084 | for (i = 0, j = 0; i < QLC_DCB_MAX_APP; i++) { | ||
1085 | app = &peer->app[i]; | ||
1086 | if (!app->valid) | ||
1087 | continue; | ||
1088 | |||
1089 | table[j].selector = app->selector; | ||
1090 | table[j].priority = app->priority; | ||
1091 | table[j++].protocol = app->protocol; | ||
1092 | } | ||
1093 | |||
1094 | return 0; | ||
1095 | } | ||
1096 | |||
1097 | static int qlcnic_dcb_cee_peer_get_pg(struct net_device *netdev, | ||
1098 | struct cee_pg *pg) | ||
1099 | { | ||
1100 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
1101 | struct qlcnic_dcb_cee *peer; | ||
1102 | u8 i, j, k, map; | ||
1103 | |||
1104 | if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state)) | ||
1105 | return 0; | ||
1106 | |||
1107 | peer = &adapter->dcb->cfg->type[QLC_DCB_PEER_IDX]; | ||
1108 | |||
1109 | for (i = 0, j = 0; i < QLC_DCB_MAX_PG; i++) { | ||
1110 | if (!peer->pg_cfg[i].valid) | ||
1111 | continue; | ||
1112 | |||
1113 | pg->pg_bw[j] = peer->pg_cfg[i].total_bw_percent; | ||
1114 | |||
1115 | for (k = 0; k < QLC_DCB_MAX_TC; k++) { | ||
1116 | if (peer->tc_cfg[i].valid && | ||
1117 | (peer->tc_cfg[i].pgid == i)) { | ||
1118 | map = peer->tc_cfg[i].up_tc_map; | ||
1119 | pg->prio_pg[j++] = map; | ||
1120 | break; | ||
1121 | } | ||
1122 | } | ||
1123 | } | ||
1124 | |||
1125 | return 0; | ||
1126 | } | ||
1127 | |||
1128 | static int qlcnic_dcb_cee_peer_get_pfc(struct net_device *netdev, | ||
1129 | struct cee_pfc *pfc) | ||
1130 | { | ||
1131 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
1132 | struct qlcnic_dcb_cfg *cfg = adapter->dcb->cfg; | ||
1133 | struct qlcnic_dcb_tc_cfg *tc; | ||
1134 | struct qlcnic_dcb_cee *peer; | ||
1135 | u8 i, setting, prio; | ||
1136 | |||
1137 | pfc->pfc_en = 0; | ||
1138 | |||
1139 | if (!test_bit(__QLCNIC_DCB_STATE, &adapter->state)) | ||
1140 | return 0; | ||
1141 | |||
1142 | peer = &cfg->type[QLC_DCB_PEER_IDX]; | ||
1143 | |||
1144 | for (i = 0; i < QLC_DCB_MAX_TC; i++) { | ||
1145 | tc = &peer->tc_cfg[i]; | ||
1146 | prio = qlcnic_dcb_prio_count(tc->up_tc_map); | ||
1147 | |||
1148 | setting = 0; | ||
1149 | qlcnic_dcb_get_pfc_cfg(netdev, prio, &setting); | ||
1150 | if (setting) | ||
1151 | pfc->pfc_en |= QLC_DCB_GET_MAP(i); | ||
1152 | } | ||
1153 | |||
1154 | pfc->tcs_supported = cfg->capability.max_pfc_tc; | ||
1155 | |||
1156 | return 0; | ||
1157 | } | ||
1158 | |||
1159 | static const struct dcbnl_rtnl_ops qlcnic_dcbnl_ops = { | ||
1160 | .getstate = qlcnic_dcb_get_state, | ||
1161 | .getpermhwaddr = qlcnic_dcb_get_perm_hw_addr, | ||
1162 | .getpgtccfgtx = qlcnic_dcb_get_pg_tc_cfg_tx, | ||
1163 | .getpgbwgcfgtx = qlcnic_dcb_get_pg_bwg_cfg_tx, | ||
1164 | .getpfccfg = qlcnic_dcb_get_pfc_cfg, | ||
1165 | .getcap = qlcnic_dcb_get_capability, | ||
1166 | .getnumtcs = qlcnic_dcb_get_num_tcs, | ||
1167 | .getapp = qlcnic_dcb_get_app, | ||
1168 | .getpfcstate = qlcnic_dcb_get_pfc_state, | ||
1169 | .getdcbx = qlcnic_dcb_get_dcbx, | ||
1170 | .getfeatcfg = qlcnic_dcb_get_feat_cfg, | ||
1171 | |||
1172 | .getpgtccfgrx = qlcnic_dcb_get_pg_tc_cfg_rx, | ||
1173 | .getpgbwgcfgrx = qlcnic_dcb_get_pg_bwg_cfg_rx, | ||
1174 | |||
1175 | .peer_getappinfo = qlcnic_dcb_peer_app_info, | ||
1176 | .peer_getapptable = qlcnic_dcb_peer_app_table, | ||
1177 | .cee_peer_getpg = qlcnic_dcb_cee_peer_get_pg, | ||
1178 | .cee_peer_getpfc = qlcnic_dcb_cee_peer_get_pfc, | ||
1179 | }; | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h new file mode 100644 index 000000000000..b87ce9fb503e --- /dev/null +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * QLogic qlcnic NIC Driver | ||
3 | * Copyright (c) 2009-2013 QLogic Corporation | ||
4 | * | ||
5 | * See LICENSE.qlcnic for copyright and licensing details. | ||
6 | */ | ||
7 | |||
8 | #ifndef __QLCNIC_DCBX_H | ||
9 | #define __QLCNIC_DCBX_H | ||
10 | |||
11 | void qlcnic_clear_dcb_ops(struct qlcnic_adapter *); | ||
12 | |||
13 | #ifdef CONFIG_QLCNIC_DCB | ||
14 | int __qlcnic_register_dcb(struct qlcnic_adapter *); | ||
15 | #else | ||
16 | static inline int __qlcnic_register_dcb(struct qlcnic_adapter *adapter) | ||
17 | { return 0; } | ||
18 | #endif | ||
19 | |||
20 | struct qlcnic_dcb_ops { | ||
21 | void (*init_dcbnl_ops) (struct qlcnic_adapter *); | ||
22 | void (*free) (struct qlcnic_adapter *); | ||
23 | int (*attach) (struct qlcnic_adapter *); | ||
24 | int (*query_hw_capability) (struct qlcnic_adapter *, char *); | ||
25 | int (*get_hw_capability) (struct qlcnic_adapter *); | ||
26 | void (*get_info) (struct qlcnic_adapter *); | ||
27 | int (*query_cee_param) (struct qlcnic_adapter *, char *, u8); | ||
28 | int (*get_cee_cfg) (struct qlcnic_adapter *); | ||
29 | int (*register_aen) (struct qlcnic_adapter *, bool); | ||
30 | void (*handle_aen) (struct qlcnic_adapter *, void *); | ||
31 | }; | ||
32 | |||
33 | struct qlcnic_dcb { | ||
34 | struct qlcnic_dcb_mbx_params *param; | ||
35 | struct qlcnic_adapter *adapter; | ||
36 | struct delayed_work aen_work; | ||
37 | struct workqueue_struct *wq; | ||
38 | struct qlcnic_dcb_ops *ops; | ||
39 | struct qlcnic_dcb_cfg *cfg; | ||
40 | }; | ||
41 | #endif | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c index 7aac23ab31d1..4d7ad0074d1c 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | |||
@@ -125,6 +125,14 @@ static const char qlcnic_83xx_mac_stats_strings[][ETH_GSTRING_LEN] = { | |||
125 | }; | 125 | }; |
126 | 126 | ||
127 | #define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats) | 127 | #define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats) |
128 | |||
129 | static const char qlcnic_tx_ring_stats_strings[][ETH_GSTRING_LEN] = { | ||
130 | "xmit_on", | ||
131 | "xmit_off", | ||
132 | "xmit_called", | ||
133 | "xmit_finished", | ||
134 | }; | ||
135 | |||
128 | static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = { | 136 | static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = { |
129 | "ctx_rx_bytes", | 137 | "ctx_rx_bytes", |
130 | "ctx_rx_pkts", | 138 | "ctx_rx_pkts", |
@@ -630,15 +638,15 @@ qlcnic_set_ringparam(struct net_device *dev, | |||
630 | static void qlcnic_get_channels(struct net_device *dev, | 638 | static void qlcnic_get_channels(struct net_device *dev, |
631 | struct ethtool_channels *channel) | 639 | struct ethtool_channels *channel) |
632 | { | 640 | { |
633 | int min; | ||
634 | struct qlcnic_adapter *adapter = netdev_priv(dev); | 641 | struct qlcnic_adapter *adapter = netdev_priv(dev); |
642 | int min; | ||
635 | 643 | ||
636 | min = min_t(int, adapter->ahw->max_rx_ques, num_online_cpus()); | 644 | min = min_t(int, adapter->ahw->max_rx_ques, num_online_cpus()); |
637 | channel->max_rx = rounddown_pow_of_two(min); | 645 | channel->max_rx = rounddown_pow_of_two(min); |
638 | channel->max_tx = adapter->ahw->max_tx_ques; | 646 | channel->max_tx = min_t(int, QLCNIC_MAX_TX_RINGS, num_online_cpus()); |
639 | 647 | ||
640 | channel->rx_count = adapter->max_sds_rings; | 648 | channel->rx_count = adapter->max_sds_rings; |
641 | channel->tx_count = adapter->ahw->max_tx_ques; | 649 | channel->tx_count = adapter->max_drv_tx_rings; |
642 | } | 650 | } |
643 | 651 | ||
644 | static int qlcnic_set_channels(struct net_device *dev, | 652 | static int qlcnic_set_channels(struct net_device *dev, |
@@ -646,18 +654,27 @@ static int qlcnic_set_channels(struct net_device *dev, | |||
646 | { | 654 | { |
647 | struct qlcnic_adapter *adapter = netdev_priv(dev); | 655 | struct qlcnic_adapter *adapter = netdev_priv(dev); |
648 | int err; | 656 | int err; |
657 | int txq = 0; | ||
649 | 658 | ||
650 | if (channel->other_count || channel->combined_count || | 659 | if (channel->other_count || channel->combined_count) |
651 | channel->tx_count != channel->max_tx) | ||
652 | return -EINVAL; | 660 | return -EINVAL; |
653 | 661 | ||
654 | err = qlcnic_validate_max_rss(adapter, channel->rx_count); | 662 | if (channel->rx_count) { |
655 | if (err) | 663 | err = qlcnic_validate_max_rss(adapter, channel->rx_count); |
656 | return err; | 664 | if (err) |
665 | return err; | ||
666 | } | ||
667 | |||
668 | if (channel->tx_count) { | ||
669 | err = qlcnic_validate_max_tx_rings(adapter, channel->tx_count); | ||
670 | if (err) | ||
671 | return err; | ||
672 | txq = channel->tx_count; | ||
673 | } | ||
657 | 674 | ||
658 | err = qlcnic_set_max_rss(adapter, channel->rx_count, 0); | 675 | err = qlcnic_set_max_rss(adapter, channel->rx_count, txq); |
659 | netdev_info(dev, "allocated 0x%x sds rings\n", | 676 | netdev_info(dev, "allocated 0x%x sds rings and 0x%x tx rings\n", |
660 | adapter->max_sds_rings); | 677 | adapter->max_sds_rings, adapter->max_drv_tx_rings); |
661 | return err; | 678 | return err; |
662 | } | 679 | } |
663 | 680 | ||
@@ -893,6 +910,7 @@ free_diag_res: | |||
893 | clear_diag_irq: | 910 | clear_diag_irq: |
894 | adapter->max_sds_rings = max_sds_rings; | 911 | adapter->max_sds_rings = max_sds_rings; |
895 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 912 | clear_bit(__QLCNIC_RESETTING, &adapter->state); |
913 | |||
896 | return ret; | 914 | return ret; |
897 | } | 915 | } |
898 | 916 | ||
@@ -966,6 +984,7 @@ int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode) | |||
966 | int qlcnic_loopback_test(struct net_device *netdev, u8 mode) | 984 | int qlcnic_loopback_test(struct net_device *netdev, u8 mode) |
967 | { | 985 | { |
968 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 986 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
987 | int max_drv_tx_rings = adapter->max_drv_tx_rings; | ||
969 | int max_sds_rings = adapter->max_sds_rings; | 988 | int max_sds_rings = adapter->max_sds_rings; |
970 | struct qlcnic_host_sds_ring *sds_ring; | 989 | struct qlcnic_host_sds_ring *sds_ring; |
971 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 990 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
@@ -1006,9 +1025,9 @@ int qlcnic_loopback_test(struct net_device *netdev, u8 mode) | |||
1006 | msleep(500); | 1025 | msleep(500); |
1007 | qlcnic_process_rcv_ring_diag(sds_ring); | 1026 | qlcnic_process_rcv_ring_diag(sds_ring); |
1008 | if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) { | 1027 | if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) { |
1009 | netdev_info(netdev, "firmware didnt respond to loopback" | 1028 | netdev_info(netdev, |
1010 | " configure request\n"); | 1029 | "Firmware didn't sent link up event to loopback request\n"); |
1011 | ret = -QLCNIC_FW_NOT_RESPOND; | 1030 | ret = -ETIMEDOUT; |
1012 | goto free_res; | 1031 | goto free_res; |
1013 | } else if (adapter->ahw->diag_cnt) { | 1032 | } else if (adapter->ahw->diag_cnt) { |
1014 | ret = adapter->ahw->diag_cnt; | 1033 | ret = adapter->ahw->diag_cnt; |
@@ -1025,6 +1044,7 @@ int qlcnic_loopback_test(struct net_device *netdev, u8 mode) | |||
1025 | 1044 | ||
1026 | clear_it: | 1045 | clear_it: |
1027 | adapter->max_sds_rings = max_sds_rings; | 1046 | adapter->max_sds_rings = max_sds_rings; |
1047 | adapter->max_drv_tx_rings = max_drv_tx_rings; | ||
1028 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 1048 | clear_bit(__QLCNIC_RESETTING, &adapter->state); |
1029 | return ret; | 1049 | return ret; |
1030 | } | 1050 | } |
@@ -1077,11 +1097,21 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data) | |||
1077 | QLCNIC_TEST_LEN * ETH_GSTRING_LEN); | 1097 | QLCNIC_TEST_LEN * ETH_GSTRING_LEN); |
1078 | break; | 1098 | break; |
1079 | case ETH_SS_STATS: | 1099 | case ETH_SS_STATS: |
1100 | num_stats = ARRAY_SIZE(qlcnic_tx_ring_stats_strings); | ||
1101 | for (i = 0; i < adapter->max_drv_tx_rings; i++) { | ||
1102 | for (index = 0; index < num_stats; index++) { | ||
1103 | sprintf(data, "tx_ring_%d %s", i, | ||
1104 | qlcnic_tx_ring_stats_strings[index]); | ||
1105 | data += ETH_GSTRING_LEN; | ||
1106 | } | ||
1107 | } | ||
1108 | |||
1080 | for (index = 0; index < QLCNIC_STATS_LEN; index++) { | 1109 | for (index = 0; index < QLCNIC_STATS_LEN; index++) { |
1081 | memcpy(data + index * ETH_GSTRING_LEN, | 1110 | memcpy(data + index * ETH_GSTRING_LEN, |
1082 | qlcnic_gstrings_stats[index].stat_string, | 1111 | qlcnic_gstrings_stats[index].stat_string, |
1083 | ETH_GSTRING_LEN); | 1112 | ETH_GSTRING_LEN); |
1084 | } | 1113 | } |
1114 | |||
1085 | if (qlcnic_83xx_check(adapter)) { | 1115 | if (qlcnic_83xx_check(adapter)) { |
1086 | num_stats = ARRAY_SIZE(qlcnic_83xx_tx_stats_strings); | 1116 | num_stats = ARRAY_SIZE(qlcnic_83xx_tx_stats_strings); |
1087 | for (i = 0; i < num_stats; i++, index++) | 1117 | for (i = 0; i < num_stats; i++, index++) |
@@ -1173,11 +1203,22 @@ static void qlcnic_get_ethtool_stats(struct net_device *dev, | |||
1173 | struct ethtool_stats *stats, u64 *data) | 1203 | struct ethtool_stats *stats, u64 *data) |
1174 | { | 1204 | { |
1175 | struct qlcnic_adapter *adapter = netdev_priv(dev); | 1205 | struct qlcnic_adapter *adapter = netdev_priv(dev); |
1206 | struct qlcnic_host_tx_ring *tx_ring; | ||
1176 | struct qlcnic_esw_statistics port_stats; | 1207 | struct qlcnic_esw_statistics port_stats; |
1177 | struct qlcnic_mac_statistics mac_stats; | 1208 | struct qlcnic_mac_statistics mac_stats; |
1178 | int index, ret, length, size; | 1209 | int index, ret, length, size, ring; |
1179 | char *p; | 1210 | char *p; |
1180 | 1211 | ||
1212 | memset(data, 0, adapter->max_drv_tx_rings * 4 * sizeof(u64)); | ||
1213 | for (ring = 0, index = 0; ring < adapter->max_drv_tx_rings; ring++) { | ||
1214 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) { | ||
1215 | tx_ring = &adapter->tx_ring[ring]; | ||
1216 | *data++ = tx_ring->xmit_on; | ||
1217 | *data++ = tx_ring->xmit_off; | ||
1218 | *data++ = tx_ring->xmit_called; | ||
1219 | *data++ = tx_ring->xmit_finished; | ||
1220 | } | ||
1221 | } | ||
1181 | memset(data, 0, stats->n_stats * sizeof(u64)); | 1222 | memset(data, 0, stats->n_stats * sizeof(u64)); |
1182 | length = QLCNIC_STATS_LEN; | 1223 | length = QLCNIC_STATS_LEN; |
1183 | for (index = 0; index < length; index++) { | 1224 | for (index = 0; index < length; index++) { |
@@ -1468,6 +1509,68 @@ static void qlcnic_set_msglevel(struct net_device *netdev, u32 msglvl) | |||
1468 | adapter->ahw->msg_enable = msglvl; | 1509 | adapter->ahw->msg_enable = msglvl; |
1469 | } | 1510 | } |
1470 | 1511 | ||
1512 | int qlcnic_enable_fw_dump_state(struct qlcnic_adapter *adapter) | ||
1513 | { | ||
1514 | struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; | ||
1515 | u32 val; | ||
1516 | |||
1517 | if (qlcnic_84xx_check(adapter)) { | ||
1518 | if (qlcnic_83xx_lock_driver(adapter)) | ||
1519 | return -EBUSY; | ||
1520 | |||
1521 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); | ||
1522 | val &= ~QLC_83XX_IDC_DISABLE_FW_DUMP; | ||
1523 | QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val); | ||
1524 | |||
1525 | qlcnic_83xx_unlock_driver(adapter); | ||
1526 | } else { | ||
1527 | fw_dump->enable = true; | ||
1528 | } | ||
1529 | |||
1530 | dev_info(&adapter->pdev->dev, "FW dump enabled\n"); | ||
1531 | |||
1532 | return 0; | ||
1533 | } | ||
1534 | |||
1535 | static int qlcnic_disable_fw_dump_state(struct qlcnic_adapter *adapter) | ||
1536 | { | ||
1537 | struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; | ||
1538 | u32 val; | ||
1539 | |||
1540 | if (qlcnic_84xx_check(adapter)) { | ||
1541 | if (qlcnic_83xx_lock_driver(adapter)) | ||
1542 | return -EBUSY; | ||
1543 | |||
1544 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); | ||
1545 | val |= QLC_83XX_IDC_DISABLE_FW_DUMP; | ||
1546 | QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val); | ||
1547 | |||
1548 | qlcnic_83xx_unlock_driver(adapter); | ||
1549 | } else { | ||
1550 | fw_dump->enable = false; | ||
1551 | } | ||
1552 | |||
1553 | dev_info(&adapter->pdev->dev, "FW dump disabled\n"); | ||
1554 | |||
1555 | return 0; | ||
1556 | } | ||
1557 | |||
1558 | bool qlcnic_check_fw_dump_state(struct qlcnic_adapter *adapter) | ||
1559 | { | ||
1560 | struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; | ||
1561 | bool state; | ||
1562 | u32 val; | ||
1563 | |||
1564 | if (qlcnic_84xx_check(adapter)) { | ||
1565 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); | ||
1566 | state = (val & QLC_83XX_IDC_DISABLE_FW_DUMP) ? false : true; | ||
1567 | } else { | ||
1568 | state = fw_dump->enable; | ||
1569 | } | ||
1570 | |||
1571 | return state; | ||
1572 | } | ||
1573 | |||
1471 | static int | 1574 | static int |
1472 | qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) | 1575 | qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) |
1473 | { | 1576 | { |
@@ -1484,7 +1587,7 @@ qlcnic_get_dump_flag(struct net_device *netdev, struct ethtool_dump *dump) | |||
1484 | else | 1587 | else |
1485 | dump->len = 0; | 1588 | dump->len = 0; |
1486 | 1589 | ||
1487 | if (!fw_dump->enable) | 1590 | if (!qlcnic_check_fw_dump_state(adapter)) |
1488 | dump->flag = ETH_FW_DUMP_DISABLE; | 1591 | dump->flag = ETH_FW_DUMP_DISABLE; |
1489 | else | 1592 | else |
1490 | dump->flag = fw_dump->tmpl_hdr->drv_cap_mask; | 1593 | dump->flag = fw_dump->tmpl_hdr->drv_cap_mask; |
@@ -1532,77 +1635,111 @@ qlcnic_get_dump_data(struct net_device *netdev, struct ethtool_dump *dump, | |||
1532 | return 0; | 1635 | return 0; |
1533 | } | 1636 | } |
1534 | 1637 | ||
1638 | static int qlcnic_set_dump_mask(struct qlcnic_adapter *adapter, u32 mask) | ||
1639 | { | ||
1640 | struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; | ||
1641 | struct net_device *netdev = adapter->netdev; | ||
1642 | |||
1643 | if (!qlcnic_check_fw_dump_state(adapter)) { | ||
1644 | netdev_info(netdev, | ||
1645 | "Can not change driver mask to 0x%x. FW dump not enabled\n", | ||
1646 | mask); | ||
1647 | return -EOPNOTSUPP; | ||
1648 | } | ||
1649 | |||
1650 | fw_dump->tmpl_hdr->drv_cap_mask = mask; | ||
1651 | netdev_info(netdev, "Driver mask changed to: 0x%x\n", mask); | ||
1652 | return 0; | ||
1653 | } | ||
1654 | |||
1535 | static int | 1655 | static int |
1536 | qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) | 1656 | qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) |
1537 | { | 1657 | { |
1538 | int i; | ||
1539 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 1658 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
1540 | struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; | 1659 | struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; |
1660 | bool valid_mask = false; | ||
1661 | int i, ret = 0; | ||
1541 | u32 state; | 1662 | u32 state; |
1542 | 1663 | ||
1543 | switch (val->flag) { | 1664 | switch (val->flag) { |
1544 | case QLCNIC_FORCE_FW_DUMP_KEY: | 1665 | case QLCNIC_FORCE_FW_DUMP_KEY: |
1545 | if (!fw_dump->tmpl_hdr) { | 1666 | if (!fw_dump->tmpl_hdr) { |
1546 | netdev_err(netdev, "FW dump not supported\n"); | 1667 | netdev_err(netdev, "FW dump not supported\n"); |
1547 | return -ENOTSUPP; | 1668 | ret = -EOPNOTSUPP; |
1669 | break; | ||
1548 | } | 1670 | } |
1549 | if (!fw_dump->enable) { | 1671 | |
1672 | if (!qlcnic_check_fw_dump_state(adapter)) { | ||
1550 | netdev_info(netdev, "FW dump not enabled\n"); | 1673 | netdev_info(netdev, "FW dump not enabled\n"); |
1551 | return 0; | 1674 | ret = -EOPNOTSUPP; |
1675 | break; | ||
1552 | } | 1676 | } |
1677 | |||
1553 | if (fw_dump->clr) { | 1678 | if (fw_dump->clr) { |
1554 | netdev_info(netdev, | 1679 | netdev_info(netdev, |
1555 | "Previous dump not cleared, not forcing dump\n"); | 1680 | "Previous dump not cleared, not forcing dump\n"); |
1556 | return 0; | 1681 | break; |
1557 | } | 1682 | } |
1683 | |||
1558 | netdev_info(netdev, "Forcing a FW dump\n"); | 1684 | netdev_info(netdev, "Forcing a FW dump\n"); |
1559 | qlcnic_dev_request_reset(adapter, val->flag); | 1685 | qlcnic_dev_request_reset(adapter, val->flag); |
1560 | break; | 1686 | break; |
1561 | case QLCNIC_DISABLE_FW_DUMP: | 1687 | case QLCNIC_DISABLE_FW_DUMP: |
1562 | if (fw_dump->enable && fw_dump->tmpl_hdr) { | 1688 | if (!fw_dump->tmpl_hdr) { |
1563 | netdev_info(netdev, "Disabling FW dump\n"); | 1689 | netdev_err(netdev, "FW dump not supported\n"); |
1564 | fw_dump->enable = 0; | 1690 | ret = -EOPNOTSUPP; |
1691 | break; | ||
1565 | } | 1692 | } |
1566 | return 0; | 1693 | |
1694 | ret = qlcnic_disable_fw_dump_state(adapter); | ||
1695 | break; | ||
1696 | |||
1567 | case QLCNIC_ENABLE_FW_DUMP: | 1697 | case QLCNIC_ENABLE_FW_DUMP: |
1568 | if (!fw_dump->tmpl_hdr) { | 1698 | if (!fw_dump->tmpl_hdr) { |
1569 | netdev_err(netdev, "FW dump not supported\n"); | 1699 | netdev_err(netdev, "FW dump not supported\n"); |
1570 | return -ENOTSUPP; | 1700 | ret = -EOPNOTSUPP; |
1571 | } | 1701 | break; |
1572 | if (!fw_dump->enable) { | ||
1573 | netdev_info(netdev, "Enabling FW dump\n"); | ||
1574 | fw_dump->enable = 1; | ||
1575 | } | 1702 | } |
1576 | return 0; | 1703 | |
1704 | ret = qlcnic_enable_fw_dump_state(adapter); | ||
1705 | break; | ||
1706 | |||
1577 | case QLCNIC_FORCE_FW_RESET: | 1707 | case QLCNIC_FORCE_FW_RESET: |
1578 | netdev_info(netdev, "Forcing a FW reset\n"); | 1708 | netdev_info(netdev, "Forcing a FW reset\n"); |
1579 | qlcnic_dev_request_reset(adapter, val->flag); | 1709 | qlcnic_dev_request_reset(adapter, val->flag); |
1580 | adapter->flags &= ~QLCNIC_FW_RESET_OWNER; | 1710 | adapter->flags &= ~QLCNIC_FW_RESET_OWNER; |
1581 | return 0; | 1711 | break; |
1712 | |||
1582 | case QLCNIC_SET_QUIESCENT: | 1713 | case QLCNIC_SET_QUIESCENT: |
1583 | case QLCNIC_RESET_QUIESCENT: | 1714 | case QLCNIC_RESET_QUIESCENT: |
1584 | state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); | 1715 | state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); |
1585 | if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) | 1716 | if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) |
1586 | netdev_info(netdev, "Device in FAILED state\n"); | 1717 | netdev_info(netdev, "Device in FAILED state\n"); |
1587 | return 0; | 1718 | break; |
1719 | |||
1588 | default: | 1720 | default: |
1589 | if (!fw_dump->tmpl_hdr) { | 1721 | if (!fw_dump->tmpl_hdr) { |
1590 | netdev_err(netdev, "FW dump not supported\n"); | 1722 | netdev_err(netdev, "FW dump not supported\n"); |
1591 | return -ENOTSUPP; | 1723 | ret = -EOPNOTSUPP; |
1724 | break; | ||
1592 | } | 1725 | } |
1726 | |||
1593 | for (i = 0; i < ARRAY_SIZE(qlcnic_fw_dump_level); i++) { | 1727 | for (i = 0; i < ARRAY_SIZE(qlcnic_fw_dump_level); i++) { |
1594 | if (val->flag == qlcnic_fw_dump_level[i]) { | 1728 | if (val->flag == qlcnic_fw_dump_level[i]) { |
1595 | fw_dump->tmpl_hdr->drv_cap_mask = | 1729 | valid_mask = true; |
1596 | val->flag; | 1730 | break; |
1597 | netdev_info(netdev, "Driver mask changed to: 0x%x\n", | ||
1598 | fw_dump->tmpl_hdr->drv_cap_mask); | ||
1599 | return 0; | ||
1600 | } | 1731 | } |
1601 | } | 1732 | } |
1602 | netdev_info(netdev, "Invalid dump level: 0x%x\n", val->flag); | 1733 | |
1603 | return -EINVAL; | 1734 | if (valid_mask) { |
1735 | ret = qlcnic_set_dump_mask(adapter, val->flag); | ||
1736 | } else { | ||
1737 | netdev_info(netdev, "Invalid dump level: 0x%x\n", | ||
1738 | val->flag); | ||
1739 | ret = -EINVAL; | ||
1740 | } | ||
1604 | } | 1741 | } |
1605 | return 0; | 1742 | return ret; |
1606 | } | 1743 | } |
1607 | 1744 | ||
1608 | const struct ethtool_ops qlcnic_ethtool_ops = { | 1745 | const struct ethtool_ops qlcnic_ethtool_ops = { |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index 4d5f59b2d153..f8adc7b01f1f 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | |||
@@ -387,7 +387,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter, | |||
387 | if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) | 387 | if (!test_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) |
388 | return -EIO; | 388 | return -EIO; |
389 | 389 | ||
390 | tx_ring = adapter->tx_ring; | 390 | tx_ring = &adapter->tx_ring[0]; |
391 | __netif_tx_lock_bh(tx_ring->txq); | 391 | __netif_tx_lock_bh(tx_ring->txq); |
392 | 392 | ||
393 | producer = tx_ring->producer; | 393 | producer = tx_ring->producer; |
@@ -740,6 +740,22 @@ int qlcnic_82xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode) | |||
740 | return 0; | 740 | return 0; |
741 | } | 741 | } |
742 | 742 | ||
743 | int qlcnic_82xx_read_phys_port_id(struct qlcnic_adapter *adapter) | ||
744 | { | ||
745 | u8 mac[ETH_ALEN]; | ||
746 | int ret; | ||
747 | |||
748 | ret = qlcnic_get_mac_address(adapter, mac, | ||
749 | adapter->ahw->physical_port); | ||
750 | if (ret) | ||
751 | return ret; | ||
752 | |||
753 | memcpy(adapter->ahw->phys_port_id, mac, ETH_ALEN); | ||
754 | adapter->flags |= QLCNIC_HAS_PHYS_PORT_ID; | ||
755 | |||
756 | return 0; | ||
757 | } | ||
758 | |||
743 | /* | 759 | /* |
744 | * Send the interrupt coalescing parameter set by ethtool to the card. | 760 | * Send the interrupt coalescing parameter set by ethtool to the card. |
745 | */ | 761 | */ |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h index 4a71b28effcb..272c356cf9b2 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h | |||
@@ -85,8 +85,11 @@ enum qlcnic_regs { | |||
85 | #define QLCNIC_CMD_GET_TEMP_HDR 0x30 | 85 | #define QLCNIC_CMD_GET_TEMP_HDR 0x30 |
86 | #define QLCNIC_CMD_BC_EVENT_SETUP 0x31 | 86 | #define QLCNIC_CMD_BC_EVENT_SETUP 0x31 |
87 | #define QLCNIC_CMD_CONFIG_VPORT 0x32 | 87 | #define QLCNIC_CMD_CONFIG_VPORT 0x32 |
88 | #define QLCNIC_CMD_DCB_QUERY_CAP 0x34 | ||
89 | #define QLCNIC_CMD_DCB_QUERY_PARAM 0x35 | ||
88 | #define QLCNIC_CMD_GET_MAC_STATS 0x37 | 90 | #define QLCNIC_CMD_GET_MAC_STATS 0x37 |
89 | #define QLCNIC_CMD_82XX_SET_DRV_VER 0x38 | 91 | #define QLCNIC_CMD_82XX_SET_DRV_VER 0x38 |
92 | #define QLCNIC_CMD_MQ_TX_CONFIG_INTR 0x39 | ||
90 | #define QLCNIC_CMD_GET_LED_STATUS 0x3C | 93 | #define QLCNIC_CMD_GET_LED_STATUS 0x3C |
91 | #define QLCNIC_CMD_CONFIGURE_RSS 0x41 | 94 | #define QLCNIC_CMD_CONFIGURE_RSS 0x41 |
92 | #define QLCNIC_CMD_CONFIG_INTR_COAL 0x43 | 95 | #define QLCNIC_CMD_CONFIG_INTR_COAL 0x43 |
@@ -122,6 +125,7 @@ enum qlcnic_regs { | |||
122 | #define QLCNIC_MBX_COMP_EVENT 0x8100 | 125 | #define QLCNIC_MBX_COMP_EVENT 0x8100 |
123 | #define QLCNIC_MBX_REQUEST_EVENT 0x8101 | 126 | #define QLCNIC_MBX_REQUEST_EVENT 0x8101 |
124 | #define QLCNIC_MBX_TIME_EXTEND_EVENT 0x8102 | 127 | #define QLCNIC_MBX_TIME_EXTEND_EVENT 0x8102 |
128 | #define QLCNIC_MBX_DCBX_CONFIG_CHANGE_EVENT 0x8110 | ||
125 | #define QLCNIC_MBX_SFP_INSERT_EVENT 0x8130 | 129 | #define QLCNIC_MBX_SFP_INSERT_EVENT 0x8130 |
126 | #define QLCNIC_MBX_SFP_REMOVE_EVENT 0x8131 | 130 | #define QLCNIC_MBX_SFP_REMOVE_EVENT 0x8131 |
127 | 131 | ||
@@ -149,7 +153,6 @@ struct ethtool_stats; | |||
149 | struct pci_device_id; | 153 | struct pci_device_id; |
150 | struct qlcnic_host_sds_ring; | 154 | struct qlcnic_host_sds_ring; |
151 | struct qlcnic_host_tx_ring; | 155 | struct qlcnic_host_tx_ring; |
152 | struct qlcnic_host_tx_ring; | ||
153 | struct qlcnic_hardware_context; | 156 | struct qlcnic_hardware_context; |
154 | struct qlcnic_adapter; | 157 | struct qlcnic_adapter; |
155 | 158 | ||
@@ -173,10 +176,12 @@ int qlcnic_82xx_set_lb_mode(struct qlcnic_adapter *, u8); | |||
173 | void qlcnic_82xx_write_crb(struct qlcnic_adapter *, char *, loff_t, size_t); | 176 | void qlcnic_82xx_write_crb(struct qlcnic_adapter *, char *, loff_t, size_t); |
174 | void qlcnic_82xx_read_crb(struct qlcnic_adapter *, char *, loff_t, size_t); | 177 | void qlcnic_82xx_read_crb(struct qlcnic_adapter *, char *, loff_t, size_t); |
175 | void qlcnic_82xx_dev_request_reset(struct qlcnic_adapter *, u32); | 178 | void qlcnic_82xx_dev_request_reset(struct qlcnic_adapter *, u32); |
176 | int qlcnic_82xx_setup_intr(struct qlcnic_adapter *, u8); | 179 | int qlcnic_82xx_setup_intr(struct qlcnic_adapter *, u8, int); |
177 | irqreturn_t qlcnic_82xx_clear_legacy_intr(struct qlcnic_adapter *); | 180 | irqreturn_t qlcnic_82xx_clear_legacy_intr(struct qlcnic_adapter *); |
178 | int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter, | 181 | int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter, |
179 | struct qlcnic_cmd_args *); | 182 | struct qlcnic_cmd_args *); |
183 | int qlcnic_82xx_mq_intrpt(struct qlcnic_adapter *, int); | ||
184 | int qlcnic_82xx_config_intrpt(struct qlcnic_adapter *, u8); | ||
180 | int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *); | 185 | int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *); |
181 | int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *, | 186 | int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *, |
182 | struct qlcnic_host_tx_ring *tx_ring, int); | 187 | struct qlcnic_host_tx_ring *tx_ring, int); |
@@ -184,7 +189,7 @@ void qlcnic_82xx_fw_cmd_del_rx_ctx(struct qlcnic_adapter *); | |||
184 | void qlcnic_82xx_fw_cmd_del_tx_ctx(struct qlcnic_adapter *, | 189 | void qlcnic_82xx_fw_cmd_del_tx_ctx(struct qlcnic_adapter *, |
185 | struct qlcnic_host_tx_ring *); | 190 | struct qlcnic_host_tx_ring *); |
186 | int qlcnic_82xx_sre_macaddr_change(struct qlcnic_adapter *, u8 *, u16, u8); | 191 | int qlcnic_82xx_sre_macaddr_change(struct qlcnic_adapter *, u8 *, u16, u8); |
187 | int qlcnic_82xx_get_mac_address(struct qlcnic_adapter *, u8*); | 192 | int qlcnic_82xx_get_mac_address(struct qlcnic_adapter *, u8*, u8); |
188 | int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8); | 193 | int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8); |
189 | int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *); | 194 | int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *); |
190 | int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info*); | 195 | int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info*); |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c index 974d62607e13..66c26cf7a2b8 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | |||
@@ -127,12 +127,12 @@ void qlcnic_reset_rx_buffers_list(struct qlcnic_adapter *adapter) | |||
127 | } | 127 | } |
128 | } | 128 | } |
129 | 129 | ||
130 | void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter) | 130 | void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter, |
131 | struct qlcnic_host_tx_ring *tx_ring) | ||
131 | { | 132 | { |
132 | struct qlcnic_cmd_buffer *cmd_buf; | 133 | struct qlcnic_cmd_buffer *cmd_buf; |
133 | struct qlcnic_skb_frag *buffrag; | 134 | struct qlcnic_skb_frag *buffrag; |
134 | int i, j; | 135 | int i, j; |
135 | struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; | ||
136 | 136 | ||
137 | cmd_buf = tx_ring->cmd_buf_arr; | 137 | cmd_buf = tx_ring->cmd_buf_arr; |
138 | for (i = 0; i < tx_ring->num_desc; i++) { | 138 | for (i = 0; i < tx_ring->num_desc; i++) { |
@@ -241,7 +241,13 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) | |||
241 | sds_ring->irq = adapter->msix_entries[ring].vector; | 241 | sds_ring->irq = adapter->msix_entries[ring].vector; |
242 | sds_ring->adapter = adapter; | 242 | sds_ring->adapter = adapter; |
243 | sds_ring->num_desc = adapter->num_rxd; | 243 | sds_ring->num_desc = adapter->num_rxd; |
244 | 244 | if (qlcnic_82xx_check(adapter)) { | |
245 | if (qlcnic_check_multi_tx(adapter) && | ||
246 | !adapter->ahw->diag_test) | ||
247 | sds_ring->tx_ring = &adapter->tx_ring[ring]; | ||
248 | else | ||
249 | sds_ring->tx_ring = &adapter->tx_ring[0]; | ||
250 | } | ||
245 | for (i = 0; i < NUM_RCV_DESC_RINGS; i++) | 251 | for (i = 0; i < NUM_RCV_DESC_RINGS; i++) |
246 | INIT_LIST_HEAD(&sds_ring->free_list[i]); | 252 | INIT_LIST_HEAD(&sds_ring->free_list[i]); |
247 | } | 253 | } |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c index 6946d354f44f..b7b245b43b87 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | |||
@@ -127,6 +127,23 @@ | |||
127 | struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *, | 127 | struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *, |
128 | struct qlcnic_host_rds_ring *, u16, u16); | 128 | struct qlcnic_host_rds_ring *, u16, u16); |
129 | 129 | ||
130 | inline void qlcnic_enable_tx_intr(struct qlcnic_adapter *adapter, | ||
131 | struct qlcnic_host_tx_ring *tx_ring) | ||
132 | { | ||
133 | if (qlcnic_check_multi_tx(adapter) && | ||
134 | !adapter->ahw->diag_test) | ||
135 | writel(0x0, tx_ring->crb_intr_mask); | ||
136 | } | ||
137 | |||
138 | |||
139 | static inline void qlcnic_disable_tx_int(struct qlcnic_adapter *adapter, | ||
140 | struct qlcnic_host_tx_ring *tx_ring) | ||
141 | { | ||
142 | if (qlcnic_check_multi_tx(adapter) && | ||
143 | !adapter->ahw->diag_test) | ||
144 | writel(1, tx_ring->crb_intr_mask); | ||
145 | } | ||
146 | |||
130 | inline void qlcnic_83xx_enable_tx_intr(struct qlcnic_adapter *adapter, | 147 | inline void qlcnic_83xx_enable_tx_intr(struct qlcnic_adapter *adapter, |
131 | struct qlcnic_host_tx_ring *tx_ring) | 148 | struct qlcnic_host_tx_ring *tx_ring) |
132 | { | 149 | { |
@@ -147,10 +164,7 @@ static inline u8 qlcnic_mac_hash(u64 mac) | |||
147 | static inline u32 qlcnic_get_ref_handle(struct qlcnic_adapter *adapter, | 164 | static inline u32 qlcnic_get_ref_handle(struct qlcnic_adapter *adapter, |
148 | u16 handle, u8 ring_id) | 165 | u16 handle, u8 ring_id) |
149 | { | 166 | { |
150 | unsigned short device = adapter->pdev->device; | 167 | if (qlcnic_83xx_check(adapter)) |
151 | |||
152 | if ((device == PCI_DEVICE_ID_QLOGIC_QLE834X) || | ||
153 | (device == PCI_DEVICE_ID_QLOGIC_VF_QLE834X)) | ||
154 | return handle | (ring_id << 15); | 168 | return handle | (ring_id << 15); |
155 | else | 169 | else |
156 | return handle; | 170 | return handle; |
@@ -357,14 +371,14 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter, | |||
357 | } | 371 | } |
358 | 372 | ||
359 | static int qlcnic_tx_pkt(struct qlcnic_adapter *adapter, | 373 | static int qlcnic_tx_pkt(struct qlcnic_adapter *adapter, |
360 | struct cmd_desc_type0 *first_desc, struct sk_buff *skb) | 374 | struct cmd_desc_type0 *first_desc, struct sk_buff *skb, |
375 | struct qlcnic_host_tx_ring *tx_ring) | ||
361 | { | 376 | { |
362 | u8 l4proto, opcode = 0, hdr_len = 0; | 377 | u8 l4proto, opcode = 0, hdr_len = 0; |
363 | u16 flags = 0, vlan_tci = 0; | 378 | u16 flags = 0, vlan_tci = 0; |
364 | int copied, offset, copy_len, size; | 379 | int copied, offset, copy_len, size; |
365 | struct cmd_desc_type0 *hwdesc; | 380 | struct cmd_desc_type0 *hwdesc; |
366 | struct vlan_ethhdr *vh; | 381 | struct vlan_ethhdr *vh; |
367 | struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; | ||
368 | u16 protocol = ntohs(skb->protocol); | 382 | u16 protocol = ntohs(skb->protocol); |
369 | u32 producer = tx_ring->producer; | 383 | u32 producer = tx_ring->producer; |
370 | 384 | ||
@@ -547,7 +561,7 @@ static inline void qlcnic_clear_cmddesc(u64 *desc) | |||
547 | netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | 561 | netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) |
548 | { | 562 | { |
549 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 563 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
550 | struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; | 564 | struct qlcnic_host_tx_ring *tx_ring; |
551 | struct qlcnic_cmd_buffer *pbuf; | 565 | struct qlcnic_cmd_buffer *pbuf; |
552 | struct qlcnic_skb_frag *buffrag; | 566 | struct qlcnic_skb_frag *buffrag; |
553 | struct cmd_desc_type0 *hwdesc, *first_desc; | 567 | struct cmd_desc_type0 *hwdesc, *first_desc; |
@@ -556,10 +570,8 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
556 | int i, k, frag_count, delta = 0; | 570 | int i, k, frag_count, delta = 0; |
557 | u32 producer, num_txd; | 571 | u32 producer, num_txd; |
558 | 572 | ||
559 | num_txd = tx_ring->num_desc; | ||
560 | |||
561 | if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { | 573 | if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { |
562 | netif_stop_queue(netdev); | 574 | netif_tx_stop_all_queues(netdev); |
563 | return NETDEV_TX_BUSY; | 575 | return NETDEV_TX_BUSY; |
564 | } | 576 | } |
565 | 577 | ||
@@ -569,7 +581,14 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
569 | goto drop_packet; | 581 | goto drop_packet; |
570 | } | 582 | } |
571 | 583 | ||
584 | if (qlcnic_check_multi_tx(adapter)) | ||
585 | tx_ring = &adapter->tx_ring[skb_get_queue_mapping(skb)]; | ||
586 | else | ||
587 | tx_ring = &adapter->tx_ring[0]; | ||
588 | num_txd = tx_ring->num_desc; | ||
589 | |||
572 | frag_count = skb_shinfo(skb)->nr_frags + 1; | 590 | frag_count = skb_shinfo(skb)->nr_frags + 1; |
591 | |||
573 | /* 14 frags supported for normal packet and | 592 | /* 14 frags supported for normal packet and |
574 | * 32 frags supported for TSO packet | 593 | * 32 frags supported for TSO packet |
575 | */ | 594 | */ |
@@ -584,11 +603,12 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
584 | } | 603 | } |
585 | 604 | ||
586 | if (unlikely(qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH)) { | 605 | if (unlikely(qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH)) { |
587 | netif_stop_queue(netdev); | 606 | netif_tx_stop_queue(tx_ring->txq); |
588 | if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) { | 607 | if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) { |
589 | netif_start_queue(netdev); | 608 | netif_tx_start_queue(tx_ring->txq); |
590 | } else { | 609 | } else { |
591 | adapter->stats.xmit_off++; | 610 | adapter->stats.xmit_off++; |
611 | tx_ring->xmit_off++; | ||
592 | return NETDEV_TX_BUSY; | 612 | return NETDEV_TX_BUSY; |
593 | } | 613 | } |
594 | } | 614 | } |
@@ -643,7 +663,7 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
643 | tx_ring->producer = get_next_index(producer, num_txd); | 663 | tx_ring->producer = get_next_index(producer, num_txd); |
644 | smp_mb(); | 664 | smp_mb(); |
645 | 665 | ||
646 | if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb))) | 666 | if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb, tx_ring))) |
647 | goto unwind_buff; | 667 | goto unwind_buff; |
648 | 668 | ||
649 | if (adapter->drv_mac_learn) | 669 | if (adapter->drv_mac_learn) |
@@ -651,6 +671,7 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
651 | 671 | ||
652 | adapter->stats.txbytes += skb->len; | 672 | adapter->stats.txbytes += skb->len; |
653 | adapter->stats.xmitcalled++; | 673 | adapter->stats.xmitcalled++; |
674 | tx_ring->xmit_called++; | ||
654 | 675 | ||
655 | qlcnic_update_cmd_producer(tx_ring); | 676 | qlcnic_update_cmd_producer(tx_ring); |
656 | 677 | ||
@@ -673,7 +694,7 @@ void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup) | |||
673 | adapter->ahw->linkup = 0; | 694 | adapter->ahw->linkup = 0; |
674 | if (netif_running(netdev)) { | 695 | if (netif_running(netdev)) { |
675 | netif_carrier_off(netdev); | 696 | netif_carrier_off(netdev); |
676 | netif_stop_queue(netdev); | 697 | netif_tx_stop_all_queues(netdev); |
677 | } | 698 | } |
678 | } else if (!adapter->ahw->linkup && linkup) { | 699 | } else if (!adapter->ahw->linkup && linkup) { |
679 | netdev_info(netdev, "NIC Link is up\n"); | 700 | netdev_info(netdev, "NIC Link is up\n"); |
@@ -768,9 +789,6 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter, | |||
768 | struct net_device *netdev = adapter->netdev; | 789 | struct net_device *netdev = adapter->netdev; |
769 | struct qlcnic_skb_frag *frag; | 790 | struct qlcnic_skb_frag *frag; |
770 | 791 | ||
771 | if (!spin_trylock(&adapter->tx_clean_lock)) | ||
772 | return 1; | ||
773 | |||
774 | sw_consumer = tx_ring->sw_consumer; | 792 | sw_consumer = tx_ring->sw_consumer; |
775 | hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); | 793 | hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); |
776 | 794 | ||
@@ -788,6 +806,7 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter, | |||
788 | frag->dma = 0ULL; | 806 | frag->dma = 0ULL; |
789 | } | 807 | } |
790 | adapter->stats.xmitfinished++; | 808 | adapter->stats.xmitfinished++; |
809 | tx_ring->xmit_finished++; | ||
791 | dev_kfree_skb_any(buffer->skb); | 810 | dev_kfree_skb_any(buffer->skb); |
792 | buffer->skb = NULL; | 811 | buffer->skb = NULL; |
793 | } | 812 | } |
@@ -800,10 +819,12 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter, | |||
800 | if (count && netif_running(netdev)) { | 819 | if (count && netif_running(netdev)) { |
801 | tx_ring->sw_consumer = sw_consumer; | 820 | tx_ring->sw_consumer = sw_consumer; |
802 | smp_mb(); | 821 | smp_mb(); |
803 | if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { | 822 | if (netif_tx_queue_stopped(tx_ring->txq) && |
823 | netif_carrier_ok(netdev)) { | ||
804 | if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) { | 824 | if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) { |
805 | netif_wake_queue(netdev); | 825 | netif_tx_wake_queue(tx_ring->txq); |
806 | adapter->stats.xmit_on++; | 826 | adapter->stats.xmit_on++; |
827 | tx_ring->xmit_on++; | ||
807 | } | 828 | } |
808 | } | 829 | } |
809 | adapter->tx_timeo_cnt = 0; | 830 | adapter->tx_timeo_cnt = 0; |
@@ -823,7 +844,6 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter, | |||
823 | */ | 844 | */ |
824 | hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); | 845 | hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); |
825 | done = (sw_consumer == hw_consumer); | 846 | done = (sw_consumer == hw_consumer); |
826 | spin_unlock(&adapter->tx_clean_lock); | ||
827 | 847 | ||
828 | return done; | 848 | return done; |
829 | } | 849 | } |
@@ -833,16 +853,40 @@ static int qlcnic_poll(struct napi_struct *napi, int budget) | |||
833 | int tx_complete, work_done; | 853 | int tx_complete, work_done; |
834 | struct qlcnic_host_sds_ring *sds_ring; | 854 | struct qlcnic_host_sds_ring *sds_ring; |
835 | struct qlcnic_adapter *adapter; | 855 | struct qlcnic_adapter *adapter; |
856 | struct qlcnic_host_tx_ring *tx_ring; | ||
836 | 857 | ||
837 | sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi); | 858 | sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi); |
838 | adapter = sds_ring->adapter; | 859 | adapter = sds_ring->adapter; |
839 | tx_complete = qlcnic_process_cmd_ring(adapter, adapter->tx_ring, | 860 | tx_ring = sds_ring->tx_ring; |
861 | |||
862 | tx_complete = qlcnic_process_cmd_ring(adapter, tx_ring, | ||
840 | budget); | 863 | budget); |
841 | work_done = qlcnic_process_rcv_ring(sds_ring, budget); | 864 | work_done = qlcnic_process_rcv_ring(sds_ring, budget); |
842 | if ((work_done < budget) && tx_complete) { | 865 | if ((work_done < budget) && tx_complete) { |
843 | napi_complete(&sds_ring->napi); | 866 | napi_complete(&sds_ring->napi); |
844 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) | 867 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) { |
845 | qlcnic_enable_int(sds_ring); | 868 | qlcnic_enable_int(sds_ring); |
869 | qlcnic_enable_tx_intr(adapter, tx_ring); | ||
870 | } | ||
871 | } | ||
872 | |||
873 | return work_done; | ||
874 | } | ||
875 | |||
876 | static int qlcnic_tx_poll(struct napi_struct *napi, int budget) | ||
877 | { | ||
878 | struct qlcnic_host_tx_ring *tx_ring; | ||
879 | struct qlcnic_adapter *adapter; | ||
880 | int work_done; | ||
881 | |||
882 | tx_ring = container_of(napi, struct qlcnic_host_tx_ring, napi); | ||
883 | adapter = tx_ring->adapter; | ||
884 | |||
885 | work_done = qlcnic_process_cmd_ring(adapter, tx_ring, budget); | ||
886 | if (work_done) { | ||
887 | napi_complete(&tx_ring->napi); | ||
888 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) | ||
889 | qlcnic_enable_tx_intr(adapter, tx_ring); | ||
846 | } | 890 | } |
847 | 891 | ||
848 | return work_done; | 892 | return work_done; |
@@ -952,20 +996,23 @@ static void qlcnic_handle_fw_message(int desc_cnt, int index, | |||
952 | break; | 996 | break; |
953 | case 1: | 997 | case 1: |
954 | dev_info(dev, "loopback already in progress\n"); | 998 | dev_info(dev, "loopback already in progress\n"); |
955 | adapter->ahw->diag_cnt = -QLCNIC_TEST_IN_PROGRESS; | 999 | adapter->ahw->diag_cnt = -EINPROGRESS; |
956 | break; | 1000 | break; |
957 | case 2: | 1001 | case 2: |
958 | dev_info(dev, "loopback cable is not connected\n"); | 1002 | dev_info(dev, "loopback cable is not connected\n"); |
959 | adapter->ahw->diag_cnt = -QLCNIC_LB_CABLE_NOT_CONN; | 1003 | adapter->ahw->diag_cnt = -ENODEV; |
960 | break; | 1004 | break; |
961 | default: | 1005 | default: |
962 | dev_info(dev, | 1006 | dev_info(dev, |
963 | "loopback configure request failed, err %x\n", | 1007 | "loopback configure request failed, err %x\n", |
964 | ret); | 1008 | ret); |
965 | adapter->ahw->diag_cnt = -QLCNIC_UNDEFINED_ERROR; | 1009 | adapter->ahw->diag_cnt = -EIO; |
966 | break; | 1010 | break; |
967 | } | 1011 | } |
968 | break; | 1012 | break; |
1013 | case QLCNIC_C2H_OPCODE_GET_DCB_AEN: | ||
1014 | qlcnic_dcb_handle_aen(adapter, (void *)&msg); | ||
1015 | break; | ||
969 | default: | 1016 | default: |
970 | break; | 1017 | break; |
971 | } | 1018 | } |
@@ -1411,23 +1458,31 @@ void qlcnic_82xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring) | |||
1411 | int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter, | 1458 | int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter, |
1412 | struct net_device *netdev) | 1459 | struct net_device *netdev) |
1413 | { | 1460 | { |
1414 | int ring, max_sds_rings; | 1461 | int ring; |
1415 | struct qlcnic_host_sds_ring *sds_ring; | 1462 | struct qlcnic_host_sds_ring *sds_ring; |
1416 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | 1463 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; |
1464 | struct qlcnic_host_tx_ring *tx_ring; | ||
1417 | 1465 | ||
1418 | if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings)) | 1466 | if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings)) |
1419 | return -ENOMEM; | 1467 | return -ENOMEM; |
1420 | 1468 | ||
1421 | max_sds_rings = adapter->max_sds_rings; | ||
1422 | |||
1423 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | 1469 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
1424 | sds_ring = &recv_ctx->sds_rings[ring]; | 1470 | sds_ring = &recv_ctx->sds_rings[ring]; |
1425 | if (ring == adapter->max_sds_rings - 1) | 1471 | if (qlcnic_check_multi_tx(adapter) && |
1426 | netif_napi_add(netdev, &sds_ring->napi, qlcnic_poll, | 1472 | !adapter->ahw->diag_test && |
1427 | QLCNIC_NETDEV_WEIGHT / max_sds_rings); | 1473 | (adapter->max_drv_tx_rings > 1)) { |
1428 | else | ||
1429 | netif_napi_add(netdev, &sds_ring->napi, qlcnic_rx_poll, | 1474 | netif_napi_add(netdev, &sds_ring->napi, qlcnic_rx_poll, |
1430 | QLCNIC_NETDEV_WEIGHT*2); | 1475 | NAPI_POLL_WEIGHT); |
1476 | } else { | ||
1477 | if (ring == (adapter->max_sds_rings - 1)) | ||
1478 | netif_napi_add(netdev, &sds_ring->napi, | ||
1479 | qlcnic_poll, | ||
1480 | NAPI_POLL_WEIGHT); | ||
1481 | else | ||
1482 | netif_napi_add(netdev, &sds_ring->napi, | ||
1483 | qlcnic_rx_poll, | ||
1484 | NAPI_POLL_WEIGHT); | ||
1485 | } | ||
1431 | } | 1486 | } |
1432 | 1487 | ||
1433 | if (qlcnic_alloc_tx_rings(adapter, netdev)) { | 1488 | if (qlcnic_alloc_tx_rings(adapter, netdev)) { |
@@ -1435,6 +1490,14 @@ int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter, | |||
1435 | return -ENOMEM; | 1490 | return -ENOMEM; |
1436 | } | 1491 | } |
1437 | 1492 | ||
1493 | if (qlcnic_check_multi_tx(adapter) && !adapter->ahw->diag_test) { | ||
1494 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | ||
1495 | tx_ring = &adapter->tx_ring[ring]; | ||
1496 | netif_napi_add(netdev, &tx_ring->napi, qlcnic_tx_poll, | ||
1497 | NAPI_POLL_WEIGHT); | ||
1498 | } | ||
1499 | } | ||
1500 | |||
1438 | return 0; | 1501 | return 0; |
1439 | } | 1502 | } |
1440 | 1503 | ||
@@ -1443,6 +1506,7 @@ void qlcnic_82xx_napi_del(struct qlcnic_adapter *adapter) | |||
1443 | int ring; | 1506 | int ring; |
1444 | struct qlcnic_host_sds_ring *sds_ring; | 1507 | struct qlcnic_host_sds_ring *sds_ring; |
1445 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | 1508 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; |
1509 | struct qlcnic_host_tx_ring *tx_ring; | ||
1446 | 1510 | ||
1447 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | 1511 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
1448 | sds_ring = &recv_ctx->sds_rings[ring]; | 1512 | sds_ring = &recv_ctx->sds_rings[ring]; |
@@ -1450,6 +1514,14 @@ void qlcnic_82xx_napi_del(struct qlcnic_adapter *adapter) | |||
1450 | } | 1514 | } |
1451 | 1515 | ||
1452 | qlcnic_free_sds_rings(adapter->recv_ctx); | 1516 | qlcnic_free_sds_rings(adapter->recv_ctx); |
1517 | |||
1518 | if (qlcnic_check_multi_tx(adapter) && !adapter->ahw->diag_test) { | ||
1519 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | ||
1520 | tx_ring = &adapter->tx_ring[ring]; | ||
1521 | netif_napi_del(&tx_ring->napi); | ||
1522 | } | ||
1523 | } | ||
1524 | |||
1453 | qlcnic_free_tx_rings(adapter); | 1525 | qlcnic_free_tx_rings(adapter); |
1454 | } | 1526 | } |
1455 | 1527 | ||
@@ -1457,6 +1529,7 @@ void qlcnic_82xx_napi_enable(struct qlcnic_adapter *adapter) | |||
1457 | { | 1529 | { |
1458 | int ring; | 1530 | int ring; |
1459 | struct qlcnic_host_sds_ring *sds_ring; | 1531 | struct qlcnic_host_sds_ring *sds_ring; |
1532 | struct qlcnic_host_tx_ring *tx_ring; | ||
1460 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | 1533 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; |
1461 | 1534 | ||
1462 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) | 1535 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) |
@@ -1467,12 +1540,24 @@ void qlcnic_82xx_napi_enable(struct qlcnic_adapter *adapter) | |||
1467 | napi_enable(&sds_ring->napi); | 1540 | napi_enable(&sds_ring->napi); |
1468 | qlcnic_enable_int(sds_ring); | 1541 | qlcnic_enable_int(sds_ring); |
1469 | } | 1542 | } |
1543 | |||
1544 | if (qlcnic_check_multi_tx(adapter) && | ||
1545 | (adapter->flags & QLCNIC_MSIX_ENABLED) && | ||
1546 | !adapter->ahw->diag_test && | ||
1547 | (adapter->max_drv_tx_rings > 1)) { | ||
1548 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | ||
1549 | tx_ring = &adapter->tx_ring[ring]; | ||
1550 | napi_enable(&tx_ring->napi); | ||
1551 | qlcnic_enable_tx_intr(adapter, tx_ring); | ||
1552 | } | ||
1553 | } | ||
1470 | } | 1554 | } |
1471 | 1555 | ||
1472 | void qlcnic_82xx_napi_disable(struct qlcnic_adapter *adapter) | 1556 | void qlcnic_82xx_napi_disable(struct qlcnic_adapter *adapter) |
1473 | { | 1557 | { |
1474 | int ring; | 1558 | int ring; |
1475 | struct qlcnic_host_sds_ring *sds_ring; | 1559 | struct qlcnic_host_sds_ring *sds_ring; |
1560 | struct qlcnic_host_tx_ring *tx_ring; | ||
1476 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | 1561 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; |
1477 | 1562 | ||
1478 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) | 1563 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) |
@@ -1484,6 +1569,17 @@ void qlcnic_82xx_napi_disable(struct qlcnic_adapter *adapter) | |||
1484 | napi_synchronize(&sds_ring->napi); | 1569 | napi_synchronize(&sds_ring->napi); |
1485 | napi_disable(&sds_ring->napi); | 1570 | napi_disable(&sds_ring->napi); |
1486 | } | 1571 | } |
1572 | |||
1573 | if ((adapter->flags & QLCNIC_MSIX_ENABLED) && | ||
1574 | !adapter->ahw->diag_test && | ||
1575 | qlcnic_check_multi_tx(adapter)) { | ||
1576 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | ||
1577 | tx_ring = &adapter->tx_ring[ring]; | ||
1578 | qlcnic_disable_tx_int(adapter, tx_ring); | ||
1579 | napi_synchronize(&tx_ring->napi); | ||
1580 | napi_disable(&tx_ring->napi); | ||
1581 | } | ||
1582 | } | ||
1487 | } | 1583 | } |
1488 | 1584 | ||
1489 | #define QLC_83XX_NORMAL_LB_PKT (1ULL << 36) | 1585 | #define QLC_83XX_NORMAL_LB_PKT (1ULL << 36) |
@@ -1864,7 +1960,7 @@ void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter) | |||
1864 | int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter, | 1960 | int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter, |
1865 | struct net_device *netdev) | 1961 | struct net_device *netdev) |
1866 | { | 1962 | { |
1867 | int ring, max_sds_rings, temp; | 1963 | int ring; |
1868 | struct qlcnic_host_sds_ring *sds_ring; | 1964 | struct qlcnic_host_sds_ring *sds_ring; |
1869 | struct qlcnic_host_tx_ring *tx_ring; | 1965 | struct qlcnic_host_tx_ring *tx_ring; |
1870 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | 1966 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; |
@@ -1872,25 +1968,22 @@ int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter, | |||
1872 | if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings)) | 1968 | if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings)) |
1873 | return -ENOMEM; | 1969 | return -ENOMEM; |
1874 | 1970 | ||
1875 | max_sds_rings = adapter->max_sds_rings; | ||
1876 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | 1971 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
1877 | sds_ring = &recv_ctx->sds_rings[ring]; | 1972 | sds_ring = &recv_ctx->sds_rings[ring]; |
1878 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { | 1973 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { |
1879 | if (!(adapter->flags & QLCNIC_TX_INTR_SHARED)) { | 1974 | if (!(adapter->flags & QLCNIC_TX_INTR_SHARED)) |
1880 | netif_napi_add(netdev, &sds_ring->napi, | 1975 | netif_napi_add(netdev, &sds_ring->napi, |
1881 | qlcnic_83xx_rx_poll, | 1976 | qlcnic_83xx_rx_poll, |
1882 | QLCNIC_NETDEV_WEIGHT * 2); | 1977 | NAPI_POLL_WEIGHT); |
1883 | } else { | 1978 | else |
1884 | temp = QLCNIC_NETDEV_WEIGHT / max_sds_rings; | ||
1885 | netif_napi_add(netdev, &sds_ring->napi, | 1979 | netif_napi_add(netdev, &sds_ring->napi, |
1886 | qlcnic_83xx_msix_sriov_vf_poll, | 1980 | qlcnic_83xx_msix_sriov_vf_poll, |
1887 | temp); | 1981 | NAPI_POLL_WEIGHT); |
1888 | } | ||
1889 | 1982 | ||
1890 | } else { | 1983 | } else { |
1891 | netif_napi_add(netdev, &sds_ring->napi, | 1984 | netif_napi_add(netdev, &sds_ring->napi, |
1892 | qlcnic_83xx_poll, | 1985 | qlcnic_83xx_poll, |
1893 | QLCNIC_NETDEV_WEIGHT / max_sds_rings); | 1986 | NAPI_POLL_WEIGHT); |
1894 | } | 1987 | } |
1895 | } | 1988 | } |
1896 | 1989 | ||
@@ -1905,7 +1998,7 @@ int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter, | |||
1905 | tx_ring = &adapter->tx_ring[ring]; | 1998 | tx_ring = &adapter->tx_ring[ring]; |
1906 | netif_napi_add(netdev, &tx_ring->napi, | 1999 | netif_napi_add(netdev, &tx_ring->napi, |
1907 | qlcnic_83xx_msix_tx_poll, | 2000 | qlcnic_83xx_msix_tx_poll, |
1908 | QLCNIC_NETDEV_WEIGHT); | 2001 | NAPI_POLL_WEIGHT); |
1909 | } | 2002 | } |
1910 | } | 2003 | } |
1911 | 2004 | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index bc05d016c859..c4c5023e1fdf 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
@@ -100,6 +100,8 @@ static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = { | |||
100 | ENTRY(PCI_DEVICE_ID_QLOGIC_QLE824X), | 100 | ENTRY(PCI_DEVICE_ID_QLOGIC_QLE824X), |
101 | ENTRY(PCI_DEVICE_ID_QLOGIC_QLE834X), | 101 | ENTRY(PCI_DEVICE_ID_QLOGIC_QLE834X), |
102 | ENTRY(PCI_DEVICE_ID_QLOGIC_VF_QLE834X), | 102 | ENTRY(PCI_DEVICE_ID_QLOGIC_VF_QLE834X), |
103 | ENTRY(PCI_DEVICE_ID_QLOGIC_QLE844X), | ||
104 | ENTRY(PCI_DEVICE_ID_QLOGIC_VF_QLE844X), | ||
103 | {0,} | 105 | {0,} |
104 | }; | 106 | }; |
105 | 107 | ||
@@ -146,6 +148,11 @@ static const u32 qlcnic_reg_tbl[] = { | |||
146 | 148 | ||
147 | static const struct qlcnic_board_info qlcnic_boards[] = { | 149 | static const struct qlcnic_board_info qlcnic_boards[] = { |
148 | { PCI_VENDOR_ID_QLOGIC, | 150 | { PCI_VENDOR_ID_QLOGIC, |
151 | PCI_DEVICE_ID_QLOGIC_QLE844X, | ||
152 | 0x0, | ||
153 | 0x0, | ||
154 | "8400 series 10GbE Converged Network Adapter (TCP/IP Networking)" }, | ||
155 | { PCI_VENDOR_ID_QLOGIC, | ||
149 | PCI_DEVICE_ID_QLOGIC_QLE834X, | 156 | PCI_DEVICE_ID_QLOGIC_QLE834X, |
150 | PCI_VENDOR_ID_QLOGIC, | 157 | PCI_VENDOR_ID_QLOGIC, |
151 | 0x24e, | 158 | 0x24e, |
@@ -254,7 +261,6 @@ static const struct qlcnic_board_info qlcnic_boards[] = { | |||
254 | }; | 261 | }; |
255 | 262 | ||
256 | #define NUM_SUPPORTED_BOARDS ARRAY_SIZE(qlcnic_boards) | 263 | #define NUM_SUPPORTED_BOARDS ARRAY_SIZE(qlcnic_boards) |
257 | #define QLC_MAX_SDS_RINGS 8 | ||
258 | 264 | ||
259 | static const | 265 | static const |
260 | struct qlcnic_legacy_intr_set legacy_intr[] = QLCNIC_LEGACY_INTR_CONFIG; | 266 | struct qlcnic_legacy_intr_set legacy_intr[] = QLCNIC_LEGACY_INTR_CONFIG; |
@@ -278,12 +284,15 @@ void qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx) | |||
278 | 284 | ||
279 | int qlcnic_read_mac_addr(struct qlcnic_adapter *adapter) | 285 | int qlcnic_read_mac_addr(struct qlcnic_adapter *adapter) |
280 | { | 286 | { |
281 | u8 mac_addr[ETH_ALEN]; | ||
282 | struct net_device *netdev = adapter->netdev; | 287 | struct net_device *netdev = adapter->netdev; |
283 | struct pci_dev *pdev = adapter->pdev; | 288 | struct pci_dev *pdev = adapter->pdev; |
289 | u8 mac_addr[ETH_ALEN]; | ||
290 | int ret; | ||
284 | 291 | ||
285 | if (qlcnic_get_mac_address(adapter, mac_addr) != 0) | 292 | ret = qlcnic_get_mac_address(adapter, mac_addr, |
286 | return -EIO; | 293 | adapter->ahw->pci_func); |
294 | if (ret) | ||
295 | return ret; | ||
287 | 296 | ||
288 | memcpy(netdev->dev_addr, mac_addr, ETH_ALEN); | 297 | memcpy(netdev->dev_addr, mac_addr, ETH_ALEN); |
289 | memcpy(adapter->mac_addr, netdev->dev_addr, netdev->addr_len); | 298 | memcpy(adapter->mac_addr, netdev->dev_addr, netdev->addr_len); |
@@ -425,6 +434,21 @@ static void qlcnic_82xx_cancel_idc_work(struct qlcnic_adapter *adapter) | |||
425 | cancel_delayed_work_sync(&adapter->fw_work); | 434 | cancel_delayed_work_sync(&adapter->fw_work); |
426 | } | 435 | } |
427 | 436 | ||
437 | static int qlcnic_get_phys_port_id(struct net_device *netdev, | ||
438 | struct netdev_phys_port_id *ppid) | ||
439 | { | ||
440 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
441 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
442 | |||
443 | if (!(adapter->flags & QLCNIC_HAS_PHYS_PORT_ID)) | ||
444 | return -EOPNOTSUPP; | ||
445 | |||
446 | ppid->id_len = sizeof(ahw->phys_port_id); | ||
447 | memcpy(ppid->id, ahw->phys_port_id, ppid->id_len); | ||
448 | |||
449 | return 0; | ||
450 | } | ||
451 | |||
428 | static const struct net_device_ops qlcnic_netdev_ops = { | 452 | static const struct net_device_ops qlcnic_netdev_ops = { |
429 | .ndo_open = qlcnic_open, | 453 | .ndo_open = qlcnic_open, |
430 | .ndo_stop = qlcnic_close, | 454 | .ndo_stop = qlcnic_close, |
@@ -442,6 +466,7 @@ static const struct net_device_ops qlcnic_netdev_ops = { | |||
442 | .ndo_fdb_add = qlcnic_fdb_add, | 466 | .ndo_fdb_add = qlcnic_fdb_add, |
443 | .ndo_fdb_del = qlcnic_fdb_del, | 467 | .ndo_fdb_del = qlcnic_fdb_del, |
444 | .ndo_fdb_dump = qlcnic_fdb_dump, | 468 | .ndo_fdb_dump = qlcnic_fdb_dump, |
469 | .ndo_get_phys_port_id = qlcnic_get_phys_port_id, | ||
445 | #ifdef CONFIG_NET_POLL_CONTROLLER | 470 | #ifdef CONFIG_NET_POLL_CONTROLLER |
446 | .ndo_poll_controller = qlcnic_poll_controller, | 471 | .ndo_poll_controller = qlcnic_poll_controller, |
447 | #endif | 472 | #endif |
@@ -514,13 +539,36 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = { | |||
514 | .get_board_info = qlcnic_82xx_get_board_info, | 539 | .get_board_info = qlcnic_82xx_get_board_info, |
515 | .set_mac_filter_count = qlcnic_82xx_set_mac_filter_count, | 540 | .set_mac_filter_count = qlcnic_82xx_set_mac_filter_count, |
516 | .free_mac_list = qlcnic_82xx_free_mac_list, | 541 | .free_mac_list = qlcnic_82xx_free_mac_list, |
542 | .read_phys_port_id = qlcnic_82xx_read_phys_port_id, | ||
543 | .io_error_detected = qlcnic_82xx_io_error_detected, | ||
544 | .io_slot_reset = qlcnic_82xx_io_slot_reset, | ||
545 | .io_resume = qlcnic_82xx_io_resume, | ||
517 | }; | 546 | }; |
518 | 547 | ||
548 | static void qlcnic_get_multiq_capability(struct qlcnic_adapter *adapter) | ||
549 | { | ||
550 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
551 | int num_tx_q; | ||
552 | |||
553 | if (ahw->msix_supported && | ||
554 | (ahw->extra_capability[0] & QLCNIC_FW_CAPABILITY_2_MULTI_TX)) { | ||
555 | num_tx_q = min_t(int, QLCNIC_DEF_NUM_TX_RINGS, | ||
556 | num_online_cpus()); | ||
557 | if (num_tx_q > 1) { | ||
558 | test_and_set_bit(__QLCNIC_MULTI_TX_UNIQUE, | ||
559 | &adapter->state); | ||
560 | adapter->max_drv_tx_rings = num_tx_q; | ||
561 | } | ||
562 | } else { | ||
563 | adapter->max_drv_tx_rings = 1; | ||
564 | } | ||
565 | } | ||
566 | |||
519 | int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) | 567 | int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) |
520 | { | 568 | { |
521 | struct pci_dev *pdev = adapter->pdev; | 569 | struct pci_dev *pdev = adapter->pdev; |
570 | int max_tx_rings, max_sds_rings, tx_vector; | ||
522 | int err = -1, i; | 571 | int err = -1, i; |
523 | int max_tx_rings, tx_vector; | ||
524 | 572 | ||
525 | if (adapter->flags & QLCNIC_TX_INTR_SHARED) { | 573 | if (adapter->flags & QLCNIC_TX_INTR_SHARED) { |
526 | max_tx_rings = 0; | 574 | max_tx_rings = 0; |
@@ -554,7 +602,15 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) | |||
554 | adapter->max_sds_rings = num_msix - | 602 | adapter->max_sds_rings = num_msix - |
555 | max_tx_rings - 1; | 603 | max_tx_rings - 1; |
556 | } else { | 604 | } else { |
557 | adapter->max_sds_rings = num_msix; | 605 | adapter->ahw->num_msix = num_msix; |
606 | if (qlcnic_check_multi_tx(adapter) && | ||
607 | !adapter->ahw->diag_test && | ||
608 | (adapter->max_drv_tx_rings > 1)) | ||
609 | max_sds_rings = num_msix - max_tx_rings; | ||
610 | else | ||
611 | max_sds_rings = num_msix; | ||
612 | |||
613 | adapter->max_sds_rings = max_sds_rings; | ||
558 | } | 614 | } |
559 | dev_info(&pdev->dev, "using msi-x interrupts\n"); | 615 | dev_info(&pdev->dev, "using msi-x interrupts\n"); |
560 | return err; | 616 | return err; |
@@ -570,6 +626,8 @@ int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) | |||
570 | num_msix += (max_tx_rings + 1); | 626 | num_msix += (max_tx_rings + 1); |
571 | } else { | 627 | } else { |
572 | num_msix = rounddown_pow_of_two(err); | 628 | num_msix = rounddown_pow_of_two(err); |
629 | if (qlcnic_check_multi_tx(adapter)) | ||
630 | num_msix += max_tx_rings; | ||
573 | } | 631 | } |
574 | 632 | ||
575 | if (num_msix) { | 633 | if (num_msix) { |
@@ -605,6 +663,7 @@ static int qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter) | |||
605 | adapter->msix_entries[0].vector = pdev->irq; | 663 | adapter->msix_entries[0].vector = pdev->irq; |
606 | return err; | 664 | return err; |
607 | } | 665 | } |
666 | |||
608 | if (qlcnic_use_msi || qlcnic_use_msi_x) | 667 | if (qlcnic_use_msi || qlcnic_use_msi_x) |
609 | return -EOPNOTSUPP; | 668 | return -EOPNOTSUPP; |
610 | 669 | ||
@@ -621,28 +680,69 @@ static int qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter) | |||
621 | return err; | 680 | return err; |
622 | } | 681 | } |
623 | 682 | ||
624 | int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr) | 683 | int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr, int txq) |
625 | { | 684 | { |
685 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
626 | int num_msix, err = 0; | 686 | int num_msix, err = 0; |
627 | 687 | ||
628 | if (!num_intr) | 688 | if (!num_intr) |
629 | num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS; | 689 | num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS; |
630 | 690 | ||
631 | if (adapter->ahw->msix_supported) | 691 | if (ahw->msix_supported) { |
632 | num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(), | 692 | num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(), |
633 | num_intr)); | 693 | num_intr)); |
634 | else | 694 | if (qlcnic_check_multi_tx(adapter)) { |
695 | if (txq) | ||
696 | adapter->max_drv_tx_rings = txq; | ||
697 | num_msix += adapter->max_drv_tx_rings; | ||
698 | } | ||
699 | } else { | ||
635 | num_msix = 1; | 700 | num_msix = 1; |
701 | } | ||
636 | 702 | ||
637 | err = qlcnic_enable_msix(adapter, num_msix); | 703 | err = qlcnic_enable_msix(adapter, num_msix); |
638 | if (err == -ENOMEM || !err) | 704 | if (err == -ENOMEM) |
639 | return err; | 705 | return err; |
640 | 706 | ||
641 | err = qlcnic_enable_msi_legacy(adapter); | 707 | if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) { |
642 | if (!err) | 708 | qlcnic_disable_multi_tx(adapter); |
709 | |||
710 | err = qlcnic_enable_msi_legacy(adapter); | ||
711 | if (!err) | ||
712 | return err; | ||
713 | } | ||
714 | |||
715 | return 0; | ||
716 | } | ||
717 | |||
718 | int qlcnic_82xx_mq_intrpt(struct qlcnic_adapter *adapter, int op_type) | ||
719 | { | ||
720 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
721 | int err, i; | ||
722 | |||
723 | if (qlcnic_check_multi_tx(adapter) && | ||
724 | !ahw->diag_test && | ||
725 | (adapter->flags & QLCNIC_MSIX_ENABLED)) { | ||
726 | ahw->intr_tbl = vzalloc(ahw->num_msix * | ||
727 | sizeof(struct qlcnic_intrpt_config)); | ||
728 | if (!ahw->intr_tbl) | ||
729 | return -ENOMEM; | ||
730 | |||
731 | for (i = 0; i < ahw->num_msix; i++) { | ||
732 | ahw->intr_tbl[i].type = QLCNIC_INTRPT_MSIX; | ||
733 | ahw->intr_tbl[i].id = i; | ||
734 | ahw->intr_tbl[i].src = 0; | ||
735 | } | ||
736 | |||
737 | err = qlcnic_82xx_config_intrpt(adapter, 1); | ||
738 | if (err) | ||
739 | dev_err(&adapter->pdev->dev, | ||
740 | "Failed to configure Interrupt for %d vector\n", | ||
741 | ahw->num_msix); | ||
643 | return err; | 742 | return err; |
743 | } | ||
644 | 744 | ||
645 | return -EIO; | 745 | return 0; |
646 | } | 746 | } |
647 | 747 | ||
648 | void qlcnic_teardown_intr(struct qlcnic_adapter *adapter) | 748 | void qlcnic_teardown_intr(struct qlcnic_adapter *adapter) |
@@ -696,6 +796,23 @@ static int qlcnic_get_act_pci_func(struct qlcnic_adapter *adapter) | |||
696 | return ret; | 796 | return ret; |
697 | } | 797 | } |
698 | 798 | ||
799 | static bool qlcnic_port_eswitch_cfg_capability(struct qlcnic_adapter *adapter) | ||
800 | { | ||
801 | bool ret = false; | ||
802 | |||
803 | if (qlcnic_84xx_check(adapter)) { | ||
804 | ret = true; | ||
805 | } else if (qlcnic_83xx_check(adapter)) { | ||
806 | if (adapter->ahw->extra_capability[0] & | ||
807 | QLCNIC_FW_CAPABILITY_2_PER_PORT_ESWITCH_CFG) | ||
808 | ret = true; | ||
809 | else | ||
810 | ret = false; | ||
811 | } | ||
812 | |||
813 | return ret; | ||
814 | } | ||
815 | |||
699 | int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) | 816 | int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) |
700 | { | 817 | { |
701 | struct qlcnic_pci_info *pci_info; | 818 | struct qlcnic_pci_info *pci_info; |
@@ -739,18 +856,30 @@ int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) | |||
739 | (pci_info[i].type != QLCNIC_TYPE_NIC)) | 856 | (pci_info[i].type != QLCNIC_TYPE_NIC)) |
740 | continue; | 857 | continue; |
741 | 858 | ||
859 | if (qlcnic_port_eswitch_cfg_capability(adapter)) { | ||
860 | if (!qlcnic_83xx_enable_port_eswitch(adapter, pfn)) | ||
861 | adapter->npars[j].eswitch_status = true; | ||
862 | else | ||
863 | continue; | ||
864 | } else { | ||
865 | adapter->npars[j].eswitch_status = true; | ||
866 | } | ||
867 | |||
742 | adapter->npars[j].pci_func = pfn; | 868 | adapter->npars[j].pci_func = pfn; |
743 | adapter->npars[j].active = (u8)pci_info[i].active; | 869 | adapter->npars[j].active = (u8)pci_info[i].active; |
744 | adapter->npars[j].type = (u8)pci_info[i].type; | 870 | adapter->npars[j].type = (u8)pci_info[i].type; |
745 | adapter->npars[j].phy_port = (u8)pci_info[i].default_port; | 871 | adapter->npars[j].phy_port = (u8)pci_info[i].default_port; |
746 | adapter->npars[j].min_bw = pci_info[i].tx_min_bw; | 872 | adapter->npars[j].min_bw = pci_info[i].tx_min_bw; |
747 | adapter->npars[j].max_bw = pci_info[i].tx_max_bw; | 873 | adapter->npars[j].max_bw = pci_info[i].tx_max_bw; |
874 | |||
748 | j++; | 875 | j++; |
749 | } | 876 | } |
750 | 877 | ||
751 | for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) { | 878 | if (qlcnic_82xx_check(adapter)) { |
752 | adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE; | 879 | for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) |
753 | if (qlcnic_83xx_check(adapter)) | 880 | adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE; |
881 | } else if (!qlcnic_port_eswitch_cfg_capability(adapter)) { | ||
882 | for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) | ||
754 | qlcnic_enable_eswitch(adapter, i, 1); | 883 | qlcnic_enable_eswitch(adapter, i, 1); |
755 | } | 884 | } |
756 | 885 | ||
@@ -829,7 +958,9 @@ static void qlcnic_get_bar_length(u32 dev_id, ulong *bar) | |||
829 | *bar = QLCNIC_82XX_BAR0_LENGTH; | 958 | *bar = QLCNIC_82XX_BAR0_LENGTH; |
830 | break; | 959 | break; |
831 | case PCI_DEVICE_ID_QLOGIC_QLE834X: | 960 | case PCI_DEVICE_ID_QLOGIC_QLE834X: |
961 | case PCI_DEVICE_ID_QLOGIC_QLE844X: | ||
832 | case PCI_DEVICE_ID_QLOGIC_VF_QLE834X: | 962 | case PCI_DEVICE_ID_QLOGIC_VF_QLE834X: |
963 | case PCI_DEVICE_ID_QLOGIC_VF_QLE844X: | ||
833 | *bar = QLCNIC_83XX_BAR0_LENGTH; | 964 | *bar = QLCNIC_83XX_BAR0_LENGTH; |
834 | break; | 965 | break; |
835 | default: | 966 | default: |
@@ -870,8 +1001,8 @@ static int qlcnic_setup_pci_map(struct pci_dev *pdev, | |||
870 | return 0; | 1001 | return 0; |
871 | } | 1002 | } |
872 | 1003 | ||
873 | static inline bool qlcnic_validate_subsystem_id(struct qlcnic_adapter *adapter, | 1004 | static bool qlcnic_validate_subsystem_id(struct qlcnic_adapter *adapter, |
874 | int index) | 1005 | int index) |
875 | { | 1006 | { |
876 | struct pci_dev *pdev = adapter->pdev; | 1007 | struct pci_dev *pdev = adapter->pdev; |
877 | unsigned short subsystem_vendor; | 1008 | unsigned short subsystem_vendor; |
@@ -1173,6 +1304,9 @@ int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter) | |||
1173 | return 0; | 1304 | return 0; |
1174 | 1305 | ||
1175 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { | 1306 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { |
1307 | if (!adapter->npars[i].eswitch_status) | ||
1308 | continue; | ||
1309 | |||
1176 | memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg)); | 1310 | memset(&esw_cfg, 0, sizeof(struct qlcnic_esw_func_cfg)); |
1177 | esw_cfg.pci_func = adapter->npars[i].pci_func; | 1311 | esw_cfg.pci_func = adapter->npars[i].pci_func; |
1178 | esw_cfg.mac_override = BIT_0; | 1312 | esw_cfg.mac_override = BIT_0; |
@@ -1235,6 +1369,9 @@ int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter) | |||
1235 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { | 1369 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { |
1236 | npar = &adapter->npars[i]; | 1370 | npar = &adapter->npars[i]; |
1237 | pci_func = npar->pci_func; | 1371 | pci_func = npar->pci_func; |
1372 | if (!adapter->npars[i].eswitch_status) | ||
1373 | continue; | ||
1374 | |||
1238 | memset(&nic_info, 0, sizeof(struct qlcnic_info)); | 1375 | memset(&nic_info, 0, sizeof(struct qlcnic_info)); |
1239 | err = qlcnic_get_nic_info(adapter, &nic_info, pci_func); | 1376 | err = qlcnic_get_nic_info(adapter, &nic_info, pci_func); |
1240 | if (err) | 1377 | if (err) |
@@ -1413,6 +1550,7 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter) | |||
1413 | for (ring = 0; ring < num_sds_rings; ring++) { | 1550 | for (ring = 0; ring < num_sds_rings; ring++) { |
1414 | sds_ring = &recv_ctx->sds_rings[ring]; | 1551 | sds_ring = &recv_ctx->sds_rings[ring]; |
1415 | if (qlcnic_82xx_check(adapter) && | 1552 | if (qlcnic_82xx_check(adapter) && |
1553 | !qlcnic_check_multi_tx(adapter) && | ||
1416 | (ring == (num_sds_rings - 1))) { | 1554 | (ring == (num_sds_rings - 1))) { |
1417 | if (!(adapter->flags & | 1555 | if (!(adapter->flags & |
1418 | QLCNIC_MSIX_ENABLED)) | 1556 | QLCNIC_MSIX_ENABLED)) |
@@ -1436,9 +1574,11 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter) | |||
1436 | return err; | 1574 | return err; |
1437 | } | 1575 | } |
1438 | } | 1576 | } |
1439 | if (qlcnic_83xx_check(adapter) && | 1577 | if ((qlcnic_82xx_check(adapter) && |
1440 | (adapter->flags & QLCNIC_MSIX_ENABLED) && | 1578 | qlcnic_check_multi_tx(adapter)) || |
1441 | !(adapter->flags & QLCNIC_TX_INTR_SHARED)) { | 1579 | (qlcnic_83xx_check(adapter) && |
1580 | (adapter->flags & QLCNIC_MSIX_ENABLED) && | ||
1581 | !(adapter->flags & QLCNIC_TX_INTR_SHARED))) { | ||
1442 | handler = qlcnic_msix_tx_intr; | 1582 | handler = qlcnic_msix_tx_intr; |
1443 | for (ring = 0; ring < adapter->max_drv_tx_rings; | 1583 | for (ring = 0; ring < adapter->max_drv_tx_rings; |
1444 | ring++) { | 1584 | ring++) { |
@@ -1473,8 +1613,10 @@ qlcnic_free_irq(struct qlcnic_adapter *adapter) | |||
1473 | free_irq(sds_ring->irq, sds_ring); | 1613 | free_irq(sds_ring->irq, sds_ring); |
1474 | } | 1614 | } |
1475 | } | 1615 | } |
1476 | if (qlcnic_83xx_check(adapter) && | 1616 | if ((qlcnic_83xx_check(adapter) && |
1477 | !(adapter->flags & QLCNIC_TX_INTR_SHARED)) { | 1617 | !(adapter->flags & QLCNIC_TX_INTR_SHARED)) || |
1618 | (qlcnic_82xx_check(adapter) && | ||
1619 | qlcnic_check_multi_tx(adapter))) { | ||
1478 | for (ring = 0; ring < adapter->max_drv_tx_rings; | 1620 | for (ring = 0; ring < adapter->max_drv_tx_rings; |
1479 | ring++) { | 1621 | ring++) { |
1480 | tx_ring = &adapter->tx_ring[ring]; | 1622 | tx_ring = &adapter->tx_ring[ring]; |
@@ -1510,8 +1652,10 @@ int __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) | |||
1510 | 1652 | ||
1511 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) | 1653 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) |
1512 | return 0; | 1654 | return 0; |
1655 | |||
1513 | if (qlcnic_set_eswitch_port_config(adapter)) | 1656 | if (qlcnic_set_eswitch_port_config(adapter)) |
1514 | return -EIO; | 1657 | return -EIO; |
1658 | |||
1515 | qlcnic_get_lro_mss_capability(adapter); | 1659 | qlcnic_get_lro_mss_capability(adapter); |
1516 | 1660 | ||
1517 | if (qlcnic_fw_create_ctx(adapter)) | 1661 | if (qlcnic_fw_create_ctx(adapter)) |
@@ -1558,6 +1702,8 @@ int qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) | |||
1558 | 1702 | ||
1559 | void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) | 1703 | void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) |
1560 | { | 1704 | { |
1705 | int ring; | ||
1706 | |||
1561 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) | 1707 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) |
1562 | return; | 1708 | return; |
1563 | 1709 | ||
@@ -1567,7 +1713,6 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) | |||
1567 | if (qlcnic_sriov_vf_check(adapter)) | 1713 | if (qlcnic_sriov_vf_check(adapter)) |
1568 | qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc); | 1714 | qlcnic_sriov_cleanup_async_list(&adapter->ahw->sriov->bc); |
1569 | smp_mb(); | 1715 | smp_mb(); |
1570 | spin_lock(&adapter->tx_clean_lock); | ||
1571 | netif_carrier_off(netdev); | 1716 | netif_carrier_off(netdev); |
1572 | adapter->ahw->linkup = 0; | 1717 | adapter->ahw->linkup = 0; |
1573 | netif_tx_disable(netdev); | 1718 | netif_tx_disable(netdev); |
@@ -1585,8 +1730,9 @@ void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) | |||
1585 | adapter->flags &= ~QLCNIC_FW_LRO_MSS_CAP; | 1730 | adapter->flags &= ~QLCNIC_FW_LRO_MSS_CAP; |
1586 | 1731 | ||
1587 | qlcnic_reset_rx_buffers_list(adapter); | 1732 | qlcnic_reset_rx_buffers_list(adapter); |
1588 | qlcnic_release_tx_buffers(adapter); | 1733 | |
1589 | spin_unlock(&adapter->tx_clean_lock); | 1734 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) |
1735 | qlcnic_release_tx_buffers(adapter, &adapter->tx_ring[ring]); | ||
1590 | } | 1736 | } |
1591 | 1737 | ||
1592 | /* Usage: During suspend and firmware recovery module */ | 1738 | /* Usage: During suspend and firmware recovery module */ |
@@ -1666,6 +1812,7 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings) | |||
1666 | { | 1812 | { |
1667 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 1813 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
1668 | struct qlcnic_host_sds_ring *sds_ring; | 1814 | struct qlcnic_host_sds_ring *sds_ring; |
1815 | int max_tx_rings = adapter->max_drv_tx_rings; | ||
1669 | int ring; | 1816 | int ring; |
1670 | 1817 | ||
1671 | clear_bit(__QLCNIC_DEV_UP, &adapter->state); | 1818 | clear_bit(__QLCNIC_DEV_UP, &adapter->state); |
@@ -1682,6 +1829,7 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings) | |||
1682 | 1829 | ||
1683 | adapter->ahw->diag_test = 0; | 1830 | adapter->ahw->diag_test = 0; |
1684 | adapter->max_sds_rings = max_sds_rings; | 1831 | adapter->max_sds_rings = max_sds_rings; |
1832 | adapter->max_drv_tx_rings = max_tx_rings; | ||
1685 | 1833 | ||
1686 | if (qlcnic_attach(adapter)) | 1834 | if (qlcnic_attach(adapter)) |
1687 | goto out; | 1835 | goto out; |
@@ -1750,6 +1898,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test) | |||
1750 | adapter->max_sds_rings = 1; | 1898 | adapter->max_sds_rings = 1; |
1751 | adapter->ahw->diag_test = test; | 1899 | adapter->ahw->diag_test = test; |
1752 | adapter->ahw->linkup = 0; | 1900 | adapter->ahw->linkup = 0; |
1901 | adapter->max_drv_tx_rings = 1; | ||
1753 | 1902 | ||
1754 | ret = qlcnic_attach(adapter); | 1903 | ret = qlcnic_attach(adapter); |
1755 | if (ret) { | 1904 | if (ret) { |
@@ -1907,12 +2056,18 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev, | |||
1907 | netdev->priv_flags |= IFF_UNICAST_FLT; | 2056 | netdev->priv_flags |= IFF_UNICAST_FLT; |
1908 | netdev->irq = adapter->msix_entries[0].vector; | 2057 | netdev->irq = adapter->msix_entries[0].vector; |
1909 | 2058 | ||
2059 | err = qlcnic_set_real_num_queues(adapter, netdev); | ||
2060 | if (err) | ||
2061 | return err; | ||
2062 | |||
1910 | err = register_netdev(netdev); | 2063 | err = register_netdev(netdev); |
1911 | if (err) { | 2064 | if (err) { |
1912 | dev_err(&pdev->dev, "failed to register net device\n"); | 2065 | dev_err(&pdev->dev, "failed to register net device\n"); |
1913 | return err; | 2066 | return err; |
1914 | } | 2067 | } |
1915 | 2068 | ||
2069 | qlcnic_dcb_init_dcbnl_ops(adapter); | ||
2070 | |||
1916 | return 0; | 2071 | return 0; |
1917 | } | 2072 | } |
1918 | 2073 | ||
@@ -1975,7 +2130,8 @@ int qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter, | |||
1975 | tx_ring->cmd_buf_arr = cmd_buf_arr; | 2130 | tx_ring->cmd_buf_arr = cmd_buf_arr; |
1976 | } | 2131 | } |
1977 | 2132 | ||
1978 | if (qlcnic_83xx_check(adapter)) { | 2133 | if (qlcnic_83xx_check(adapter) || |
2134 | (qlcnic_82xx_check(adapter) && qlcnic_check_multi_tx(adapter))) { | ||
1979 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | 2135 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { |
1980 | tx_ring = &adapter->tx_ring[ring]; | 2136 | tx_ring = &adapter->tx_ring[ring]; |
1981 | tx_ring->adapter = adapter; | 2137 | tx_ring->adapter = adapter; |
@@ -1986,6 +2142,7 @@ int qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter, | |||
1986 | } | 2142 | } |
1987 | } | 2143 | } |
1988 | } | 2144 | } |
2145 | |||
1989 | return 0; | 2146 | return 0; |
1990 | } | 2147 | } |
1991 | 2148 | ||
@@ -2004,6 +2161,17 @@ void qlcnic_set_drv_version(struct qlcnic_adapter *adapter) | |||
2004 | qlcnic_fw_cmd_set_drv_version(adapter, fw_cmd); | 2161 | qlcnic_fw_cmd_set_drv_version(adapter, fw_cmd); |
2005 | } | 2162 | } |
2006 | 2163 | ||
2164 | static int qlcnic_register_dcb(struct qlcnic_adapter *adapter) | ||
2165 | { | ||
2166 | return __qlcnic_register_dcb(adapter); | ||
2167 | } | ||
2168 | |||
2169 | void qlcnic_clear_dcb_ops(struct qlcnic_adapter *adapter) | ||
2170 | { | ||
2171 | kfree(adapter->dcb); | ||
2172 | adapter->dcb = NULL; | ||
2173 | } | ||
2174 | |||
2007 | static int | 2175 | static int |
2008 | qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 2176 | qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
2009 | { | 2177 | { |
@@ -2048,9 +2216,11 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2048 | ahw->reg_tbl = (u32 *) qlcnic_reg_tbl; | 2216 | ahw->reg_tbl = (u32 *) qlcnic_reg_tbl; |
2049 | break; | 2217 | break; |
2050 | case PCI_DEVICE_ID_QLOGIC_QLE834X: | 2218 | case PCI_DEVICE_ID_QLOGIC_QLE834X: |
2219 | case PCI_DEVICE_ID_QLOGIC_QLE844X: | ||
2051 | qlcnic_83xx_register_map(ahw); | 2220 | qlcnic_83xx_register_map(ahw); |
2052 | break; | 2221 | break; |
2053 | case PCI_DEVICE_ID_QLOGIC_VF_QLE834X: | 2222 | case PCI_DEVICE_ID_QLOGIC_VF_QLE834X: |
2223 | case PCI_DEVICE_ID_QLOGIC_VF_QLE844X: | ||
2054 | qlcnic_sriov_vf_register_map(ahw); | 2224 | qlcnic_sriov_vf_register_map(ahw); |
2055 | break; | 2225 | break; |
2056 | default: | 2226 | default: |
@@ -2061,7 +2231,8 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2061 | if (err) | 2231 | if (err) |
2062 | goto err_out_free_hw_res; | 2232 | goto err_out_free_hw_res; |
2063 | 2233 | ||
2064 | netdev = alloc_etherdev(sizeof(struct qlcnic_adapter)); | 2234 | netdev = alloc_etherdev_mq(sizeof(struct qlcnic_adapter), |
2235 | QLCNIC_MAX_TX_RINGS); | ||
2065 | if (!netdev) { | 2236 | if (!netdev) { |
2066 | err = -ENOMEM; | 2237 | err = -ENOMEM; |
2067 | goto err_out_iounmap; | 2238 | goto err_out_iounmap; |
@@ -2091,14 +2262,14 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2091 | adapter->fdb_mac_learn = true; | 2262 | adapter->fdb_mac_learn = true; |
2092 | else if (qlcnic_mac_learn == DRV_MAC_LEARN) | 2263 | else if (qlcnic_mac_learn == DRV_MAC_LEARN) |
2093 | adapter->drv_mac_learn = true; | 2264 | adapter->drv_mac_learn = true; |
2094 | adapter->max_drv_tx_rings = 1; | ||
2095 | 2265 | ||
2096 | rwlock_init(&adapter->ahw->crb_lock); | 2266 | rwlock_init(&adapter->ahw->crb_lock); |
2097 | mutex_init(&adapter->ahw->mem_lock); | 2267 | mutex_init(&adapter->ahw->mem_lock); |
2098 | 2268 | ||
2099 | spin_lock_init(&adapter->tx_clean_lock); | ||
2100 | INIT_LIST_HEAD(&adapter->mac_list); | 2269 | INIT_LIST_HEAD(&adapter->mac_list); |
2101 | 2270 | ||
2271 | qlcnic_register_dcb(adapter); | ||
2272 | |||
2102 | if (qlcnic_82xx_check(adapter)) { | 2273 | if (qlcnic_82xx_check(adapter)) { |
2103 | qlcnic_check_vf(adapter, ent); | 2274 | qlcnic_check_vf(adapter, ent); |
2104 | adapter->portnum = adapter->ahw->pci_func; | 2275 | adapter->portnum = adapter->ahw->pci_func; |
@@ -2108,12 +2279,31 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2108 | goto err_out_free_hw; | 2279 | goto err_out_free_hw; |
2109 | } | 2280 | } |
2110 | 2281 | ||
2282 | qlcnic_get_multiq_capability(adapter); | ||
2283 | |||
2284 | if ((adapter->ahw->act_pci_func > 2) && | ||
2285 | qlcnic_check_multi_tx(adapter)) { | ||
2286 | adapter->max_drv_tx_rings = QLCNIC_DEF_NUM_TX_RINGS; | ||
2287 | dev_info(&adapter->pdev->dev, | ||
2288 | "vNIC mode enabled, Set max TX rings = %d\n", | ||
2289 | adapter->max_drv_tx_rings); | ||
2290 | } | ||
2291 | |||
2292 | if (!qlcnic_check_multi_tx(adapter)) { | ||
2293 | clear_bit(__QLCNIC_MULTI_TX_UNIQUE, &adapter->state); | ||
2294 | adapter->max_drv_tx_rings = 1; | ||
2295 | } | ||
2111 | err = qlcnic_setup_idc_param(adapter); | 2296 | err = qlcnic_setup_idc_param(adapter); |
2112 | if (err) | 2297 | if (err) |
2113 | goto err_out_free_hw; | 2298 | goto err_out_free_hw; |
2114 | 2299 | ||
2115 | adapter->flags |= QLCNIC_NEED_FLR; | 2300 | adapter->flags |= QLCNIC_NEED_FLR; |
2301 | |||
2302 | if (adapter->dcb && qlcnic_dcb_attach(adapter)) | ||
2303 | qlcnic_clear_dcb_ops(adapter); | ||
2304 | |||
2116 | } else if (qlcnic_83xx_check(adapter)) { | 2305 | } else if (qlcnic_83xx_check(adapter)) { |
2306 | adapter->max_drv_tx_rings = 1; | ||
2117 | qlcnic_83xx_check_vf(adapter, ent); | 2307 | qlcnic_83xx_check_vf(adapter, ent); |
2118 | adapter->portnum = adapter->ahw->pci_func; | 2308 | adapter->portnum = adapter->ahw->pci_func; |
2119 | err = qlcnic_83xx_init(adapter, pci_using_dac); | 2309 | err = qlcnic_83xx_init(adapter, pci_using_dac); |
@@ -2132,6 +2322,8 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2132 | if (qlcnic_read_mac_addr(adapter)) | 2322 | if (qlcnic_read_mac_addr(adapter)) |
2133 | dev_warn(&pdev->dev, "failed to read mac addr\n"); | 2323 | dev_warn(&pdev->dev, "failed to read mac addr\n"); |
2134 | 2324 | ||
2325 | qlcnic_read_phys_port_id(adapter); | ||
2326 | |||
2135 | if (adapter->portnum == 0) { | 2327 | if (adapter->portnum == 0) { |
2136 | qlcnic_get_board_name(adapter, board_name); | 2328 | qlcnic_get_board_name(adapter, board_name); |
2137 | 2329 | ||
@@ -2145,16 +2337,12 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2145 | dev_warn(&pdev->dev, | 2337 | dev_warn(&pdev->dev, |
2146 | "Device does not support MSI interrupts\n"); | 2338 | "Device does not support MSI interrupts\n"); |
2147 | 2339 | ||
2148 | err = qlcnic_setup_intr(adapter, 0); | 2340 | if (qlcnic_82xx_check(adapter)) { |
2149 | if (err) { | 2341 | err = qlcnic_setup_intr(adapter, 0, 0); |
2150 | dev_err(&pdev->dev, "Failed to setup interrupt\n"); | 2342 | if (err) { |
2151 | goto err_out_disable_msi; | 2343 | dev_err(&pdev->dev, "Failed to setup interrupt\n"); |
2152 | } | ||
2153 | |||
2154 | if (qlcnic_83xx_check(adapter)) { | ||
2155 | err = qlcnic_83xx_setup_mbx_intr(adapter); | ||
2156 | if (err) | ||
2157 | goto err_out_disable_msi; | 2344 | goto err_out_disable_msi; |
2345 | } | ||
2158 | } | 2346 | } |
2159 | 2347 | ||
2160 | err = qlcnic_get_act_pci_func(adapter); | 2348 | err = qlcnic_get_act_pci_func(adapter); |
@@ -2238,13 +2426,18 @@ static void qlcnic_remove(struct pci_dev *pdev) | |||
2238 | qlcnic_cancel_idc_work(adapter); | 2426 | qlcnic_cancel_idc_work(adapter); |
2239 | ahw = adapter->ahw; | 2427 | ahw = adapter->ahw; |
2240 | 2428 | ||
2429 | qlcnic_dcb_free(adapter); | ||
2430 | |||
2241 | unregister_netdev(netdev); | 2431 | unregister_netdev(netdev); |
2242 | qlcnic_sriov_cleanup(adapter); | 2432 | qlcnic_sriov_cleanup(adapter); |
2243 | 2433 | ||
2244 | if (qlcnic_83xx_check(adapter)) { | 2434 | if (qlcnic_83xx_check(adapter)) { |
2245 | qlcnic_83xx_free_mbx_intr(adapter); | ||
2246 | qlcnic_83xx_register_nic_idc_func(adapter, 0); | 2435 | qlcnic_83xx_register_nic_idc_func(adapter, 0); |
2247 | cancel_delayed_work_sync(&adapter->idc_aen_work); | 2436 | cancel_delayed_work_sync(&adapter->idc_aen_work); |
2437 | qlcnic_83xx_free_mbx_intr(adapter); | ||
2438 | qlcnic_83xx_detach_mailbox_work(adapter); | ||
2439 | qlcnic_83xx_free_mailbox(ahw->mailbox); | ||
2440 | kfree(ahw->fw_info); | ||
2248 | } | 2441 | } |
2249 | 2442 | ||
2250 | qlcnic_detach(adapter); | 2443 | qlcnic_detach(adapter); |
@@ -2278,6 +2471,7 @@ static void qlcnic_remove(struct pci_dev *pdev) | |||
2278 | destroy_workqueue(adapter->qlcnic_wq); | 2471 | destroy_workqueue(adapter->qlcnic_wq); |
2279 | adapter->qlcnic_wq = NULL; | 2472 | adapter->qlcnic_wq = NULL; |
2280 | } | 2473 | } |
2474 | |||
2281 | qlcnic_free_adapter_resources(adapter); | 2475 | qlcnic_free_adapter_resources(adapter); |
2282 | kfree(ahw); | 2476 | kfree(ahw); |
2283 | free_netdev(netdev); | 2477 | free_netdev(netdev); |
@@ -2336,7 +2530,7 @@ static int qlcnic_open(struct net_device *netdev) | |||
2336 | if (err) | 2530 | if (err) |
2337 | goto err_out; | 2531 | goto err_out; |
2338 | 2532 | ||
2339 | netif_start_queue(netdev); | 2533 | netif_tx_start_all_queues(netdev); |
2340 | 2534 | ||
2341 | return 0; | 2535 | return 0; |
2342 | 2536 | ||
@@ -2468,6 +2662,8 @@ int qlcnic_check_temp(struct qlcnic_adapter *adapter) | |||
2468 | static void qlcnic_tx_timeout(struct net_device *netdev) | 2662 | static void qlcnic_tx_timeout(struct net_device *netdev) |
2469 | { | 2663 | { |
2470 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 2664 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
2665 | struct qlcnic_host_tx_ring *tx_ring; | ||
2666 | int ring; | ||
2471 | 2667 | ||
2472 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) | 2668 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) |
2473 | return; | 2669 | return; |
@@ -2481,6 +2677,25 @@ static void qlcnic_tx_timeout(struct net_device *netdev) | |||
2481 | QLCNIC_FORCE_FW_DUMP_KEY); | 2677 | QLCNIC_FORCE_FW_DUMP_KEY); |
2482 | } else { | 2678 | } else { |
2483 | netdev_info(netdev, "Tx timeout, reset adapter context.\n"); | 2679 | netdev_info(netdev, "Tx timeout, reset adapter context.\n"); |
2680 | if (qlcnic_82xx_check(adapter)) { | ||
2681 | for (ring = 0; ring < adapter->max_drv_tx_rings; | ||
2682 | ring++) { | ||
2683 | tx_ring = &adapter->tx_ring[ring]; | ||
2684 | dev_info(&netdev->dev, "ring=%d\n", ring); | ||
2685 | dev_info(&netdev->dev, "crb_intr_mask=%d\n", | ||
2686 | readl(tx_ring->crb_intr_mask)); | ||
2687 | dev_info(&netdev->dev, "producer=%d\n", | ||
2688 | readl(tx_ring->crb_cmd_producer)); | ||
2689 | dev_info(&netdev->dev, "sw_consumer = %d\n", | ||
2690 | tx_ring->sw_consumer); | ||
2691 | dev_info(&netdev->dev, "hw_consumer = %d\n", | ||
2692 | le32_to_cpu(*(tx_ring->hw_consumer))); | ||
2693 | dev_info(&netdev->dev, "xmit-on=%llu\n", | ||
2694 | tx_ring->xmit_on); | ||
2695 | dev_info(&netdev->dev, "xmit-off=%llu\n", | ||
2696 | tx_ring->xmit_off); | ||
2697 | } | ||
2698 | } | ||
2484 | adapter->ahw->reset_context = 1; | 2699 | adapter->ahw->reset_context = 1; |
2485 | } | 2700 | } |
2486 | } | 2701 | } |
@@ -2869,7 +3084,7 @@ skip_ack_check: | |||
2869 | qlcnic_api_unlock(adapter); | 3084 | qlcnic_api_unlock(adapter); |
2870 | 3085 | ||
2871 | rtnl_lock(); | 3086 | rtnl_lock(); |
2872 | if (adapter->ahw->fw_dump.enable && | 3087 | if (qlcnic_check_fw_dump_state(adapter) && |
2873 | (adapter->flags & QLCNIC_FW_RESET_OWNER)) { | 3088 | (adapter->flags & QLCNIC_FW_RESET_OWNER)) { |
2874 | QLCDB(adapter, DRV, "Take FW dump\n"); | 3089 | QLCDB(adapter, DRV, "Take FW dump\n"); |
2875 | qlcnic_dump_fw(adapter); | 3090 | qlcnic_dump_fw(adapter); |
@@ -3074,6 +3289,8 @@ qlcnic_attach_work(struct work_struct *work) | |||
3074 | return; | 3289 | return; |
3075 | } | 3290 | } |
3076 | attach: | 3291 | attach: |
3292 | qlcnic_dcb_get_info(adapter); | ||
3293 | |||
3077 | if (netif_running(netdev)) { | 3294 | if (netif_running(netdev)) { |
3078 | if (qlcnic_up(adapter, netdev)) | 3295 | if (qlcnic_up(adapter, netdev)) |
3079 | goto done; | 3296 | goto done; |
@@ -3245,7 +3462,7 @@ static int qlcnic_attach_func(struct pci_dev *pdev) | |||
3245 | qlcnic_clr_drv_state(adapter); | 3462 | qlcnic_clr_drv_state(adapter); |
3246 | kfree(adapter->msix_entries); | 3463 | kfree(adapter->msix_entries); |
3247 | adapter->msix_entries = NULL; | 3464 | adapter->msix_entries = NULL; |
3248 | err = qlcnic_setup_intr(adapter, 0); | 3465 | err = qlcnic_setup_intr(adapter, 0, 0); |
3249 | 3466 | ||
3250 | if (err) { | 3467 | if (err) { |
3251 | kfree(adapter->msix_entries); | 3468 | kfree(adapter->msix_entries); |
@@ -3253,19 +3470,6 @@ static int qlcnic_attach_func(struct pci_dev *pdev) | |||
3253 | return err; | 3470 | return err; |
3254 | } | 3471 | } |
3255 | 3472 | ||
3256 | if (qlcnic_83xx_check(adapter)) { | ||
3257 | /* register for NIC IDC AEN Events */ | ||
3258 | qlcnic_83xx_register_nic_idc_func(adapter, 1); | ||
3259 | err = qlcnic_83xx_setup_mbx_intr(adapter); | ||
3260 | if (err) { | ||
3261 | dev_err(&adapter->pdev->dev, | ||
3262 | "failed to setup mbx interrupt\n"); | ||
3263 | qlcnic_clr_all_drv_state(adapter, 1); | ||
3264 | clear_bit(__QLCNIC_AER, &adapter->state); | ||
3265 | goto done; | ||
3266 | } | ||
3267 | } | ||
3268 | |||
3269 | if (netif_running(netdev)) { | 3473 | if (netif_running(netdev)) { |
3270 | err = qlcnic_attach(adapter); | 3474 | err = qlcnic_attach(adapter); |
3271 | if (err) { | 3475 | if (err) { |
@@ -3286,8 +3490,8 @@ static int qlcnic_attach_func(struct pci_dev *pdev) | |||
3286 | return err; | 3490 | return err; |
3287 | } | 3491 | } |
3288 | 3492 | ||
3289 | static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev, | 3493 | pci_ers_result_t qlcnic_82xx_io_error_detected(struct pci_dev *pdev, |
3290 | pci_channel_state_t state) | 3494 | pci_channel_state_t state) |
3291 | { | 3495 | { |
3292 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | 3496 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); |
3293 | struct net_device *netdev = adapter->netdev; | 3497 | struct net_device *netdev = adapter->netdev; |
@@ -3306,12 +3510,6 @@ static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev, | |||
3306 | if (netif_running(netdev)) | 3510 | if (netif_running(netdev)) |
3307 | qlcnic_down(adapter, netdev); | 3511 | qlcnic_down(adapter, netdev); |
3308 | 3512 | ||
3309 | if (qlcnic_83xx_check(adapter)) { | ||
3310 | qlcnic_83xx_free_mbx_intr(adapter); | ||
3311 | qlcnic_83xx_register_nic_idc_func(adapter, 0); | ||
3312 | cancel_delayed_work_sync(&adapter->idc_aen_work); | ||
3313 | } | ||
3314 | |||
3315 | qlcnic_detach(adapter); | 3513 | qlcnic_detach(adapter); |
3316 | qlcnic_teardown_intr(adapter); | 3514 | qlcnic_teardown_intr(adapter); |
3317 | 3515 | ||
@@ -3323,13 +3521,13 @@ static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev, | |||
3323 | return PCI_ERS_RESULT_NEED_RESET; | 3521 | return PCI_ERS_RESULT_NEED_RESET; |
3324 | } | 3522 | } |
3325 | 3523 | ||
3326 | static pci_ers_result_t qlcnic_io_slot_reset(struct pci_dev *pdev) | 3524 | pci_ers_result_t qlcnic_82xx_io_slot_reset(struct pci_dev *pdev) |
3327 | { | 3525 | { |
3328 | return qlcnic_attach_func(pdev) ? PCI_ERS_RESULT_DISCONNECT : | 3526 | return qlcnic_attach_func(pdev) ? PCI_ERS_RESULT_DISCONNECT : |
3329 | PCI_ERS_RESULT_RECOVERED; | 3527 | PCI_ERS_RESULT_RECOVERED; |
3330 | } | 3528 | } |
3331 | 3529 | ||
3332 | static void qlcnic_io_resume(struct pci_dev *pdev) | 3530 | void qlcnic_82xx_io_resume(struct pci_dev *pdev) |
3333 | { | 3531 | { |
3334 | u32 state; | 3532 | u32 state; |
3335 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | 3533 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); |
@@ -3339,9 +3537,48 @@ static void qlcnic_io_resume(struct pci_dev *pdev) | |||
3339 | if (state == QLCNIC_DEV_READY && test_and_clear_bit(__QLCNIC_AER, | 3537 | if (state == QLCNIC_DEV_READY && test_and_clear_bit(__QLCNIC_AER, |
3340 | &adapter->state)) | 3538 | &adapter->state)) |
3341 | qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, | 3539 | qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, |
3342 | FW_POLL_DELAY); | 3540 | FW_POLL_DELAY); |
3541 | } | ||
3542 | |||
3543 | static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev, | ||
3544 | pci_channel_state_t state) | ||
3545 | { | ||
3546 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | ||
3547 | struct qlcnic_hardware_ops *hw_ops = adapter->ahw->hw_ops; | ||
3548 | |||
3549 | if (hw_ops->io_error_detected) { | ||
3550 | return hw_ops->io_error_detected(pdev, state); | ||
3551 | } else { | ||
3552 | dev_err(&pdev->dev, "AER error_detected handler not registered.\n"); | ||
3553 | return PCI_ERS_RESULT_DISCONNECT; | ||
3554 | } | ||
3555 | } | ||
3556 | |||
3557 | static pci_ers_result_t qlcnic_io_slot_reset(struct pci_dev *pdev) | ||
3558 | { | ||
3559 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | ||
3560 | struct qlcnic_hardware_ops *hw_ops = adapter->ahw->hw_ops; | ||
3561 | |||
3562 | if (hw_ops->io_slot_reset) { | ||
3563 | return hw_ops->io_slot_reset(pdev); | ||
3564 | } else { | ||
3565 | dev_err(&pdev->dev, "AER slot_reset handler not registered.\n"); | ||
3566 | return PCI_ERS_RESULT_DISCONNECT; | ||
3567 | } | ||
3568 | } | ||
3569 | |||
3570 | static void qlcnic_io_resume(struct pci_dev *pdev) | ||
3571 | { | ||
3572 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | ||
3573 | struct qlcnic_hardware_ops *hw_ops = adapter->ahw->hw_ops; | ||
3574 | |||
3575 | if (hw_ops->io_resume) | ||
3576 | hw_ops->io_resume(pdev); | ||
3577 | else | ||
3578 | dev_err(&pdev->dev, "AER resume handler not registered.\n"); | ||
3343 | } | 3579 | } |
3344 | 3580 | ||
3581 | |||
3345 | static int | 3582 | static int |
3346 | qlcnicvf_start_firmware(struct qlcnic_adapter *adapter) | 3583 | qlcnicvf_start_firmware(struct qlcnic_adapter *adapter) |
3347 | { | 3584 | { |
@@ -3370,16 +3607,65 @@ qlcnicvf_start_firmware(struct qlcnic_adapter *adapter) | |||
3370 | return err; | 3607 | return err; |
3371 | } | 3608 | } |
3372 | 3609 | ||
3610 | int qlcnic_validate_max_tx_rings(struct qlcnic_adapter *adapter, u32 txq) | ||
3611 | { | ||
3612 | struct net_device *netdev = adapter->netdev; | ||
3613 | u8 max_hw = QLCNIC_MAX_TX_RINGS; | ||
3614 | u32 max_allowed; | ||
3615 | |||
3616 | if (!qlcnic_82xx_check(adapter)) { | ||
3617 | netdev_err(netdev, "No Multi TX-Q support\n"); | ||
3618 | return -EINVAL; | ||
3619 | } | ||
3620 | |||
3621 | if (!qlcnic_use_msi_x && !qlcnic_use_msi) { | ||
3622 | netdev_err(netdev, "No Multi TX-Q support in INT-x mode\n"); | ||
3623 | return -EINVAL; | ||
3624 | } | ||
3625 | |||
3626 | if (!qlcnic_check_multi_tx(adapter)) { | ||
3627 | netdev_err(netdev, "No Multi TX-Q support\n"); | ||
3628 | return -EINVAL; | ||
3629 | } | ||
3630 | |||
3631 | if (txq > QLCNIC_MAX_TX_RINGS) { | ||
3632 | netdev_err(netdev, "Invalid ring count\n"); | ||
3633 | return -EINVAL; | ||
3634 | } | ||
3635 | |||
3636 | max_allowed = rounddown_pow_of_two(min_t(int, max_hw, | ||
3637 | num_online_cpus())); | ||
3638 | if ((txq > max_allowed) || !is_power_of_2(txq)) { | ||
3639 | if (!is_power_of_2(txq)) | ||
3640 | netdev_err(netdev, | ||
3641 | "TX queue should be a power of 2\n"); | ||
3642 | if (txq > num_online_cpus()) | ||
3643 | netdev_err(netdev, | ||
3644 | "Tx queue should not be higher than [%u], number of online CPUs in the system\n", | ||
3645 | num_online_cpus()); | ||
3646 | netdev_err(netdev, "Unable to configure %u Tx rings\n", txq); | ||
3647 | return -EINVAL; | ||
3648 | } | ||
3649 | |||
3650 | return 0; | ||
3651 | } | ||
3652 | |||
3373 | int qlcnic_validate_max_rss(struct qlcnic_adapter *adapter, | 3653 | int qlcnic_validate_max_rss(struct qlcnic_adapter *adapter, |
3374 | __u32 val) | 3654 | __u32 val) |
3375 | { | 3655 | { |
3376 | struct net_device *netdev = adapter->netdev; | 3656 | struct net_device *netdev = adapter->netdev; |
3377 | u8 max_hw = adapter->ahw->max_rx_ques; | 3657 | u8 max_hw = adapter->ahw->max_rx_ques; |
3378 | u32 max_allowed; | 3658 | u32 max_allowed; |
3379 | 3659 | ||
3380 | if (val > QLC_MAX_SDS_RINGS) { | 3660 | if (qlcnic_82xx_check(adapter) && !qlcnic_use_msi_x && |
3661 | !qlcnic_use_msi) { | ||
3662 | netdev_err(netdev, "No RSS support in INT-x mode\n"); | ||
3663 | return -EINVAL; | ||
3664 | } | ||
3665 | |||
3666 | if (val > QLCNIC_MAX_SDS_RINGS) { | ||
3381 | netdev_err(netdev, "RSS value should not be higher than %u\n", | 3667 | netdev_err(netdev, "RSS value should not be higher than %u\n", |
3382 | QLC_MAX_SDS_RINGS); | 3668 | QLCNIC_MAX_SDS_RINGS); |
3383 | return -EINVAL; | 3669 | return -EINVAL; |
3384 | } | 3670 | } |
3385 | 3671 | ||
@@ -3409,27 +3695,48 @@ int qlcnic_validate_max_rss(struct qlcnic_adapter *adapter, | |||
3409 | return 0; | 3695 | return 0; |
3410 | } | 3696 | } |
3411 | 3697 | ||
3412 | int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data, size_t len) | 3698 | int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data, int txq) |
3413 | { | 3699 | { |
3414 | int err; | 3700 | int err; |
3415 | struct net_device *netdev = adapter->netdev; | 3701 | struct net_device *netdev = adapter->netdev; |
3702 | int num_msix; | ||
3416 | 3703 | ||
3417 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) | 3704 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) |
3418 | return -EBUSY; | 3705 | return -EBUSY; |
3419 | 3706 | ||
3707 | if (qlcnic_82xx_check(adapter) && !qlcnic_use_msi_x && | ||
3708 | !qlcnic_use_msi) { | ||
3709 | netdev_err(netdev, "No RSS support in INT-x mode\n"); | ||
3710 | return -EINVAL; | ||
3711 | } | ||
3712 | |||
3420 | netif_device_detach(netdev); | 3713 | netif_device_detach(netdev); |
3421 | if (netif_running(netdev)) | 3714 | if (netif_running(netdev)) |
3422 | __qlcnic_down(adapter, netdev); | 3715 | __qlcnic_down(adapter, netdev); |
3423 | 3716 | ||
3424 | qlcnic_detach(adapter); | 3717 | qlcnic_detach(adapter); |
3425 | 3718 | ||
3719 | if (qlcnic_82xx_check(adapter)) { | ||
3720 | if (txq != 0) | ||
3721 | adapter->max_drv_tx_rings = txq; | ||
3722 | |||
3723 | if (qlcnic_check_multi_tx(adapter) && | ||
3724 | (txq > adapter->max_drv_tx_rings)) | ||
3725 | num_msix = adapter->max_drv_tx_rings; | ||
3726 | else | ||
3727 | num_msix = data; | ||
3728 | } | ||
3729 | |||
3426 | if (qlcnic_83xx_check(adapter)) { | 3730 | if (qlcnic_83xx_check(adapter)) { |
3427 | qlcnic_83xx_free_mbx_intr(adapter); | 3731 | qlcnic_83xx_free_mbx_intr(adapter); |
3428 | qlcnic_83xx_enable_mbx_poll(adapter); | 3732 | qlcnic_83xx_enable_mbx_poll(adapter); |
3429 | } | 3733 | } |
3430 | 3734 | ||
3735 | netif_set_real_num_tx_queues(netdev, adapter->max_drv_tx_rings); | ||
3736 | |||
3431 | qlcnic_teardown_intr(adapter); | 3737 | qlcnic_teardown_intr(adapter); |
3432 | err = qlcnic_setup_intr(adapter, data); | 3738 | |
3739 | err = qlcnic_setup_intr(adapter, data, txq); | ||
3433 | if (err) { | 3740 | if (err) { |
3434 | kfree(adapter->msix_entries); | 3741 | kfree(adapter->msix_entries); |
3435 | netdev_err(netdev, "failed to setup interrupt\n"); | 3742 | netdev_err(netdev, "failed to setup interrupt\n"); |
@@ -3457,8 +3764,7 @@ int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data, size_t len) | |||
3457 | goto done; | 3764 | goto done; |
3458 | qlcnic_restore_indev_addr(netdev, NETDEV_UP); | 3765 | qlcnic_restore_indev_addr(netdev, NETDEV_UP); |
3459 | } | 3766 | } |
3460 | err = len; | 3767 | done: |
3461 | done: | ||
3462 | netif_device_attach(netdev); | 3768 | netif_device_attach(netdev); |
3463 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 3769 | clear_bit(__QLCNIC_RESETTING, &adapter->state); |
3464 | return err; | 3770 | return err; |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c index 79e54efe07b9..15513608d480 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | |||
@@ -1082,14 +1082,17 @@ flash_temp: | |||
1082 | } | 1082 | } |
1083 | 1083 | ||
1084 | tmpl_hdr = ahw->fw_dump.tmpl_hdr; | 1084 | tmpl_hdr = ahw->fw_dump.tmpl_hdr; |
1085 | tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF; | 1085 | tmpl_hdr->drv_cap_mask = tmpl_hdr->cap_mask; |
1086 | dev_info(&adapter->pdev->dev, | ||
1087 | "Default minidump capture mask 0x%x\n", | ||
1088 | tmpl_hdr->cap_mask); | ||
1086 | 1089 | ||
1087 | if ((tmpl_hdr->version & 0xfffff) >= 0x20001) | 1090 | if ((tmpl_hdr->version & 0xfffff) >= 0x20001) |
1088 | ahw->fw_dump.use_pex_dma = true; | 1091 | ahw->fw_dump.use_pex_dma = true; |
1089 | else | 1092 | else |
1090 | ahw->fw_dump.use_pex_dma = false; | 1093 | ahw->fw_dump.use_pex_dma = false; |
1091 | 1094 | ||
1092 | ahw->fw_dump.enable = 1; | 1095 | qlcnic_enable_fw_dump_state(adapter); |
1093 | 1096 | ||
1094 | return 0; | 1097 | return 0; |
1095 | } | 1098 | } |
@@ -1112,7 +1115,11 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter) | |||
1112 | 1115 | ||
1113 | ahw = adapter->ahw; | 1116 | ahw = adapter->ahw; |
1114 | 1117 | ||
1115 | if (!fw_dump->enable) { | 1118 | /* Return if we don't have firmware dump template header */ |
1119 | if (!tmpl_hdr) | ||
1120 | return -EIO; | ||
1121 | |||
1122 | if (!qlcnic_check_fw_dump_state(adapter)) { | ||
1116 | dev_info(&adapter->pdev->dev, "Dump not enabled\n"); | 1123 | dev_info(&adapter->pdev->dev, "Dump not enabled\n"); |
1117 | return -EIO; | 1124 | return -EIO; |
1118 | } | 1125 | } |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c index 5d40045b3cea..652cc13c5023 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_common.c | |||
@@ -33,7 +33,7 @@ static int qlcnic_sriov_alloc_bc_mbx_args(struct qlcnic_cmd_args *, u32); | |||
33 | static void qlcnic_sriov_vf_poll_dev_state(struct work_struct *); | 33 | static void qlcnic_sriov_vf_poll_dev_state(struct work_struct *); |
34 | static void qlcnic_sriov_vf_cancel_fw_work(struct qlcnic_adapter *); | 34 | static void qlcnic_sriov_vf_cancel_fw_work(struct qlcnic_adapter *); |
35 | static void qlcnic_sriov_cleanup_transaction(struct qlcnic_bc_trans *); | 35 | static void qlcnic_sriov_cleanup_transaction(struct qlcnic_bc_trans *); |
36 | static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *, | 36 | static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *, |
37 | struct qlcnic_cmd_args *); | 37 | struct qlcnic_cmd_args *); |
38 | static void qlcnic_sriov_process_bc_cmd(struct work_struct *); | 38 | static void qlcnic_sriov_process_bc_cmd(struct work_struct *); |
39 | 39 | ||
@@ -45,7 +45,7 @@ static struct qlcnic_hardware_ops qlcnic_sriov_vf_hw_ops = { | |||
45 | .get_mac_address = qlcnic_83xx_get_mac_address, | 45 | .get_mac_address = qlcnic_83xx_get_mac_address, |
46 | .setup_intr = qlcnic_83xx_setup_intr, | 46 | .setup_intr = qlcnic_83xx_setup_intr, |
47 | .alloc_mbx_args = qlcnic_83xx_alloc_mbx_args, | 47 | .alloc_mbx_args = qlcnic_83xx_alloc_mbx_args, |
48 | .mbx_cmd = qlcnic_sriov_vf_mbx_op, | 48 | .mbx_cmd = qlcnic_sriov_issue_cmd, |
49 | .get_func_no = qlcnic_83xx_get_func_no, | 49 | .get_func_no = qlcnic_83xx_get_func_no, |
50 | .api_lock = qlcnic_83xx_cam_lock, | 50 | .api_lock = qlcnic_83xx_cam_lock, |
51 | .api_unlock = qlcnic_83xx_cam_unlock, | 51 | .api_unlock = qlcnic_83xx_cam_unlock, |
@@ -286,96 +286,38 @@ void qlcnic_sriov_cleanup(struct qlcnic_adapter *adapter) | |||
286 | static int qlcnic_sriov_post_bc_msg(struct qlcnic_adapter *adapter, u32 *hdr, | 286 | static int qlcnic_sriov_post_bc_msg(struct qlcnic_adapter *adapter, u32 *hdr, |
287 | u32 *pay, u8 pci_func, u8 size) | 287 | u32 *pay, u8 pci_func, u8 size) |
288 | { | 288 | { |
289 | u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, val, wait_time = 0; | ||
290 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 289 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
291 | unsigned long flags; | 290 | struct qlcnic_mailbox *mbx = ahw->mailbox; |
292 | u16 opcode; | 291 | struct qlcnic_cmd_args cmd; |
293 | u8 mbx_err_code; | 292 | unsigned long timeout; |
294 | int i, j; | 293 | int err; |
295 | |||
296 | opcode = ((struct qlcnic_bc_hdr *)hdr)->cmd_op; | ||
297 | |||
298 | if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) { | ||
299 | dev_info(&adapter->pdev->dev, | ||
300 | "Mailbox cmd attempted, 0x%x\n", opcode); | ||
301 | dev_info(&adapter->pdev->dev, "Mailbox detached\n"); | ||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | spin_lock_irqsave(&ahw->mbx_lock, flags); | ||
306 | |||
307 | mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL); | ||
308 | if (mbx_val) { | ||
309 | QLCDB(adapter, DRV, "Mailbox cmd attempted, 0x%x\n", opcode); | ||
310 | spin_unlock_irqrestore(&ahw->mbx_lock, flags); | ||
311 | return QLCNIC_RCODE_TIMEOUT; | ||
312 | } | ||
313 | /* Fill in mailbox registers */ | ||
314 | val = size + (sizeof(struct qlcnic_bc_hdr) / sizeof(u32)); | ||
315 | mbx_cmd = 0x31 | (val << 16) | (adapter->ahw->fw_hal_version << 29); | ||
316 | |||
317 | writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0)); | ||
318 | mbx_cmd = 0x1 | (1 << 4); | ||
319 | 294 | ||
320 | if (qlcnic_sriov_pf_check(adapter)) | 295 | memset(&cmd, 0, sizeof(struct qlcnic_cmd_args)); |
321 | mbx_cmd |= (pci_func << 5); | 296 | cmd.hdr = hdr; |
297 | cmd.pay = pay; | ||
298 | cmd.pay_size = size; | ||
299 | cmd.func_num = pci_func; | ||
300 | cmd.op_type = QLC_83XX_MBX_POST_BC_OP; | ||
301 | cmd.cmd_op = ((struct qlcnic_bc_hdr *)hdr)->cmd_op; | ||
322 | 302 | ||
323 | writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 1)); | 303 | err = mbx->ops->enqueue_cmd(adapter, &cmd, &timeout); |
324 | for (i = 2, j = 0; j < (sizeof(struct qlcnic_bc_hdr) / sizeof(u32)); | 304 | if (err) { |
325 | i++, j++) { | 305 | dev_err(&adapter->pdev->dev, |
326 | writel(*(hdr++), QLCNIC_MBX_HOST(ahw, i)); | 306 | "%s: Mailbox not available, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n", |
307 | __func__, cmd.cmd_op, cmd.type, ahw->pci_func, | ||
308 | ahw->op_mode); | ||
309 | return err; | ||
327 | } | 310 | } |
328 | for (j = 0; j < size; j++, i++) | ||
329 | writel(*(pay++), QLCNIC_MBX_HOST(ahw, i)); | ||
330 | 311 | ||
331 | /* Signal FW about the impending command */ | 312 | if (!wait_for_completion_timeout(&cmd.completion, timeout)) { |
332 | QLCWRX(ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER); | 313 | dev_err(&adapter->pdev->dev, |
333 | 314 | "%s: Mailbox command timed out, cmd_op=0x%x, cmd_type=0x%x, pci_func=0x%x, op_mode=0x%x\n", | |
334 | /* Waiting for the mailbox cmd to complete and while waiting here | 315 | __func__, cmd.cmd_op, cmd.type, ahw->pci_func, |
335 | * some AEN might arrive. If more than 5 seconds expire we can | 316 | ahw->op_mode); |
336 | * assume something is wrong. | 317 | flush_workqueue(mbx->work_q); |
337 | */ | ||
338 | poll: | ||
339 | rsp = qlcnic_83xx_mbx_poll(adapter, &wait_time); | ||
340 | if (rsp != QLCNIC_RCODE_TIMEOUT) { | ||
341 | /* Get the FW response data */ | ||
342 | fw_data = readl(QLCNIC_MBX_FW(ahw, 0)); | ||
343 | if (fw_data & QLCNIC_MBX_ASYNC_EVENT) { | ||
344 | __qlcnic_83xx_process_aen(adapter); | ||
345 | goto poll; | ||
346 | } | ||
347 | mbx_err_code = QLCNIC_MBX_STATUS(fw_data); | ||
348 | rsp_num = QLCNIC_MBX_NUM_REGS(fw_data); | ||
349 | opcode = QLCNIC_MBX_RSP(fw_data); | ||
350 | |||
351 | switch (mbx_err_code) { | ||
352 | case QLCNIC_MBX_RSP_OK: | ||
353 | case QLCNIC_MBX_PORT_RSP_OK: | ||
354 | rsp = QLCNIC_RCODE_SUCCESS; | ||
355 | break; | ||
356 | default: | ||
357 | if (opcode == QLCNIC_CMD_CONFIG_MAC_VLAN) { | ||
358 | rsp = qlcnic_83xx_mac_rcode(adapter); | ||
359 | if (!rsp) | ||
360 | goto out; | ||
361 | } | ||
362 | dev_err(&adapter->pdev->dev, | ||
363 | "MBX command 0x%x failed with err:0x%x\n", | ||
364 | opcode, mbx_err_code); | ||
365 | rsp = mbx_err_code; | ||
366 | break; | ||
367 | } | ||
368 | goto out; | ||
369 | } | 318 | } |
370 | 319 | ||
371 | dev_err(&adapter->pdev->dev, "MBX command 0x%x timed out\n", | 320 | return cmd.rsp_opcode; |
372 | QLCNIC_MBX_RSP(mbx_cmd)); | ||
373 | rsp = QLCNIC_RCODE_TIMEOUT; | ||
374 | out: | ||
375 | /* clear fw mbx control register */ | ||
376 | QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER); | ||
377 | spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags); | ||
378 | return rsp; | ||
379 | } | 321 | } |
380 | 322 | ||
381 | static void qlcnic_sriov_vf_cfg_buff_desc(struct qlcnic_adapter *adapter) | 323 | static void qlcnic_sriov_vf_cfg_buff_desc(struct qlcnic_adapter *adapter) |
@@ -458,7 +400,7 @@ int qlcnic_sriov_get_vf_vport_info(struct qlcnic_adapter *adapter, | |||
458 | static int qlcnic_sriov_set_pvid_mode(struct qlcnic_adapter *adapter, | 400 | static int qlcnic_sriov_set_pvid_mode(struct qlcnic_adapter *adapter, |
459 | struct qlcnic_cmd_args *cmd) | 401 | struct qlcnic_cmd_args *cmd) |
460 | { | 402 | { |
461 | adapter->rx_pvid = (cmd->rsp.arg[1] >> 16) & 0xffff; | 403 | adapter->rx_pvid = MSW(cmd->rsp.arg[1]) & 0xffff; |
462 | adapter->flags &= ~QLCNIC_TAGGING_ENABLED; | 404 | adapter->flags &= ~QLCNIC_TAGGING_ENABLED; |
463 | return 0; | 405 | return 0; |
464 | } | 406 | } |
@@ -490,11 +432,12 @@ static int qlcnic_sriov_set_guest_vlan_mode(struct qlcnic_adapter *adapter, | |||
490 | return 0; | 432 | return 0; |
491 | } | 433 | } |
492 | 434 | ||
493 | static int qlcnic_sriov_get_vf_acl(struct qlcnic_adapter *adapter) | 435 | static int qlcnic_sriov_get_vf_acl(struct qlcnic_adapter *adapter, |
436 | struct qlcnic_info *info) | ||
494 | { | 437 | { |
495 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; | 438 | struct qlcnic_sriov *sriov = adapter->ahw->sriov; |
496 | struct qlcnic_cmd_args cmd; | 439 | struct qlcnic_cmd_args cmd; |
497 | int ret; | 440 | int ret = 0; |
498 | 441 | ||
499 | ret = qlcnic_sriov_alloc_bc_mbx_args(&cmd, QLCNIC_BC_CMD_GET_ACL); | 442 | ret = qlcnic_sriov_alloc_bc_mbx_args(&cmd, QLCNIC_BC_CMD_GET_ACL); |
500 | if (ret) | 443 | if (ret) |
@@ -522,8 +465,8 @@ static int qlcnic_sriov_get_vf_acl(struct qlcnic_adapter *adapter) | |||
522 | 465 | ||
523 | static int qlcnic_sriov_vf_init_driver(struct qlcnic_adapter *adapter) | 466 | static int qlcnic_sriov_vf_init_driver(struct qlcnic_adapter *adapter) |
524 | { | 467 | { |
525 | struct qlcnic_info nic_info; | ||
526 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 468 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
469 | struct qlcnic_info nic_info; | ||
527 | int err; | 470 | int err; |
528 | 471 | ||
529 | err = qlcnic_sriov_get_vf_vport_info(adapter, &nic_info, 0); | 472 | err = qlcnic_sriov_get_vf_vport_info(adapter, &nic_info, 0); |
@@ -534,7 +477,7 @@ static int qlcnic_sriov_vf_init_driver(struct qlcnic_adapter *adapter) | |||
534 | if (err) | 477 | if (err) |
535 | return -EIO; | 478 | return -EIO; |
536 | 479 | ||
537 | err = qlcnic_sriov_get_vf_acl(adapter); | 480 | err = qlcnic_sriov_get_vf_acl(adapter, &nic_info); |
538 | if (err) | 481 | if (err) |
539 | return err; | 482 | return err; |
540 | 483 | ||
@@ -564,7 +507,7 @@ static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter, | |||
564 | dev_warn(&adapter->pdev->dev, | 507 | dev_warn(&adapter->pdev->dev, |
565 | "Device does not support MSI interrupts\n"); | 508 | "Device does not support MSI interrupts\n"); |
566 | 509 | ||
567 | err = qlcnic_setup_intr(adapter, 1); | 510 | err = qlcnic_setup_intr(adapter, 1, 0); |
568 | if (err) { | 511 | if (err) { |
569 | dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n"); | 512 | dev_err(&adapter->pdev->dev, "Failed to setup interrupt\n"); |
570 | goto err_out_disable_msi; | 513 | goto err_out_disable_msi; |
@@ -590,6 +533,9 @@ static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter, | |||
590 | if (err) | 533 | if (err) |
591 | goto err_out_send_channel_term; | 534 | goto err_out_send_channel_term; |
592 | 535 | ||
536 | if (adapter->dcb && qlcnic_dcb_attach(adapter)) | ||
537 | qlcnic_clear_dcb_ops(adapter); | ||
538 | |||
593 | err = qlcnic_setup_netdev(adapter, adapter->netdev, pci_using_dac); | 539 | err = qlcnic_setup_netdev(adapter, adapter->netdev, pci_using_dac); |
594 | if (err) | 540 | if (err) |
595 | goto err_out_send_channel_term; | 541 | goto err_out_send_channel_term; |
@@ -597,6 +543,7 @@ static int qlcnic_sriov_setup_vf(struct qlcnic_adapter *adapter, | |||
597 | pci_set_drvdata(adapter->pdev, adapter); | 543 | pci_set_drvdata(adapter->pdev, adapter); |
598 | dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n", | 544 | dev_info(&adapter->pdev->dev, "%s: XGbE port initialized\n", |
599 | adapter->netdev->name); | 545 | adapter->netdev->name); |
546 | |||
600 | qlcnic_schedule_work(adapter, qlcnic_sriov_vf_poll_dev_state, | 547 | qlcnic_schedule_work(adapter, qlcnic_sriov_vf_poll_dev_state, |
601 | adapter->ahw->idc.delay); | 548 | adapter->ahw->idc.delay); |
602 | return 0; | 549 | return 0; |
@@ -637,8 +584,6 @@ int qlcnic_sriov_vf_init(struct qlcnic_adapter *adapter, int pci_using_dac) | |||
637 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 584 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
638 | int err; | 585 | int err; |
639 | 586 | ||
640 | spin_lock_init(&ahw->mbx_lock); | ||
641 | set_bit(QLC_83XX_MBX_READY, &ahw->idc.status); | ||
642 | set_bit(QLC_83XX_MODULE_LOADED, &ahw->idc.status); | 587 | set_bit(QLC_83XX_MODULE_LOADED, &ahw->idc.status); |
643 | ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY; | 588 | ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY; |
644 | ahw->reset_context = 0; | 589 | ahw->reset_context = 0; |
@@ -1085,6 +1030,7 @@ static void qlcnic_sriov_process_bc_cmd(struct work_struct *work) | |||
1085 | if (test_bit(QLC_BC_VF_FLR, &vf->state)) | 1030 | if (test_bit(QLC_BC_VF_FLR, &vf->state)) |
1086 | return; | 1031 | return; |
1087 | 1032 | ||
1033 | memset(&cmd, 0, sizeof(struct qlcnic_cmd_args)); | ||
1088 | trans = list_first_entry(&vf->rcv_act.wait_list, | 1034 | trans = list_first_entry(&vf->rcv_act.wait_list, |
1089 | struct qlcnic_bc_trans, list); | 1035 | struct qlcnic_bc_trans, list); |
1090 | adapter = vf->adapter; | 1036 | adapter = vf->adapter; |
@@ -1234,6 +1180,7 @@ static void qlcnic_sriov_handle_bc_cmd(struct qlcnic_sriov *sriov, | |||
1234 | return; | 1180 | return; |
1235 | } | 1181 | } |
1236 | 1182 | ||
1183 | memset(&cmd, 0, sizeof(struct qlcnic_cmd_args)); | ||
1237 | cmd_op = hdr->cmd_op; | 1184 | cmd_op = hdr->cmd_op; |
1238 | if (qlcnic_sriov_alloc_bc_trans(&trans)) | 1185 | if (qlcnic_sriov_alloc_bc_trans(&trans)) |
1239 | return; | 1186 | return; |
@@ -1359,7 +1306,7 @@ int qlcnic_sriov_cfg_bc_intr(struct qlcnic_adapter *adapter, u8 enable) | |||
1359 | if (enable) | 1306 | if (enable) |
1360 | cmd.req.arg[1] = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7); | 1307 | cmd.req.arg[1] = (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7); |
1361 | 1308 | ||
1362 | err = qlcnic_83xx_mbx_op(adapter, &cmd); | 1309 | err = qlcnic_83xx_issue_cmd(adapter, &cmd); |
1363 | 1310 | ||
1364 | if (err != QLCNIC_RCODE_SUCCESS) { | 1311 | if (err != QLCNIC_RCODE_SUCCESS) { |
1365 | dev_err(&adapter->pdev->dev, | 1312 | dev_err(&adapter->pdev->dev, |
@@ -1391,10 +1338,11 @@ static int qlcnic_sriov_retry_bc_cmd(struct qlcnic_adapter *adapter, | |||
1391 | return -EIO; | 1338 | return -EIO; |
1392 | } | 1339 | } |
1393 | 1340 | ||
1394 | static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *adapter, | 1341 | static int qlcnic_sriov_issue_cmd(struct qlcnic_adapter *adapter, |
1395 | struct qlcnic_cmd_args *cmd) | 1342 | struct qlcnic_cmd_args *cmd) |
1396 | { | 1343 | { |
1397 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 1344 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
1345 | struct qlcnic_mailbox *mbx = ahw->mailbox; | ||
1398 | struct device *dev = &adapter->pdev->dev; | 1346 | struct device *dev = &adapter->pdev->dev; |
1399 | struct qlcnic_bc_trans *trans; | 1347 | struct qlcnic_bc_trans *trans; |
1400 | int err; | 1348 | int err; |
@@ -1411,7 +1359,7 @@ static int qlcnic_sriov_vf_mbx_op(struct qlcnic_adapter *adapter, | |||
1411 | goto cleanup_transaction; | 1359 | goto cleanup_transaction; |
1412 | 1360 | ||
1413 | retry: | 1361 | retry: |
1414 | if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) { | 1362 | if (!test_bit(QLC_83XX_MBX_READY, &mbx->status)) { |
1415 | rsp = -EIO; | 1363 | rsp = -EIO; |
1416 | QLCDB(adapter, DRV, "MBX not Ready!(cmd 0x%x) for VF 0x%x\n", | 1364 | QLCDB(adapter, DRV, "MBX not Ready!(cmd 0x%x) for VF 0x%x\n", |
1417 | QLCNIC_MBX_RSP(cmd->req.arg[0]), func); | 1365 | QLCNIC_MBX_RSP(cmd->req.arg[0]), func); |
@@ -1454,7 +1402,7 @@ err_out: | |||
1454 | if (rsp == QLCNIC_RCODE_TIMEOUT) { | 1402 | if (rsp == QLCNIC_RCODE_TIMEOUT) { |
1455 | ahw->reset_context = 1; | 1403 | ahw->reset_context = 1; |
1456 | adapter->need_fw_reset = 1; | 1404 | adapter->need_fw_reset = 1; |
1457 | clear_bit(QLC_83XX_MBX_READY, &ahw->idc.status); | 1405 | clear_bit(QLC_83XX_MBX_READY, &mbx->status); |
1458 | } | 1406 | } |
1459 | 1407 | ||
1460 | cleanup_transaction: | 1408 | cleanup_transaction: |
@@ -1613,8 +1561,8 @@ static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter) | |||
1613 | { | 1561 | { |
1614 | int err; | 1562 | int err; |
1615 | 1563 | ||
1616 | set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); | 1564 | qlcnic_83xx_reinit_mbx_work(adapter->ahw->mailbox); |
1617 | qlcnic_83xx_enable_mbx_intrpt(adapter); | 1565 | qlcnic_83xx_enable_mbx_interrupt(adapter); |
1618 | 1566 | ||
1619 | err = qlcnic_sriov_cfg_bc_intr(adapter, 1); | 1567 | err = qlcnic_sriov_cfg_bc_intr(adapter, 1); |
1620 | if (err) | 1568 | if (err) |
@@ -1628,6 +1576,8 @@ static int qlcnic_sriov_vf_reinit_driver(struct qlcnic_adapter *adapter) | |||
1628 | if (err) | 1576 | if (err) |
1629 | goto err_out_term_channel; | 1577 | goto err_out_term_channel; |
1630 | 1578 | ||
1579 | qlcnic_dcb_get_info(adapter); | ||
1580 | |||
1631 | return 0; | 1581 | return 0; |
1632 | 1582 | ||
1633 | err_out_term_channel: | 1583 | err_out_term_channel: |
@@ -1657,8 +1607,10 @@ static void qlcnic_sriov_vf_detach(struct qlcnic_adapter *adapter) | |||
1657 | struct net_device *netdev = adapter->netdev; | 1607 | struct net_device *netdev = adapter->netdev; |
1658 | u8 i, max_ints = ahw->num_msix - 1; | 1608 | u8 i, max_ints = ahw->num_msix - 1; |
1659 | 1609 | ||
1660 | qlcnic_83xx_disable_mbx_intr(adapter); | ||
1661 | netif_device_detach(netdev); | 1610 | netif_device_detach(netdev); |
1611 | qlcnic_83xx_detach_mailbox_work(adapter); | ||
1612 | qlcnic_83xx_disable_mbx_intr(adapter); | ||
1613 | |||
1662 | if (netif_running(netdev)) | 1614 | if (netif_running(netdev)) |
1663 | qlcnic_down(adapter, netdev); | 1615 | qlcnic_down(adapter, netdev); |
1664 | 1616 | ||
@@ -1702,6 +1654,7 @@ static int qlcnic_sriov_vf_handle_dev_ready(struct qlcnic_adapter *adapter) | |||
1702 | static int qlcnic_sriov_vf_handle_context_reset(struct qlcnic_adapter *adapter) | 1654 | static int qlcnic_sriov_vf_handle_context_reset(struct qlcnic_adapter *adapter) |
1703 | { | 1655 | { |
1704 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 1656 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
1657 | struct qlcnic_mailbox *mbx = ahw->mailbox; | ||
1705 | struct device *dev = &adapter->pdev->dev; | 1658 | struct device *dev = &adapter->pdev->dev; |
1706 | struct qlc_83xx_idc *idc = &ahw->idc; | 1659 | struct qlc_83xx_idc *idc = &ahw->idc; |
1707 | u8 func = ahw->pci_func; | 1660 | u8 func = ahw->pci_func; |
@@ -1712,7 +1665,7 @@ static int qlcnic_sriov_vf_handle_context_reset(struct qlcnic_adapter *adapter) | |||
1712 | /* Skip the context reset and check if FW is hung */ | 1665 | /* Skip the context reset and check if FW is hung */ |
1713 | if (adapter->reset_ctx_cnt < 3) { | 1666 | if (adapter->reset_ctx_cnt < 3) { |
1714 | adapter->need_fw_reset = 1; | 1667 | adapter->need_fw_reset = 1; |
1715 | clear_bit(QLC_83XX_MBX_READY, &idc->status); | 1668 | clear_bit(QLC_83XX_MBX_READY, &mbx->status); |
1716 | dev_info(dev, | 1669 | dev_info(dev, |
1717 | "Resetting context, wait here to check if FW is in failed state\n"); | 1670 | "Resetting context, wait here to check if FW is in failed state\n"); |
1718 | return 0; | 1671 | return 0; |
@@ -1737,7 +1690,7 @@ static int qlcnic_sriov_vf_handle_context_reset(struct qlcnic_adapter *adapter) | |||
1737 | __func__, adapter->reset_ctx_cnt, func); | 1690 | __func__, adapter->reset_ctx_cnt, func); |
1738 | set_bit(__QLCNIC_RESETTING, &adapter->state); | 1691 | set_bit(__QLCNIC_RESETTING, &adapter->state); |
1739 | adapter->need_fw_reset = 1; | 1692 | adapter->need_fw_reset = 1; |
1740 | clear_bit(QLC_83XX_MBX_READY, &idc->status); | 1693 | clear_bit(QLC_83XX_MBX_READY, &mbx->status); |
1741 | qlcnic_sriov_vf_detach(adapter); | 1694 | qlcnic_sriov_vf_detach(adapter); |
1742 | adapter->need_fw_reset = 0; | 1695 | adapter->need_fw_reset = 0; |
1743 | 1696 | ||
@@ -1787,6 +1740,7 @@ static int qlcnic_sriov_vf_idc_failed_state(struct qlcnic_adapter *adapter) | |||
1787 | static int | 1740 | static int |
1788 | qlcnic_sriov_vf_idc_need_quiescent_state(struct qlcnic_adapter *adapter) | 1741 | qlcnic_sriov_vf_idc_need_quiescent_state(struct qlcnic_adapter *adapter) |
1789 | { | 1742 | { |
1743 | struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; | ||
1790 | struct qlc_83xx_idc *idc = &adapter->ahw->idc; | 1744 | struct qlc_83xx_idc *idc = &adapter->ahw->idc; |
1791 | 1745 | ||
1792 | dev_info(&adapter->pdev->dev, "Device is in quiescent state\n"); | 1746 | dev_info(&adapter->pdev->dev, "Device is in quiescent state\n"); |
@@ -1794,7 +1748,7 @@ qlcnic_sriov_vf_idc_need_quiescent_state(struct qlcnic_adapter *adapter) | |||
1794 | set_bit(__QLCNIC_RESETTING, &adapter->state); | 1748 | set_bit(__QLCNIC_RESETTING, &adapter->state); |
1795 | adapter->tx_timeo_cnt = 0; | 1749 | adapter->tx_timeo_cnt = 0; |
1796 | adapter->reset_ctx_cnt = 0; | 1750 | adapter->reset_ctx_cnt = 0; |
1797 | clear_bit(QLC_83XX_MBX_READY, &idc->status); | 1751 | clear_bit(QLC_83XX_MBX_READY, &mbx->status); |
1798 | qlcnic_sriov_vf_detach(adapter); | 1752 | qlcnic_sriov_vf_detach(adapter); |
1799 | } | 1753 | } |
1800 | 1754 | ||
@@ -1803,6 +1757,7 @@ qlcnic_sriov_vf_idc_need_quiescent_state(struct qlcnic_adapter *adapter) | |||
1803 | 1757 | ||
1804 | static int qlcnic_sriov_vf_idc_init_reset_state(struct qlcnic_adapter *adapter) | 1758 | static int qlcnic_sriov_vf_idc_init_reset_state(struct qlcnic_adapter *adapter) |
1805 | { | 1759 | { |
1760 | struct qlcnic_mailbox *mbx = adapter->ahw->mailbox; | ||
1806 | struct qlc_83xx_idc *idc = &adapter->ahw->idc; | 1761 | struct qlc_83xx_idc *idc = &adapter->ahw->idc; |
1807 | u8 func = adapter->ahw->pci_func; | 1762 | u8 func = adapter->ahw->pci_func; |
1808 | 1763 | ||
@@ -1812,7 +1767,7 @@ static int qlcnic_sriov_vf_idc_init_reset_state(struct qlcnic_adapter *adapter) | |||
1812 | set_bit(__QLCNIC_RESETTING, &adapter->state); | 1767 | set_bit(__QLCNIC_RESETTING, &adapter->state); |
1813 | adapter->tx_timeo_cnt = 0; | 1768 | adapter->tx_timeo_cnt = 0; |
1814 | adapter->reset_ctx_cnt = 0; | 1769 | adapter->reset_ctx_cnt = 0; |
1815 | clear_bit(QLC_83XX_MBX_READY, &idc->status); | 1770 | clear_bit(QLC_83XX_MBX_READY, &mbx->status); |
1816 | qlcnic_sriov_vf_detach(adapter); | 1771 | qlcnic_sriov_vf_detach(adapter); |
1817 | } | 1772 | } |
1818 | return 0; | 1773 | return 0; |
@@ -1990,7 +1945,7 @@ int qlcnic_sriov_vf_resume(struct qlcnic_adapter *adapter) | |||
1990 | int err; | 1945 | int err; |
1991 | 1946 | ||
1992 | set_bit(QLC_83XX_MODULE_LOADED, &idc->status); | 1947 | set_bit(QLC_83XX_MODULE_LOADED, &idc->status); |
1993 | qlcnic_83xx_enable_mbx_intrpt(adapter); | 1948 | qlcnic_83xx_enable_mbx_interrupt(adapter); |
1994 | err = qlcnic_sriov_cfg_bc_intr(adapter, 1); | 1949 | err = qlcnic_sriov_cfg_bc_intr(adapter, 1); |
1995 | if (err) | 1950 | if (err) |
1996 | return err; | 1951 | return err; |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c index eb49cd65378c..330d9a8774ad 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sriov_pf.c | |||
@@ -1183,10 +1183,19 @@ static int qlcnic_sriov_pf_get_acl_cmd(struct qlcnic_bc_trans *trans, | |||
1183 | struct qlcnic_vf_info *vf = trans->vf; | 1183 | struct qlcnic_vf_info *vf = trans->vf; |
1184 | struct qlcnic_vport *vp = vf->vp; | 1184 | struct qlcnic_vport *vp = vf->vp; |
1185 | u8 cmd_op, mode = vp->vlan_mode; | 1185 | u8 cmd_op, mode = vp->vlan_mode; |
1186 | struct qlcnic_adapter *adapter; | ||
1187 | |||
1188 | adapter = vf->adapter; | ||
1186 | 1189 | ||
1187 | cmd_op = trans->req_hdr->cmd_op; | 1190 | cmd_op = trans->req_hdr->cmd_op; |
1188 | cmd->rsp.arg[0] |= 1 << 25; | 1191 | cmd->rsp.arg[0] |= 1 << 25; |
1189 | 1192 | ||
1193 | /* For 84xx adapter in case of PVID , PFD should send vlan mode as | ||
1194 | * QLC_NO_VLAN_MODE to VFD which is zero in mailbox response | ||
1195 | */ | ||
1196 | if (qlcnic_84xx_check(adapter) && mode == QLC_PVID_MODE) | ||
1197 | return 0; | ||
1198 | |||
1190 | switch (mode) { | 1199 | switch (mode) { |
1191 | case QLC_GUEST_VLAN_MODE: | 1200 | case QLC_GUEST_VLAN_MODE: |
1192 | cmd->rsp.arg[1] = mode | 1 << 8; | 1201 | cmd->rsp.arg[1] = mode | 1 << 8; |
@@ -1284,6 +1293,10 @@ static const int qlcnic_pf_passthru_supp_cmds[] = { | |||
1284 | QLCNIC_CMD_GET_STATISTICS, | 1293 | QLCNIC_CMD_GET_STATISTICS, |
1285 | QLCNIC_CMD_GET_PORT_CONFIG, | 1294 | QLCNIC_CMD_GET_PORT_CONFIG, |
1286 | QLCNIC_CMD_GET_LINK_STATUS, | 1295 | QLCNIC_CMD_GET_LINK_STATUS, |
1296 | QLCNIC_CMD_DCB_QUERY_CAP, | ||
1297 | QLCNIC_CMD_DCB_QUERY_PARAM, | ||
1298 | QLCNIC_CMD_INIT_NIC_FUNC, | ||
1299 | QLCNIC_CMD_STOP_NIC_FUNC, | ||
1287 | }; | 1300 | }; |
1288 | 1301 | ||
1289 | static const struct qlcnic_sriov_cmd_handler qlcnic_pf_bc_cmd_hdlr[] = { | 1302 | static const struct qlcnic_sriov_cmd_handler qlcnic_pf_bc_cmd_hdlr[] = { |
@@ -1639,14 +1652,14 @@ int qlcnic_sriov_set_vf_mac(struct net_device *netdev, int vf, u8 *mac) | |||
1639 | if (!is_valid_ether_addr(mac) || vf >= num_vfs) | 1652 | if (!is_valid_ether_addr(mac) || vf >= num_vfs) |
1640 | return -EINVAL; | 1653 | return -EINVAL; |
1641 | 1654 | ||
1642 | if (!compare_ether_addr(adapter->mac_addr, mac)) { | 1655 | if (ether_addr_equal(adapter->mac_addr, mac)) { |
1643 | netdev_err(netdev, "MAC address is already in use by the PF\n"); | 1656 | netdev_err(netdev, "MAC address is already in use by the PF\n"); |
1644 | return -EINVAL; | 1657 | return -EINVAL; |
1645 | } | 1658 | } |
1646 | 1659 | ||
1647 | for (i = 0; i < num_vfs; i++) { | 1660 | for (i = 0; i < num_vfs; i++) { |
1648 | vf_info = &sriov->vf_info[i]; | 1661 | vf_info = &sriov->vf_info[i]; |
1649 | if (!compare_ether_addr(vf_info->vp->mac, mac)) { | 1662 | if (ether_addr_equal(vf_info->vp->mac, mac)) { |
1650 | netdev_err(netdev, | 1663 | netdev_err(netdev, |
1651 | "MAC address is already in use by VF %d\n", | 1664 | "MAC address is already in use by VF %d\n", |
1652 | i); | 1665 | i); |
@@ -1768,8 +1781,8 @@ int qlcnic_sriov_set_vf_vlan(struct net_device *netdev, int vf, | |||
1768 | return 0; | 1781 | return 0; |
1769 | } | 1782 | } |
1770 | 1783 | ||
1771 | static inline __u32 qlcnic_sriov_get_vf_vlan(struct qlcnic_adapter *adapter, | 1784 | static __u32 qlcnic_sriov_get_vf_vlan(struct qlcnic_adapter *adapter, |
1772 | struct qlcnic_vport *vp, int vf) | 1785 | struct qlcnic_vport *vp, int vf) |
1773 | { | 1786 | { |
1774 | __u32 vlan = 0; | 1787 | __u32 vlan = 0; |
1775 | 1788 | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c index 660c3f5b2237..c6165d05cc13 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | |||
@@ -465,8 +465,14 @@ static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp, | |||
465 | memset(&pm_cfg, 0, | 465 | memset(&pm_cfg, 0, |
466 | sizeof(struct qlcnic_pm_func_cfg) * QLCNIC_MAX_PCI_FUNC); | 466 | sizeof(struct qlcnic_pm_func_cfg) * QLCNIC_MAX_PCI_FUNC); |
467 | 467 | ||
468 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { | 468 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { |
469 | pci_func = adapter->npars[i].pci_func; | 469 | pci_func = adapter->npars[i].pci_func; |
470 | if (!adapter->npars[i].active) | ||
471 | continue; | ||
472 | |||
473 | if (!adapter->npars[i].eswitch_status) | ||
474 | continue; | ||
475 | |||
470 | pm_cfg[pci_func].action = adapter->npars[i].enable_pm; | 476 | pm_cfg[pci_func].action = adapter->npars[i].enable_pm; |
471 | pm_cfg[pci_func].dest_npar = 0; | 477 | pm_cfg[pci_func].dest_npar = 0; |
472 | pm_cfg[pci_func].pci_func = i; | 478 | pm_cfg[pci_func].pci_func = i; |
@@ -632,8 +638,14 @@ static ssize_t qlcnic_sysfs_read_esw_config(struct file *file, | |||
632 | memset(&esw_cfg, 0, | 638 | memset(&esw_cfg, 0, |
633 | sizeof(struct qlcnic_esw_func_cfg) * QLCNIC_MAX_PCI_FUNC); | 639 | sizeof(struct qlcnic_esw_func_cfg) * QLCNIC_MAX_PCI_FUNC); |
634 | 640 | ||
635 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { | 641 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { |
636 | pci_func = adapter->npars[i].pci_func; | 642 | pci_func = adapter->npars[i].pci_func; |
643 | if (!adapter->npars[i].active) | ||
644 | continue; | ||
645 | |||
646 | if (!adapter->npars[i].eswitch_status) | ||
647 | continue; | ||
648 | |||
637 | esw_cfg[pci_func].pci_func = pci_func; | 649 | esw_cfg[pci_func].pci_func = pci_func; |
638 | if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[pci_func])) | 650 | if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[pci_func])) |
639 | return QL_STATUS_INVALID_PARAM; | 651 | return QL_STATUS_INVALID_PARAM; |
@@ -732,6 +744,9 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file, | |||
732 | if (ret) | 744 | if (ret) |
733 | return ret; | 745 | return ret; |
734 | 746 | ||
747 | if (!adapter->npars[i].eswitch_status) | ||
748 | continue; | ||
749 | |||
735 | np_cfg[i].pci_func = i; | 750 | np_cfg[i].pci_func = i; |
736 | np_cfg[i].op_mode = (u8)nic_info.op_mode; | 751 | np_cfg[i].op_mode = (u8)nic_info.op_mode; |
737 | np_cfg[i].port_num = nic_info.phys_port; | 752 | np_cfg[i].port_num = nic_info.phys_port; |
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge.h b/drivers/net/ethernet/qlogic/qlge/qlge.h index 7e8d68263963..899433778466 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge.h +++ b/drivers/net/ethernet/qlogic/qlge/qlge.h | |||
@@ -2149,7 +2149,7 @@ struct ql_adapter { | |||
2149 | struct timer_list timer; | 2149 | struct timer_list timer; |
2150 | atomic_t lb_count; | 2150 | atomic_t lb_count; |
2151 | /* Keep local copy of current mac address. */ | 2151 | /* Keep local copy of current mac address. */ |
2152 | char current_mac_addr[6]; | 2152 | char current_mac_addr[ETH_ALEN]; |
2153 | }; | 2153 | }; |
2154 | 2154 | ||
2155 | /* | 2155 | /* |