diff options
author | Sony Chacko <sony.chacko@qlogic.com> | 2012-12-31 22:20:19 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-01-02 05:43:26 -0500 |
commit | 7f9664525f9cb507de9198a395a111371413f230 (patch) | |
tree | 3afa3c469348de2847dc2e82a2dfa9583c2fb617 /drivers/net/ethernet/qlogic/qlcnic | |
parent | a15ebd371992dbadb8a30367fd80cb5cd73b8fb1 (diff) |
qlcnic: 83xx memory map and HW access routines
83xx adapter register map.
83xx hardware interface routines.
Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: Anirban Chakraborty <anirban.chakraborty@qlogic.com>
Signed-off-by: Sritej Velaga <sritej.velaga@qlogic.com>
Signed-off-by: Sony Chacko <sony.chacko@qlogic.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/qlogic/qlcnic')
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | 76 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | 1719 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | 250 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | 47 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h | 17 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 2 |
9 files changed, 2094 insertions, 32 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile index c4b8ced83829..f8d85aec26b7 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/Makefile +++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile | |||
@@ -6,4 +6,4 @@ obj-$(CONFIG_QLCNIC) := qlcnic.o | |||
6 | 6 | ||
7 | qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \ | 7 | qlcnic-y := qlcnic_hw.o qlcnic_main.o qlcnic_init.o \ |
8 | qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o \ | 8 | qlcnic_ethtool.o qlcnic_ctx.o qlcnic_io.o \ |
9 | qlcnic_sysfs.o qlcnic_minidump.o | 9 | qlcnic_sysfs.o qlcnic_minidump.o qlcnic_83xx_hw.o |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index 5c5c57813cdd..2b7adda619bb 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | |||
@@ -33,6 +33,8 @@ | |||
33 | #include <linux/if_vlan.h> | 33 | #include <linux/if_vlan.h> |
34 | 34 | ||
35 | #include "qlcnic_hdr.h" | 35 | #include "qlcnic_hdr.h" |
36 | #include "qlcnic_hw.h" | ||
37 | #include "qlcnic_83xx_hw.h" | ||
36 | 38 | ||
37 | #define _QLCNIC_LINUX_MAJOR 5 | 39 | #define _QLCNIC_LINUX_MAJOR 5 |
38 | #define _QLCNIC_LINUX_MINOR 0 | 40 | #define _QLCNIC_LINUX_MINOR 0 |
@@ -96,7 +98,6 @@ | |||
96 | #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 \ |
97 | + MGMT_CMD_DESC_RESV) | 99 | + MGMT_CMD_DESC_RESV) |
98 | #define QLCNIC_MAX_TX_TIMEOUTS 2 | 100 | #define QLCNIC_MAX_TX_TIMEOUTS 2 |
99 | |||
100 | /* | 101 | /* |
101 | * Following are the states of the Phantom. Phantom will set them and | 102 | * Following are the states of the Phantom. Phantom will set them and |
102 | * Host will read to check if the fields are correct. | 103 | * Host will read to check if the fields are correct. |
@@ -399,10 +400,16 @@ struct qlcnic_hardware_context { | |||
399 | u32 temp; | 400 | u32 temp; |
400 | u32 int_vec_bit; | 401 | u32 int_vec_bit; |
401 | u32 fw_hal_version; | 402 | u32 fw_hal_version; |
403 | u32 port_config; | ||
402 | struct qlcnic_hardware_ops *hw_ops; | 404 | struct qlcnic_hardware_ops *hw_ops; |
403 | struct qlcnic_nic_intr_coalesce coal; | 405 | struct qlcnic_nic_intr_coalesce coal; |
404 | struct qlcnic_fw_dump fw_dump; | 406 | struct qlcnic_fw_dump fw_dump; |
407 | struct qlcnic_intrpt_config *intr_tbl; | ||
405 | u32 *reg_tbl; | 408 | u32 *reg_tbl; |
409 | u32 *ext_reg_tbl; | ||
410 | u32 mbox_aen[QLC_83XX_MBX_AEN_CNT]; | ||
411 | u32 mbox_reg[4]; | ||
412 | spinlock_t mbx_lock; | ||
406 | }; | 413 | }; |
407 | 414 | ||
408 | struct qlcnic_adapter_stats { | 415 | struct qlcnic_adapter_stats { |
@@ -423,6 +430,7 @@ struct qlcnic_adapter_stats { | |||
423 | u64 null_rxbuf; | 430 | u64 null_rxbuf; |
424 | u64 rx_dma_map_error; | 431 | u64 rx_dma_map_error; |
425 | u64 tx_dma_map_error; | 432 | u64 tx_dma_map_error; |
433 | u64 spurious_intr; | ||
426 | }; | 434 | }; |
427 | 435 | ||
428 | /* | 436 | /* |
@@ -461,6 +469,8 @@ struct qlcnic_host_sds_ring { | |||
461 | } ____cacheline_internodealigned_in_smp; | 469 | } ____cacheline_internodealigned_in_smp; |
462 | 470 | ||
463 | struct qlcnic_host_tx_ring { | 471 | struct qlcnic_host_tx_ring { |
472 | void __iomem *crb_intr_mask; | ||
473 | char name[IFNAMSIZ+4]; | ||
464 | u16 ctx_id; | 474 | u16 ctx_id; |
465 | u32 producer; | 475 | u32 producer; |
466 | u32 sw_consumer; | 476 | u32 sw_consumer; |
@@ -761,7 +771,7 @@ struct qlcnic_mac_list_s { | |||
761 | */ | 771 | */ |
762 | 772 | ||
763 | #define QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK 0x8f | 773 | #define QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK 0x8f |
764 | #define QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE 141 | 774 | #define QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE 0x8D |
765 | 775 | ||
766 | #define VPORT_MISS_MODE_DROP 0 /* drop all unmatched */ | 776 | #define VPORT_MISS_MODE_DROP 0 /* drop all unmatched */ |
767 | #define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */ | 777 | #define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */ |
@@ -854,7 +864,7 @@ struct qlcnic_ipaddr { | |||
854 | 864 | ||
855 | #define QLCNIC_MSI_ENABLED 0x02 | 865 | #define QLCNIC_MSI_ENABLED 0x02 |
856 | #define QLCNIC_MSIX_ENABLED 0x04 | 866 | #define QLCNIC_MSIX_ENABLED 0x04 |
857 | #define QLCNIC_LRO_ENABLED 0x08 | 867 | #define QLCNIC_LRO_ENABLED 0x01 |
858 | #define QLCNIC_LRO_DISABLED 0x00 | 868 | #define QLCNIC_LRO_DISABLED 0x00 |
859 | #define QLCNIC_BRIDGE_ENABLED 0X10 | 869 | #define QLCNIC_BRIDGE_ENABLED 0X10 |
860 | #define QLCNIC_DIAG_ENABLED 0x20 | 870 | #define QLCNIC_DIAG_ENABLED 0x20 |
@@ -894,6 +904,7 @@ struct qlcnic_ipaddr { | |||
894 | #define QLCNIC_FILTER_AGE 80 | 904 | #define QLCNIC_FILTER_AGE 80 |
895 | #define QLCNIC_READD_AGE 20 | 905 | #define QLCNIC_READD_AGE 20 |
896 | #define QLCNIC_LB_MAX_FILTERS 64 | 906 | #define QLCNIC_LB_MAX_FILTERS 64 |
907 | #define QLCNIC_LB_BUCKET_SIZE 32 | ||
897 | 908 | ||
898 | /* QLCNIC Driver Error Code */ | 909 | /* QLCNIC Driver Error Code */ |
899 | #define QLCNIC_FW_NOT_RESPOND 51 | 910 | #define QLCNIC_FW_NOT_RESPOND 51 |
@@ -911,7 +922,8 @@ struct qlcnic_filter { | |||
911 | struct qlcnic_filter_hash { | 922 | struct qlcnic_filter_hash { |
912 | struct hlist_head *fhead; | 923 | struct hlist_head *fhead; |
913 | u8 fnum; | 924 | u8 fnum; |
914 | u8 fmax; | 925 | u16 fmax; |
926 | u16 fbucket_size; | ||
915 | }; | 927 | }; |
916 | 928 | ||
917 | struct qlcnic_adapter { | 929 | struct qlcnic_adapter { |
@@ -933,6 +945,7 @@ struct qlcnic_adapter { | |||
933 | 945 | ||
934 | u8 max_rds_rings; | 946 | u8 max_rds_rings; |
935 | u8 max_sds_rings; | 947 | u8 max_sds_rings; |
948 | u8 rx_csum; | ||
936 | u8 portnum; | 949 | u8 portnum; |
937 | 950 | ||
938 | u8 fw_wait_cnt; | 951 | u8 fw_wait_cnt; |
@@ -968,7 +981,9 @@ struct qlcnic_adapter { | |||
968 | void __iomem *isr_int_vec; | 981 | void __iomem *isr_int_vec; |
969 | 982 | ||
970 | struct msix_entry *msix_entries; | 983 | struct msix_entry *msix_entries; |
984 | struct workqueue_struct *qlcnic_wq; | ||
971 | struct delayed_work fw_work; | 985 | struct delayed_work fw_work; |
986 | struct delayed_work idc_aen_work; | ||
972 | 987 | ||
973 | struct qlcnic_filter_hash fhash; | 988 | struct qlcnic_filter_hash fhash; |
974 | 989 | ||
@@ -994,7 +1009,24 @@ struct qlcnic_info_le { | |||
994 | __le16 max_rx_ques; | 1009 | __le16 max_rx_ques; |
995 | __le16 min_tx_bw; | 1010 | __le16 min_tx_bw; |
996 | __le16 max_tx_bw; | 1011 | __le16 max_tx_bw; |
997 | u8 reserved2[104]; | 1012 | __le32 op_type; |
1013 | __le16 max_bw_reg_offset; | ||
1014 | __le16 max_linkspeed_reg_offset; | ||
1015 | __le32 capability1; | ||
1016 | __le32 capability2; | ||
1017 | __le32 capability3; | ||
1018 | __le16 max_tx_mac_filters; | ||
1019 | __le16 max_rx_mcast_mac_filters; | ||
1020 | __le16 max_rx_ucast_mac_filters; | ||
1021 | __le16 max_rx_ip_addr; | ||
1022 | __le16 max_rx_lro_flow; | ||
1023 | __le16 max_rx_status_rings; | ||
1024 | __le16 max_rx_buf_rings; | ||
1025 | __le16 max_tx_vlan_keys; | ||
1026 | u8 total_pf; | ||
1027 | u8 total_rss_engines; | ||
1028 | __le16 max_vports; | ||
1029 | u8 reserved2[64]; | ||
998 | } __packed; | 1030 | } __packed; |
999 | 1031 | ||
1000 | struct qlcnic_info { | 1032 | struct qlcnic_info { |
@@ -1010,6 +1042,23 @@ struct qlcnic_info { | |||
1010 | u16 max_rx_ques; | 1042 | u16 max_rx_ques; |
1011 | u16 min_tx_bw; | 1043 | u16 min_tx_bw; |
1012 | u16 max_tx_bw; | 1044 | u16 max_tx_bw; |
1045 | u32 op_type; | ||
1046 | u16 max_bw_reg_offset; | ||
1047 | u16 max_linkspeed_reg_offset; | ||
1048 | u32 capability1; | ||
1049 | u32 capability2; | ||
1050 | u32 capability3; | ||
1051 | u16 max_tx_mac_filters; | ||
1052 | u16 max_rx_mcast_mac_filters; | ||
1053 | u16 max_rx_ucast_mac_filters; | ||
1054 | u16 max_rx_ip_addr; | ||
1055 | u16 max_rx_lro_flow; | ||
1056 | u16 max_rx_status_rings; | ||
1057 | u16 max_rx_buf_rings; | ||
1058 | u16 max_tx_vlan_keys; | ||
1059 | u8 total_pf; | ||
1060 | u8 total_rss_engines; | ||
1061 | u16 max_vports; | ||
1013 | }; | 1062 | }; |
1014 | 1063 | ||
1015 | struct qlcnic_pci_info_le { | 1064 | struct qlcnic_pci_info_le { |
@@ -1023,7 +1072,9 @@ struct qlcnic_pci_info_le { | |||
1023 | __le16 reserved1[2]; | 1072 | __le16 reserved1[2]; |
1024 | 1073 | ||
1025 | u8 mac[ETH_ALEN]; | 1074 | u8 mac[ETH_ALEN]; |
1026 | u8 reserved2[106]; | 1075 | __le16 func_count; |
1076 | u8 reserved2[104]; | ||
1077 | |||
1027 | } __packed; | 1078 | } __packed; |
1028 | 1079 | ||
1029 | struct qlcnic_pci_info { | 1080 | struct qlcnic_pci_info { |
@@ -1034,6 +1085,7 @@ struct qlcnic_pci_info { | |||
1034 | u16 tx_min_bw; | 1085 | u16 tx_min_bw; |
1035 | u16 tx_max_bw; | 1086 | u16 tx_max_bw; |
1036 | u8 mac[ETH_ALEN]; | 1087 | u8 mac[ETH_ALEN]; |
1088 | u16 func_count; | ||
1037 | }; | 1089 | }; |
1038 | 1090 | ||
1039 | struct qlcnic_npar_info { | 1091 | struct qlcnic_npar_info { |
@@ -1375,6 +1427,7 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev); | |||
1375 | int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data); | 1427 | int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data); |
1376 | int qlcnic_validate_max_rss(struct net_device *netdev, u8, u8); | 1428 | int qlcnic_validate_max_rss(struct net_device *netdev, u8, u8); |
1377 | void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter); | 1429 | void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter); |
1430 | int qlcnic_enable_msix(struct qlcnic_adapter *, u32); | ||
1378 | 1431 | ||
1379 | /* eSwitch management functions */ | 1432 | /* eSwitch management functions */ |
1380 | int qlcnic_config_switch_port(struct qlcnic_adapter *, | 1433 | int qlcnic_config_switch_port(struct qlcnic_adapter *, |
@@ -1394,6 +1447,7 @@ void qlcnic_napi_del(struct qlcnic_adapter *); | |||
1394 | 1447 | ||
1395 | int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *, int); | 1448 | int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *, int); |
1396 | void qlcnic_free_sds_rings(struct qlcnic_recv_context *); | 1449 | void qlcnic_free_sds_rings(struct qlcnic_recv_context *); |
1450 | void qlcnic_advert_link_change(struct qlcnic_adapter *, int); | ||
1397 | void qlcnic_free_tx_rings(struct qlcnic_adapter *); | 1451 | void qlcnic_free_tx_rings(struct qlcnic_adapter *); |
1398 | int qlcnic_alloc_tx_rings(struct qlcnic_adapter *, struct net_device *); | 1452 | int qlcnic_alloc_tx_rings(struct qlcnic_adapter *, struct net_device *); |
1399 | 1453 | ||
@@ -1502,7 +1556,7 @@ static inline void qlcnic_write_crb(struct qlcnic_adapter *adapter, char *buf, | |||
1502 | adapter->ahw->hw_ops->write_crb(adapter, buf, offset, size); | 1556 | adapter->ahw->hw_ops->write_crb(adapter, buf, offset, size); |
1503 | } | 1557 | } |
1504 | 1558 | ||
1505 | static inline u32 qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, | 1559 | static inline int qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, |
1506 | ulong off) | 1560 | ulong off) |
1507 | { | 1561 | { |
1508 | return adapter->ahw->hw_ops->read_reg(adapter, off); | 1562 | return adapter->ahw->hw_ops->read_reg(adapter, off); |
@@ -1723,6 +1777,7 @@ extern const struct ethtool_ops qlcnic_ethtool_failed_ops; | |||
1723 | __func__, ##_args); \ | 1777 | __func__, ##_args); \ |
1724 | } while (0) | 1778 | } while (0) |
1725 | 1779 | ||
1780 | #define PCI_DEVICE_ID_QLOGIC_QLE834X 0x8030 | ||
1726 | #define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020 | 1781 | #define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020 |
1727 | static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter) | 1782 | static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter) |
1728 | { | 1783 | { |
@@ -1730,4 +1785,11 @@ static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter) | |||
1730 | return (device == PCI_DEVICE_ID_QLOGIC_QLE824X) ? true : false; | 1785 | return (device == PCI_DEVICE_ID_QLOGIC_QLE824X) ? true : false; |
1731 | } | 1786 | } |
1732 | 1787 | ||
1788 | static inline bool qlcnic_83xx_check(struct qlcnic_adapter *adapter) | ||
1789 | { | ||
1790 | unsigned short device = adapter->pdev->device; | ||
1791 | return (device == PCI_DEVICE_ID_QLOGIC_QLE834X) ? true : false; | ||
1792 | } | ||
1793 | |||
1794 | |||
1733 | #endif /* __QLCNIC_H_ */ | 1795 | #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 new file mode 100644 index 000000000000..454cd9f2e545 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | |||
@@ -0,0 +1,1719 @@ | |||
1 | #include "qlcnic.h" | ||
2 | #include <linux/if_vlan.h> | ||
3 | #include <linux/ipv6.h> | ||
4 | #include <linux/ethtool.h> | ||
5 | #include <linux/interrupt.h> | ||
6 | |||
7 | #define QLCNIC_MAX_TX_QUEUES 1 | ||
8 | |||
9 | #define QLCNIC_MBX_RSP(reg) LSW(reg) | ||
10 | #define QLCNIC_MBX_NUM_REGS(reg) (MSW(reg) & 0x1FF) | ||
11 | #define QLCNIC_MBX_STATUS(reg) (((reg) >> 25) & 0x7F) | ||
12 | #define QLCNIC_MBX_HOST(ahw, i) ((ahw)->pci_base0 + ((i) * 4)) | ||
13 | #define QLCNIC_MBX_FW(ahw, i) ((ahw)->pci_base0 + 0x800 + ((i) * 4)) | ||
14 | |||
15 | #define RSS_HASHTYPE_IP_TCP 0x3 | ||
16 | |||
17 | /* status descriptor mailbox data | ||
18 | * @phy_addr: physical address of buffer | ||
19 | * @sds_ring_size: buffer size | ||
20 | * @intrpt_id: interrupt id | ||
21 | * @intrpt_val: source of interrupt | ||
22 | */ | ||
23 | struct qlcnic_sds_mbx { | ||
24 | u64 phy_addr; | ||
25 | u8 rsvd1[16]; | ||
26 | u16 sds_ring_size; | ||
27 | u16 rsvd2[3]; | ||
28 | u16 intrpt_id; | ||
29 | u8 intrpt_val; | ||
30 | u8 rsvd3[5]; | ||
31 | } __packed; | ||
32 | |||
33 | /* receive descriptor buffer data | ||
34 | * phy_addr_reg: physical address of regular buffer | ||
35 | * phy_addr_jmb: physical address of jumbo buffer | ||
36 | * reg_ring_sz: size of regular buffer | ||
37 | * reg_ring_len: no. of entries in regular buffer | ||
38 | * jmb_ring_len: no. of entries in jumbo buffer | ||
39 | * jmb_ring_sz: size of jumbo buffer | ||
40 | */ | ||
41 | struct qlcnic_rds_mbx { | ||
42 | u64 phy_addr_reg; | ||
43 | u64 phy_addr_jmb; | ||
44 | u16 reg_ring_sz; | ||
45 | u16 reg_ring_len; | ||
46 | u16 jmb_ring_sz; | ||
47 | u16 jmb_ring_len; | ||
48 | } __packed; | ||
49 | |||
50 | /* host producers for regular and jumbo rings */ | ||
51 | struct __host_producer_mbx { | ||
52 | u32 reg_buf; | ||
53 | u32 jmb_buf; | ||
54 | } __packed; | ||
55 | |||
56 | /* Receive context mailbox data outbox registers | ||
57 | * @state: state of the context | ||
58 | * @vport_id: virtual port id | ||
59 | * @context_id: receive context id | ||
60 | * @num_pci_func: number of pci functions of the port | ||
61 | * @phy_port: physical port id | ||
62 | */ | ||
63 | struct qlcnic_rcv_mbx_out { | ||
64 | u8 rcv_num; | ||
65 | u8 sts_num; | ||
66 | u16 ctx_id; | ||
67 | u8 state; | ||
68 | u8 num_pci_func; | ||
69 | u8 phy_port; | ||
70 | u8 vport_id; | ||
71 | u32 host_csmr[QLCNIC_MAX_RING_SETS]; | ||
72 | struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS]; | ||
73 | } __packed; | ||
74 | |||
75 | struct qlcnic_add_rings_mbx_out { | ||
76 | u8 rcv_num; | ||
77 | u8 sts_num; | ||
78 | u16 ctx_id; | ||
79 | u32 host_csmr[QLCNIC_MAX_RING_SETS]; | ||
80 | struct __host_producer_mbx host_prod[QLCNIC_MAX_RING_SETS]; | ||
81 | } __packed; | ||
82 | |||
83 | /* Transmit context mailbox inbox registers | ||
84 | * @phys_addr: DMA address of the transmit buffer | ||
85 | * @cnsmr_index: host consumer index | ||
86 | * @size: legth of transmit buffer ring | ||
87 | * @intr_id: interrput id | ||
88 | * @src: src of interrupt | ||
89 | */ | ||
90 | struct qlcnic_tx_mbx { | ||
91 | u64 phys_addr; | ||
92 | u64 cnsmr_index; | ||
93 | u16 size; | ||
94 | u16 intr_id; | ||
95 | u8 src; | ||
96 | u8 rsvd[3]; | ||
97 | } __packed; | ||
98 | |||
99 | /* Transmit context mailbox outbox registers | ||
100 | * @host_prod: host producer index | ||
101 | * @ctx_id: transmit context id | ||
102 | * @state: state of the transmit context | ||
103 | */ | ||
104 | struct qlcnic_tx_mbx_out { | ||
105 | u32 host_prod; | ||
106 | u16 ctx_id; | ||
107 | u8 state; | ||
108 | u8 rsvd; | ||
109 | } __packed; | ||
110 | |||
111 | static const struct qlcnic_mailbox_metadata qlcnic_83xx_mbx_tbl[] = { | ||
112 | {QLCNIC_CMD_CONFIGURE_IP_ADDR, 6, 1}, | ||
113 | {QLCNIC_CMD_CONFIG_INTRPT, 18, 34}, | ||
114 | {QLCNIC_CMD_CREATE_RX_CTX, 136, 27}, | ||
115 | {QLCNIC_CMD_DESTROY_RX_CTX, 2, 1}, | ||
116 | {QLCNIC_CMD_CREATE_TX_CTX, 54, 18}, | ||
117 | {QLCNIC_CMD_DESTROY_TX_CTX, 2, 1}, | ||
118 | {QLCNIC_CMD_CONFIGURE_MAC_LEARNING, 2, 1}, | ||
119 | {QLCNIC_CMD_INTRPT_TEST, 22, 12}, | ||
120 | {QLCNIC_CMD_SET_MTU, 3, 1}, | ||
121 | {QLCNIC_CMD_READ_PHY, 4, 2}, | ||
122 | {QLCNIC_CMD_WRITE_PHY, 5, 1}, | ||
123 | {QLCNIC_CMD_READ_HW_REG, 4, 1}, | ||
124 | {QLCNIC_CMD_GET_FLOW_CTL, 4, 2}, | ||
125 | {QLCNIC_CMD_SET_FLOW_CTL, 4, 1}, | ||
126 | {QLCNIC_CMD_READ_MAX_MTU, 4, 2}, | ||
127 | {QLCNIC_CMD_READ_MAX_LRO, 4, 2}, | ||
128 | {QLCNIC_CMD_MAC_ADDRESS, 4, 3}, | ||
129 | {QLCNIC_CMD_GET_PCI_INFO, 1, 66}, | ||
130 | {QLCNIC_CMD_GET_NIC_INFO, 2, 19}, | ||
131 | {QLCNIC_CMD_SET_NIC_INFO, 32, 1}, | ||
132 | {QLCNIC_CMD_GET_ESWITCH_CAPABILITY, 4, 3}, | ||
133 | {QLCNIC_CMD_TOGGLE_ESWITCH, 4, 1}, | ||
134 | {QLCNIC_CMD_GET_ESWITCH_STATUS, 4, 3}, | ||
135 | {QLCNIC_CMD_SET_PORTMIRRORING, 4, 1}, | ||
136 | {QLCNIC_CMD_CONFIGURE_ESWITCH, 4, 1}, | ||
137 | {QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG, 4, 3}, | ||
138 | {QLCNIC_CMD_GET_ESWITCH_STATS, 5, 1}, | ||
139 | {QLCNIC_CMD_CONFIG_PORT, 4, 1}, | ||
140 | {QLCNIC_CMD_TEMP_SIZE, 1, 4}, | ||
141 | {QLCNIC_CMD_GET_TEMP_HDR, 5, 5}, | ||
142 | {QLCNIC_CMD_GET_LINK_EVENT, 2, 1}, | ||
143 | {QLCNIC_CMD_CONFIG_MAC_VLAN, 4, 3}, | ||
144 | {QLCNIC_CMD_CONFIG_INTR_COAL, 6, 1}, | ||
145 | {QLCNIC_CMD_CONFIGURE_RSS, 14, 1}, | ||
146 | {QLCNIC_CMD_CONFIGURE_LED, 2, 1}, | ||
147 | {QLCNIC_CMD_CONFIGURE_MAC_RX_MODE, 2, 1}, | ||
148 | {QLCNIC_CMD_CONFIGURE_HW_LRO, 2, 1}, | ||
149 | {QLCNIC_CMD_GET_STATISTICS, 2, 80}, | ||
150 | {QLCNIC_CMD_SET_PORT_CONFIG, 2, 1}, | ||
151 | {QLCNIC_CMD_GET_PORT_CONFIG, 2, 2}, | ||
152 | {QLCNIC_CMD_GET_LINK_STATUS, 2, 4}, | ||
153 | {QLCNIC_CMD_IDC_ACK, 5, 1}, | ||
154 | {QLCNIC_CMD_INIT_NIC_FUNC, 2, 1}, | ||
155 | {QLCNIC_CMD_STOP_NIC_FUNC, 2, 1}, | ||
156 | {QLCNIC_CMD_SET_LED_CONFIG, 5, 1}, | ||
157 | {QLCNIC_CMD_GET_LED_CONFIG, 1, 5}, | ||
158 | {QLCNIC_CMD_ADD_RCV_RINGS, 130, 26}, | ||
159 | }; | ||
160 | |||
161 | static const u32 qlcnic_83xx_ext_reg_tbl[] = { | ||
162 | 0x38CC, /* Global Reset */ | ||
163 | 0x38F0, /* Wildcard */ | ||
164 | 0x38FC, /* Informant */ | ||
165 | 0x3038, /* Host MBX ctrl */ | ||
166 | 0x303C, /* FW MBX ctrl */ | ||
167 | 0x355C, /* BOOT LOADER ADDRESS REG */ | ||
168 | 0x3560, /* BOOT LOADER SIZE REG */ | ||
169 | 0x3564, /* FW IMAGE ADDR REG */ | ||
170 | 0x1000, /* MBX intr enable */ | ||
171 | 0x1200, /* Default Intr mask */ | ||
172 | 0x1204, /* Default Interrupt ID */ | ||
173 | 0x3780, /* QLC_83XX_IDC_MAJ_VERSION */ | ||
174 | 0x3784, /* QLC_83XX_IDC_DEV_STATE */ | ||
175 | 0x3788, /* QLC_83XX_IDC_DRV_PRESENCE */ | ||
176 | 0x378C, /* QLC_83XX_IDC_DRV_ACK */ | ||
177 | 0x3790, /* QLC_83XX_IDC_CTRL */ | ||
178 | 0x3794, /* QLC_83XX_IDC_DRV_AUDIT */ | ||
179 | 0x3798, /* QLC_83XX_IDC_MIN_VERSION */ | ||
180 | 0x379C, /* QLC_83XX_RECOVER_DRV_LOCK */ | ||
181 | 0x37A0, /* QLC_83XX_IDC_PF_0 */ | ||
182 | 0x37A4, /* QLC_83XX_IDC_PF_1 */ | ||
183 | 0x37A8, /* QLC_83XX_IDC_PF_2 */ | ||
184 | 0x37AC, /* QLC_83XX_IDC_PF_3 */ | ||
185 | 0x37B0, /* QLC_83XX_IDC_PF_4 */ | ||
186 | 0x37B4, /* QLC_83XX_IDC_PF_5 */ | ||
187 | 0x37B8, /* QLC_83XX_IDC_PF_6 */ | ||
188 | 0x37BC, /* QLC_83XX_IDC_PF_7 */ | ||
189 | 0x37C0, /* QLC_83XX_IDC_PF_8 */ | ||
190 | 0x37C4, /* QLC_83XX_IDC_PF_9 */ | ||
191 | 0x37C8, /* QLC_83XX_IDC_PF_10 */ | ||
192 | 0x37CC, /* QLC_83XX_IDC_PF_11 */ | ||
193 | 0x37D0, /* QLC_83XX_IDC_PF_12 */ | ||
194 | 0x37D4, /* QLC_83XX_IDC_PF_13 */ | ||
195 | 0x37D8, /* QLC_83XX_IDC_PF_14 */ | ||
196 | 0x37DC, /* QLC_83XX_IDC_PF_15 */ | ||
197 | 0x37E0, /* QLC_83XX_IDC_DEV_PARTITION_INFO_1 */ | ||
198 | 0x37E4, /* QLC_83XX_IDC_DEV_PARTITION_INFO_2 */ | ||
199 | 0x37F0, /* QLC_83XX_DRV_OP_MODE */ | ||
200 | 0x37F4, /* QLC_83XX_VNIC_STATE */ | ||
201 | 0x3868, /* QLC_83XX_DRV_LOCK */ | ||
202 | 0x386C, /* QLC_83XX_DRV_UNLOCK */ | ||
203 | 0x3504, /* QLC_83XX_DRV_LOCK_ID */ | ||
204 | 0x34A4, /* QLC_83XX_ASIC_TEMP */ | ||
205 | }; | ||
206 | |||
207 | static const u32 qlcnic_83xx_reg_tbl[] = { | ||
208 | 0x34A8, /* PEG_HALT_STAT1 */ | ||
209 | 0x34AC, /* PEG_HALT_STAT2 */ | ||
210 | 0x34B0, /* FW_HEARTBEAT */ | ||
211 | 0x3500, /* FLASH LOCK_ID */ | ||
212 | 0x3528, /* FW_CAPABILITIES */ | ||
213 | 0x3538, /* Driver active, DRV_REG0 */ | ||
214 | 0x3540, /* Device state, DRV_REG1 */ | ||
215 | 0x3544, /* Driver state, DRV_REG2 */ | ||
216 | 0x3548, /* Driver scratch, DRV_REG3 */ | ||
217 | 0x354C, /* Device partiton info, DRV_REG4 */ | ||
218 | 0x3524, /* Driver IDC ver, DRV_REG5 */ | ||
219 | 0x3550, /* FW_VER_MAJOR */ | ||
220 | 0x3554, /* FW_VER_MINOR */ | ||
221 | 0x3558, /* FW_VER_SUB */ | ||
222 | 0x359C, /* NPAR STATE */ | ||
223 | 0x35FC, /* FW_IMG_VALID */ | ||
224 | 0x3650, /* CMD_PEG_STATE */ | ||
225 | 0x373C, /* RCV_PEG_STATE */ | ||
226 | 0x37B4, /* ASIC TEMP */ | ||
227 | 0x356C, /* FW API */ | ||
228 | 0x3570, /* DRV OP MODE */ | ||
229 | 0x3850, /* FLASH LOCK */ | ||
230 | 0x3854, /* FLASH UNLOCK */ | ||
231 | }; | ||
232 | |||
233 | static struct qlcnic_hardware_ops qlcnic_83xx_hw_ops = { | ||
234 | .read_crb = qlcnic_83xx_read_crb, | ||
235 | .write_crb = qlcnic_83xx_write_crb, | ||
236 | .read_reg = qlcnic_83xx_rd_reg_indirect, | ||
237 | .write_reg = qlcnic_83xx_wrt_reg_indirect, | ||
238 | .get_mac_address = qlcnic_83xx_get_mac_address, | ||
239 | .setup_intr = qlcnic_83xx_setup_intr, | ||
240 | .alloc_mbx_args = qlcnic_83xx_alloc_mbx_args, | ||
241 | .mbx_cmd = qlcnic_83xx_mbx_op, | ||
242 | .get_func_no = qlcnic_83xx_get_func_no, | ||
243 | .api_lock = qlcnic_83xx_cam_lock, | ||
244 | .api_unlock = qlcnic_83xx_cam_unlock, | ||
245 | .create_rx_ctx = qlcnic_83xx_create_rx_ctx, | ||
246 | .create_tx_ctx = qlcnic_83xx_create_tx_ctx, | ||
247 | .setup_link_event = qlcnic_83xx_setup_link_event, | ||
248 | .get_nic_info = qlcnic_83xx_get_nic_info, | ||
249 | .get_pci_info = qlcnic_83xx_get_pci_info, | ||
250 | .set_nic_info = qlcnic_83xx_set_nic_info, | ||
251 | .change_macvlan = qlcnic_83xx_sre_macaddr_change, | ||
252 | .config_intr_coal = qlcnic_83xx_config_intr_coal, | ||
253 | .config_rss = qlcnic_83xx_config_rss, | ||
254 | .config_hw_lro = qlcnic_83xx_config_hw_lro, | ||
255 | .config_loopback = qlcnic_83xx_set_lb_mode, | ||
256 | .clear_loopback = qlcnic_83xx_clear_lb_mode, | ||
257 | .config_promisc_mode = qlcnic_83xx_nic_set_promisc, | ||
258 | .change_l2_filter = qlcnic_83xx_change_l2_filter, | ||
259 | .get_board_info = qlcnic_83xx_get_port_info, | ||
260 | }; | ||
261 | |||
262 | static struct qlcnic_nic_template qlcnic_83xx_ops = { | ||
263 | .config_bridged_mode = qlcnic_config_bridged_mode, | ||
264 | .config_led = qlcnic_config_led, | ||
265 | .config_ipaddr = qlcnic_83xx_config_ipaddr, | ||
266 | .clear_legacy_intr = qlcnic_83xx_clear_legacy_intr, | ||
267 | }; | ||
268 | |||
269 | void qlcnic_83xx_register_map(struct qlcnic_hardware_context *ahw) | ||
270 | { | ||
271 | ahw->hw_ops = &qlcnic_83xx_hw_ops; | ||
272 | ahw->reg_tbl = (u32 *)qlcnic_83xx_reg_tbl; | ||
273 | ahw->ext_reg_tbl = (u32 *)qlcnic_83xx_ext_reg_tbl; | ||
274 | } | ||
275 | |||
276 | int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *adapter) | ||
277 | { | ||
278 | u32 fw_major, fw_minor, fw_build; | ||
279 | struct pci_dev *pdev = adapter->pdev; | ||
280 | |||
281 | fw_major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR); | ||
282 | fw_minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR); | ||
283 | fw_build = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB); | ||
284 | adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build); | ||
285 | |||
286 | dev_info(&pdev->dev, "Driver v%s, firmware version %d.%d.%d\n", | ||
287 | QLCNIC_LINUX_VERSIONID, fw_major, fw_minor, fw_build); | ||
288 | |||
289 | return adapter->fw_version; | ||
290 | } | ||
291 | |||
292 | static int __qlcnic_set_win_base(struct qlcnic_adapter *adapter, u32 addr) | ||
293 | { | ||
294 | void __iomem *base; | ||
295 | u32 val; | ||
296 | |||
297 | base = adapter->ahw->pci_base0 + | ||
298 | QLC_83XX_CRB_WIN_FUNC(adapter->ahw->pci_func); | ||
299 | writel(addr, base); | ||
300 | val = readl(base); | ||
301 | if (val != addr) | ||
302 | return -EIO; | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | int qlcnic_83xx_rd_reg_indirect(struct qlcnic_adapter *adapter, ulong addr) | ||
308 | { | ||
309 | int ret; | ||
310 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
311 | |||
312 | ret = __qlcnic_set_win_base(adapter, (u32) addr); | ||
313 | if (!ret) { | ||
314 | return QLCRDX(ahw, QLCNIC_WILDCARD); | ||
315 | } else { | ||
316 | dev_err(&adapter->pdev->dev, | ||
317 | "%s failed, addr = 0x%x\n", __func__, (int)addr); | ||
318 | return -EIO; | ||
319 | } | ||
320 | } | ||
321 | |||
322 | int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *adapter, ulong addr, | ||
323 | u32 data) | ||
324 | { | ||
325 | int err; | ||
326 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
327 | |||
328 | err = __qlcnic_set_win_base(adapter, (u32) addr); | ||
329 | if (!err) { | ||
330 | QLCWRX(ahw, QLCNIC_WILDCARD, data); | ||
331 | return 0; | ||
332 | } else { | ||
333 | dev_err(&adapter->pdev->dev, | ||
334 | "%s failed, addr = 0x%x data = 0x%x\n", | ||
335 | __func__, (int)addr, data); | ||
336 | return err; | ||
337 | } | ||
338 | } | ||
339 | |||
340 | int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr) | ||
341 | { | ||
342 | int err, i, num_msix; | ||
343 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
344 | |||
345 | if (!num_intr) | ||
346 | num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS; | ||
347 | num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(), | ||
348 | num_intr)); | ||
349 | /* account for AEN interrupt MSI-X based interrupts */ | ||
350 | num_msix += 1; | ||
351 | num_msix += adapter->max_drv_tx_rings; | ||
352 | err = qlcnic_enable_msix(adapter, num_msix); | ||
353 | if (err == -ENOMEM) | ||
354 | return err; | ||
355 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
356 | num_msix = adapter->ahw->num_msix; | ||
357 | else | ||
358 | num_msix = 1; | ||
359 | /* setup interrupt mapping table for fw */ | ||
360 | ahw->intr_tbl = vzalloc(num_msix * | ||
361 | sizeof(struct qlcnic_intrpt_config)); | ||
362 | if (!ahw->intr_tbl) | ||
363 | return -ENOMEM; | ||
364 | if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) { | ||
365 | /* MSI-X enablement failed, use legacy interrupt */ | ||
366 | adapter->tgt_status_reg = ahw->pci_base0 + QLC_83XX_INTX_PTR; | ||
367 | adapter->tgt_mask_reg = ahw->pci_base0 + QLC_83XX_INTX_MASK; | ||
368 | adapter->isr_int_vec = ahw->pci_base0 + QLC_83XX_INTX_TRGR; | ||
369 | adapter->msix_entries[0].vector = adapter->pdev->irq; | ||
370 | dev_info(&adapter->pdev->dev, "using legacy interrupt\n"); | ||
371 | } | ||
372 | |||
373 | for (i = 0; i < num_msix; i++) { | ||
374 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
375 | ahw->intr_tbl[i].type = QLCNIC_INTRPT_MSIX; | ||
376 | else | ||
377 | ahw->intr_tbl[i].type = QLCNIC_INTRPT_INTX; | ||
378 | ahw->intr_tbl[i].id = i; | ||
379 | ahw->intr_tbl[i].src = 0; | ||
380 | } | ||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | inline void qlcnic_83xx_enable_intr(struct qlcnic_adapter *adapter, | ||
385 | struct qlcnic_host_sds_ring *sds_ring) | ||
386 | { | ||
387 | writel(0, sds_ring->crb_intr_mask); | ||
388 | if (!QLCNIC_IS_MSI_FAMILY(adapter)) | ||
389 | writel(0, adapter->tgt_mask_reg); | ||
390 | } | ||
391 | |||
392 | static inline void qlcnic_83xx_get_mbx_data(struct qlcnic_adapter *adapter, | ||
393 | struct qlcnic_cmd_args *cmd) | ||
394 | { | ||
395 | int i; | ||
396 | for (i = 0; i < cmd->rsp.num; i++) | ||
397 | cmd->rsp.arg[i] = readl(QLCNIC_MBX_FW(adapter->ahw, i)); | ||
398 | } | ||
399 | |||
400 | irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *adapter) | ||
401 | { | ||
402 | u32 intr_val; | ||
403 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
404 | int retries = 0; | ||
405 | |||
406 | intr_val = readl(adapter->tgt_status_reg); | ||
407 | |||
408 | if (!QLC_83XX_VALID_INTX_BIT31(intr_val)) | ||
409 | return IRQ_NONE; | ||
410 | |||
411 | if (QLC_83XX_INTX_FUNC(intr_val) != adapter->ahw->pci_func) { | ||
412 | adapter->stats.spurious_intr++; | ||
413 | return IRQ_NONE; | ||
414 | } | ||
415 | /* clear the interrupt trigger control register */ | ||
416 | writel(0, adapter->isr_int_vec); | ||
417 | do { | ||
418 | intr_val = readl(adapter->tgt_status_reg); | ||
419 | if (QLC_83XX_INTX_FUNC(intr_val) != ahw->pci_func) | ||
420 | break; | ||
421 | retries++; | ||
422 | } while (QLC_83XX_VALID_INTX_BIT30(intr_val) && | ||
423 | (retries < QLC_83XX_LEGACY_INTX_MAX_RETRY)); | ||
424 | |||
425 | if (retries == QLC_83XX_LEGACY_INTX_MAX_RETRY) { | ||
426 | dev_info(&adapter->pdev->dev, | ||
427 | "Reached maximum retries to clear legacy interrupt\n"); | ||
428 | return IRQ_NONE; | ||
429 | } | ||
430 | |||
431 | mdelay(QLC_83XX_LEGACY_INTX_DELAY); | ||
432 | |||
433 | return IRQ_HANDLED; | ||
434 | } | ||
435 | |||
436 | irqreturn_t qlcnic_83xx_tmp_intr(int irq, void *data) | ||
437 | { | ||
438 | struct qlcnic_host_sds_ring *sds_ring = data; | ||
439 | struct qlcnic_adapter *adapter = sds_ring->adapter; | ||
440 | |||
441 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
442 | goto done; | ||
443 | |||
444 | if (adapter->nic_ops->clear_legacy_intr(adapter) == IRQ_NONE) | ||
445 | return IRQ_NONE; | ||
446 | |||
447 | done: | ||
448 | adapter->ahw->diag_cnt++; | ||
449 | qlcnic_83xx_enable_intr(adapter, sds_ring); | ||
450 | |||
451 | return IRQ_HANDLED; | ||
452 | } | ||
453 | |||
454 | void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *adapter) | ||
455 | { | ||
456 | u32 val = 0; | ||
457 | u32 num_msix = adapter->ahw->num_msix - 1; | ||
458 | |||
459 | val = (num_msix << 8); | ||
460 | |||
461 | QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, val); | ||
462 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
463 | free_irq(adapter->msix_entries[num_msix].vector, adapter); | ||
464 | } | ||
465 | |||
466 | int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter) | ||
467 | { | ||
468 | irq_handler_t handler; | ||
469 | u32 val; | ||
470 | char name[32]; | ||
471 | int err = 0; | ||
472 | unsigned long flags = 0; | ||
473 | |||
474 | if (!(adapter->flags & QLCNIC_MSI_ENABLED) && | ||
475 | !(adapter->flags & QLCNIC_MSIX_ENABLED)) | ||
476 | flags |= IRQF_SHARED; | ||
477 | |||
478 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { | ||
479 | handler = qlcnic_83xx_handle_aen; | ||
480 | val = adapter->msix_entries[adapter->ahw->num_msix - 1].vector; | ||
481 | snprintf(name, (IFNAMSIZ + 4), | ||
482 | "%s[%s]", adapter->netdev->name, "aen"); | ||
483 | err = request_irq(val, handler, flags, name, adapter); | ||
484 | if (err) { | ||
485 | dev_err(&adapter->pdev->dev, | ||
486 | "failed to register MBX interrupt\n"); | ||
487 | return err; | ||
488 | } | ||
489 | } | ||
490 | |||
491 | /* Enable mailbox interrupt */ | ||
492 | qlcnic_83xx_enable_mbx_intrpt(adapter); | ||
493 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
494 | err = qlcnic_83xx_config_intrpt(adapter, 1); | ||
495 | |||
496 | return err; | ||
497 | } | ||
498 | |||
499 | void qlcnic_83xx_get_func_no(struct qlcnic_adapter *adapter) | ||
500 | { | ||
501 | u32 val = QLCRDX(adapter->ahw, QLCNIC_INFORMANT); | ||
502 | adapter->ahw->pci_func = val & 0xf; | ||
503 | } | ||
504 | |||
505 | int qlcnic_83xx_cam_lock(struct qlcnic_adapter *adapter) | ||
506 | { | ||
507 | void __iomem *addr; | ||
508 | u32 val, limit = 0; | ||
509 | |||
510 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
511 | |||
512 | addr = ahw->pci_base0 + QLC_83XX_SEM_LOCK_FUNC(ahw->pci_func); | ||
513 | do { | ||
514 | val = readl(addr); | ||
515 | if (val) { | ||
516 | /* write the function number to register */ | ||
517 | QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER, | ||
518 | ahw->pci_func); | ||
519 | return 0; | ||
520 | } | ||
521 | usleep_range(1000, 2000); | ||
522 | } while (++limit <= QLCNIC_PCIE_SEM_TIMEOUT); | ||
523 | |||
524 | return -EIO; | ||
525 | } | ||
526 | |||
527 | void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *adapter) | ||
528 | { | ||
529 | void __iomem *addr; | ||
530 | u32 val; | ||
531 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
532 | |||
533 | addr = ahw->pci_base0 + QLC_83XX_SEM_UNLOCK_FUNC(ahw->pci_func); | ||
534 | val = readl(addr); | ||
535 | } | ||
536 | |||
537 | void qlcnic_83xx_read_crb(struct qlcnic_adapter *adapter, char *buf, | ||
538 | loff_t offset, size_t size) | ||
539 | { | ||
540 | int ret; | ||
541 | u32 data; | ||
542 | |||
543 | if (qlcnic_api_lock(adapter)) { | ||
544 | dev_err(&adapter->pdev->dev, | ||
545 | "%s: failed to acquire lock. addr offset 0x%x\n", | ||
546 | __func__, (u32)offset); | ||
547 | return; | ||
548 | } | ||
549 | |||
550 | ret = qlcnic_83xx_rd_reg_indirect(adapter, (u32) offset); | ||
551 | qlcnic_api_unlock(adapter); | ||
552 | |||
553 | if (ret == -EIO) { | ||
554 | dev_err(&adapter->pdev->dev, | ||
555 | "%s: failed. addr offset 0x%x\n", | ||
556 | __func__, (u32)offset); | ||
557 | return; | ||
558 | } | ||
559 | data = ret; | ||
560 | memcpy(buf, &data, size); | ||
561 | } | ||
562 | |||
563 | void qlcnic_83xx_write_crb(struct qlcnic_adapter *adapter, char *buf, | ||
564 | loff_t offset, size_t size) | ||
565 | { | ||
566 | u32 data; | ||
567 | |||
568 | memcpy(&data, buf, size); | ||
569 | qlcnic_83xx_wrt_reg_indirect(adapter, (u32) offset, data); | ||
570 | } | ||
571 | |||
572 | int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter) | ||
573 | { | ||
574 | int status; | ||
575 | |||
576 | status = qlcnic_83xx_get_port_config(adapter); | ||
577 | if (status) { | ||
578 | dev_err(&adapter->pdev->dev, | ||
579 | "Get Port Info failed\n"); | ||
580 | } else { | ||
581 | if (QLC_83XX_SFP_10G_CAPABLE(adapter->ahw->port_config)) | ||
582 | adapter->ahw->port_type = QLCNIC_XGBE; | ||
583 | else | ||
584 | adapter->ahw->port_type = QLCNIC_GBE; | ||
585 | if (QLC_83XX_AUTONEG(adapter->ahw->port_config)) | ||
586 | adapter->ahw->link_autoneg = AUTONEG_ENABLE; | ||
587 | } | ||
588 | return status; | ||
589 | } | ||
590 | |||
591 | void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *adapter) | ||
592 | { | ||
593 | u32 val; | ||
594 | |||
595 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
596 | val = BIT_2 | ((adapter->ahw->num_msix - 1) << 8); | ||
597 | else | ||
598 | val = BIT_2; | ||
599 | QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, val); | ||
600 | } | ||
601 | |||
602 | void qlcnic_83xx_check_vf(struct qlcnic_adapter *adapter, | ||
603 | const struct pci_device_id *ent) | ||
604 | { | ||
605 | u32 op_mode, priv_level; | ||
606 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
607 | |||
608 | /* Determine FW API version */ | ||
609 | ahw->fw_hal_version = 2; | ||
610 | /* Find PCI function number */ | ||
611 | qlcnic_get_func_no(adapter); | ||
612 | |||
613 | /* Determine function privilege level */ | ||
614 | op_mode = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE); | ||
615 | if (op_mode == QLC_83XX_DEFAULT_OPMODE) | ||
616 | priv_level = QLCNIC_MGMT_FUNC; | ||
617 | else | ||
618 | priv_level = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode, | ||
619 | ahw->pci_func); | ||
620 | |||
621 | if (priv_level == QLCNIC_NON_PRIV_FUNC) { | ||
622 | ahw->op_mode = QLCNIC_NON_PRIV_FUNC; | ||
623 | dev_info(&adapter->pdev->dev, | ||
624 | "HAL Version: %d Non Privileged function\n", | ||
625 | ahw->fw_hal_version); | ||
626 | adapter->nic_ops = &qlcnic_vf_ops; | ||
627 | } else { | ||
628 | adapter->nic_ops = &qlcnic_83xx_ops; | ||
629 | } | ||
630 | } | ||
631 | |||
632 | static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter, | ||
633 | u32 data[]); | ||
634 | static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter, | ||
635 | u32 data[]); | ||
636 | |||
637 | static void qlcnic_dump_mbx(struct qlcnic_adapter *adapter, | ||
638 | struct qlcnic_cmd_args *cmd) | ||
639 | { | ||
640 | int i; | ||
641 | |||
642 | dev_info(&adapter->pdev->dev, | ||
643 | "Host MBX regs(%d)\n", cmd->req.num); | ||
644 | for (i = 0; i < cmd->req.num; i++) { | ||
645 | if (i && !(i % 8)) | ||
646 | pr_info("\n"); | ||
647 | pr_info("%08x ", cmd->req.arg[i]); | ||
648 | } | ||
649 | pr_info("\n"); | ||
650 | dev_info(&adapter->pdev->dev, | ||
651 | "FW MBX regs(%d)\n", cmd->rsp.num); | ||
652 | for (i = 0; i < cmd->rsp.num; i++) { | ||
653 | if (i && !(i % 8)) | ||
654 | pr_info("\n"); | ||
655 | pr_info("%08x ", cmd->rsp.arg[i]); | ||
656 | } | ||
657 | pr_info("\n"); | ||
658 | } | ||
659 | |||
660 | static u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *adapter) | ||
661 | { | ||
662 | u32 data; | ||
663 | unsigned long wait_time = 0; | ||
664 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
665 | /* wait for mailbox completion */ | ||
666 | do { | ||
667 | data = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL); | ||
668 | if (++wait_time > QLCNIC_MBX_TIMEOUT) { | ||
669 | data = QLCNIC_RCODE_TIMEOUT; | ||
670 | break; | ||
671 | } | ||
672 | mdelay(1); | ||
673 | } while (!data); | ||
674 | return data; | ||
675 | } | ||
676 | |||
677 | int qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter, | ||
678 | struct qlcnic_cmd_args *cmd) | ||
679 | { | ||
680 | int i; | ||
681 | u16 opcode; | ||
682 | u8 mbx_err_code, mac_cmd_rcode; | ||
683 | u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd, temp, fw[8]; | ||
684 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
685 | |||
686 | opcode = LSW(cmd->req.arg[0]); | ||
687 | spin_lock(&ahw->mbx_lock); | ||
688 | mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL); | ||
689 | |||
690 | if (mbx_val) { | ||
691 | QLCDB(adapter, DRV, | ||
692 | "Mailbox cmd attempted, 0x%x\n", opcode); | ||
693 | QLCDB(adapter, DRV, | ||
694 | "Mailbox not available, 0x%x, collect FW dump\n", | ||
695 | mbx_val); | ||
696 | cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT; | ||
697 | spin_unlock(&ahw->mbx_lock); | ||
698 | return cmd->rsp.arg[0]; | ||
699 | } | ||
700 | |||
701 | /* Fill in mailbox registers */ | ||
702 | mbx_cmd = cmd->req.arg[0]; | ||
703 | writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0)); | ||
704 | for (i = 1; i < cmd->req.num; i++) | ||
705 | writel(cmd->req.arg[i], QLCNIC_MBX_HOST(ahw, i)); | ||
706 | |||
707 | /* Signal FW about the impending command */ | ||
708 | QLCWRX(ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER); | ||
709 | poll: | ||
710 | rsp = qlcnic_83xx_mbx_poll(adapter); | ||
711 | /* Get the FW response data */ | ||
712 | fw_data = readl(QLCNIC_MBX_FW(ahw, 0)); | ||
713 | mbx_err_code = QLCNIC_MBX_STATUS(fw_data); | ||
714 | rsp_num = QLCNIC_MBX_NUM_REGS(fw_data); | ||
715 | opcode = QLCNIC_MBX_RSP(fw_data); | ||
716 | |||
717 | if (rsp != QLCNIC_RCODE_TIMEOUT) { | ||
718 | if (opcode == QLCNIC_MBX_LINK_EVENT) { | ||
719 | for (i = 0; i < rsp_num; i++) { | ||
720 | temp = readl(QLCNIC_MBX_FW(ahw, i)); | ||
721 | fw[i] = temp; | ||
722 | } | ||
723 | qlcnic_83xx_handle_link_aen(adapter, fw); | ||
724 | /* clear fw mbx control register */ | ||
725 | QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER); | ||
726 | mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL); | ||
727 | if (mbx_val) | ||
728 | goto poll; | ||
729 | } else if (opcode == QLCNIC_MBX_COMP_EVENT) { | ||
730 | for (i = 0; i < rsp_num; i++) { | ||
731 | temp = readl(QLCNIC_MBX_FW(ahw, i)); | ||
732 | fw[i] = temp; | ||
733 | } | ||
734 | qlcnic_83xx_handle_idc_comp_aen(adapter, fw); | ||
735 | /* clear fw mbx control register */ | ||
736 | QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER); | ||
737 | mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL); | ||
738 | if (mbx_val) | ||
739 | goto poll; | ||
740 | } else if (opcode == QLCNIC_MBX_REQUEST_EVENT) { | ||
741 | /* IDC Request Notification */ | ||
742 | for (i = 0; i < rsp_num; i++) { | ||
743 | temp = readl(QLCNIC_MBX_FW(ahw, i)); | ||
744 | fw[i] = temp; | ||
745 | } | ||
746 | for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++) { | ||
747 | temp = QLCNIC_MBX_RSP(fw[i]); | ||
748 | adapter->ahw->mbox_aen[i] = temp; | ||
749 | } | ||
750 | queue_delayed_work(adapter->qlcnic_wq, | ||
751 | &adapter->idc_aen_work, 0); | ||
752 | /* clear fw mbx control register */ | ||
753 | QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER); | ||
754 | mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL); | ||
755 | if (mbx_val) | ||
756 | goto poll; | ||
757 | } else if ((mbx_err_code == QLCNIC_MBX_RSP_OK) || | ||
758 | (mbx_err_code == QLCNIC_MBX_PORT_RSP_OK)) { | ||
759 | qlcnic_83xx_get_mbx_data(adapter, cmd); | ||
760 | rsp = QLCNIC_RCODE_SUCCESS; | ||
761 | } else { | ||
762 | qlcnic_83xx_get_mbx_data(adapter, cmd); | ||
763 | if (opcode == QLCNIC_CMD_CONFIG_MAC_VLAN) { | ||
764 | fw_data = readl(QLCNIC_MBX_FW(ahw, 2)); | ||
765 | mac_cmd_rcode = (u8)fw_data; | ||
766 | if (mac_cmd_rcode == QLC_83XX_NO_NIC_RESOURCE || | ||
767 | mac_cmd_rcode == QLC_83XX_MAC_PRESENT || | ||
768 | mac_cmd_rcode == QLC_83XX_MAC_ABSENT) { | ||
769 | rsp = QLCNIC_RCODE_SUCCESS; | ||
770 | goto out; | ||
771 | } | ||
772 | } | ||
773 | dev_info(&adapter->pdev->dev, | ||
774 | "MBX command 0x%x failed with err:0x%x\n", | ||
775 | opcode, mbx_err_code); | ||
776 | rsp = mbx_err_code; | ||
777 | qlcnic_dump_mbx(adapter, cmd); | ||
778 | } | ||
779 | } else { | ||
780 | dev_info(&adapter->pdev->dev, | ||
781 | "MBX command 0x%x timed out\n", opcode); | ||
782 | qlcnic_dump_mbx(adapter, cmd); | ||
783 | } | ||
784 | out: | ||
785 | /* clear fw mbx control register */ | ||
786 | QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER); | ||
787 | spin_unlock(&ahw->mbx_lock); | ||
788 | return rsp; | ||
789 | } | ||
790 | |||
791 | int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx, | ||
792 | struct qlcnic_adapter *adapter, u32 type) | ||
793 | { | ||
794 | int i, size; | ||
795 | u32 temp; | ||
796 | const struct qlcnic_mailbox_metadata *mbx_tbl; | ||
797 | |||
798 | mbx_tbl = qlcnic_83xx_mbx_tbl; | ||
799 | size = ARRAY_SIZE(qlcnic_83xx_mbx_tbl); | ||
800 | for (i = 0; i < size; i++) { | ||
801 | if (type == mbx_tbl[i].cmd) { | ||
802 | mbx->req.num = mbx_tbl[i].in_args; | ||
803 | mbx->rsp.num = mbx_tbl[i].out_args; | ||
804 | mbx->req.arg = kcalloc(mbx->req.num, sizeof(u32), | ||
805 | GFP_ATOMIC); | ||
806 | if (!mbx->req.arg) | ||
807 | return -ENOMEM; | ||
808 | mbx->rsp.arg = kcalloc(mbx->rsp.num, sizeof(u32), | ||
809 | GFP_ATOMIC); | ||
810 | if (!mbx->rsp.arg) { | ||
811 | kfree(mbx->req.arg); | ||
812 | mbx->req.arg = NULL; | ||
813 | return -ENOMEM; | ||
814 | } | ||
815 | memset(mbx->req.arg, 0, sizeof(u32) * mbx->req.num); | ||
816 | memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num); | ||
817 | temp = adapter->ahw->fw_hal_version << 29; | ||
818 | mbx->req.arg[0] = (type | (mbx->req.num << 16) | temp); | ||
819 | break; | ||
820 | } | ||
821 | } | ||
822 | return 0; | ||
823 | } | ||
824 | |||
825 | void qlcnic_83xx_idc_aen_work(struct work_struct *work) | ||
826 | { | ||
827 | struct qlcnic_adapter *adapter; | ||
828 | struct qlcnic_cmd_args cmd; | ||
829 | int i, err = 0; | ||
830 | |||
831 | adapter = container_of(work, struct qlcnic_adapter, idc_aen_work.work); | ||
832 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_IDC_ACK); | ||
833 | |||
834 | for (i = 1; i < QLC_83XX_MBX_AEN_CNT; i++) | ||
835 | cmd.req.arg[i] = adapter->ahw->mbox_aen[i]; | ||
836 | |||
837 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
838 | if (err) | ||
839 | dev_info(&adapter->pdev->dev, | ||
840 | "%s: Mailbox IDC ACK failed.\n", __func__); | ||
841 | qlcnic_free_mbx_args(&cmd); | ||
842 | } | ||
843 | |||
844 | static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter, | ||
845 | u32 data[]) | ||
846 | { | ||
847 | dev_dbg(&adapter->pdev->dev, "Completion AEN:0x%x.\n", | ||
848 | QLCNIC_MBX_RSP(data[0])); | ||
849 | return; | ||
850 | } | ||
851 | |||
852 | void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter) | ||
853 | { | ||
854 | u32 mask, resp, event[QLC_83XX_MBX_AEN_CNT]; | ||
855 | int i; | ||
856 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
857 | |||
858 | if (!spin_trylock(&ahw->mbx_lock)) { | ||
859 | mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK); | ||
860 | writel(0, adapter->ahw->pci_base0 + mask); | ||
861 | return; | ||
862 | } | ||
863 | resp = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL); | ||
864 | |||
865 | if (!(resp & QLCNIC_SET_OWNER)) | ||
866 | goto out; | ||
867 | |||
868 | for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++) | ||
869 | event[i] = readl(QLCNIC_MBX_FW(ahw, i)); | ||
870 | |||
871 | switch (QLCNIC_MBX_RSP(event[0])) { | ||
872 | |||
873 | case QLCNIC_MBX_LINK_EVENT: | ||
874 | qlcnic_83xx_handle_link_aen(adapter, event); | ||
875 | break; | ||
876 | case QLCNIC_MBX_COMP_EVENT: | ||
877 | qlcnic_83xx_handle_idc_comp_aen(adapter, event); | ||
878 | break; | ||
879 | case QLCNIC_MBX_REQUEST_EVENT: | ||
880 | for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++) | ||
881 | adapter->ahw->mbox_aen[i] = QLCNIC_MBX_RSP(event[i]); | ||
882 | queue_delayed_work(adapter->qlcnic_wq, | ||
883 | &adapter->idc_aen_work, 0); | ||
884 | break; | ||
885 | case QLCNIC_MBX_TIME_EXTEND_EVENT: | ||
886 | break; | ||
887 | case QLCNIC_MBX_SFP_INSERT_EVENT: | ||
888 | dev_info(&adapter->pdev->dev, "SFP+ Insert AEN:0x%x.\n", | ||
889 | QLCNIC_MBX_RSP(event[0])); | ||
890 | break; | ||
891 | case QLCNIC_MBX_SFP_REMOVE_EVENT: | ||
892 | dev_info(&adapter->pdev->dev, "SFP Removed AEN:0x%x.\n", | ||
893 | QLCNIC_MBX_RSP(event[0])); | ||
894 | break; | ||
895 | default: | ||
896 | dev_dbg(&adapter->pdev->dev, "Unsupported AEN:0x%x.\n", | ||
897 | QLCNIC_MBX_RSP(event[0])); | ||
898 | break; | ||
899 | } | ||
900 | |||
901 | QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER); | ||
902 | out: | ||
903 | mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK); | ||
904 | writel(0, adapter->ahw->pci_base0 + mask); | ||
905 | spin_unlock(&ahw->mbx_lock); | ||
906 | } | ||
907 | |||
908 | static int qlcnic_83xx_add_rings(struct qlcnic_adapter *adapter) | ||
909 | { | ||
910 | int index, i, err, sds_mbx_size; | ||
911 | u32 *buf, intrpt_id, intr_mask; | ||
912 | u16 context_id; | ||
913 | u8 num_sds; | ||
914 | struct qlcnic_cmd_args cmd; | ||
915 | struct qlcnic_host_sds_ring *sds; | ||
916 | struct qlcnic_sds_mbx sds_mbx; | ||
917 | struct qlcnic_add_rings_mbx_out *mbx_out; | ||
918 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
919 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
920 | |||
921 | sds_mbx_size = sizeof(struct qlcnic_sds_mbx); | ||
922 | context_id = recv_ctx->context_id; | ||
923 | num_sds = (adapter->max_sds_rings - QLCNIC_MAX_RING_SETS); | ||
924 | ahw->hw_ops->alloc_mbx_args(&cmd, adapter, | ||
925 | QLCNIC_CMD_ADD_RCV_RINGS); | ||
926 | cmd.req.arg[1] = 0 | (num_sds << 8) | (context_id << 16); | ||
927 | |||
928 | /* set up status rings, mbx 2-81 */ | ||
929 | index = 2; | ||
930 | for (i = 8; i < adapter->max_sds_rings; i++) { | ||
931 | memset(&sds_mbx, 0, sds_mbx_size); | ||
932 | sds = &recv_ctx->sds_rings[i]; | ||
933 | sds->consumer = 0; | ||
934 | memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds)); | ||
935 | sds_mbx.phy_addr = sds->phys_addr; | ||
936 | sds_mbx.sds_ring_size = sds->num_desc; | ||
937 | |||
938 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
939 | intrpt_id = ahw->intr_tbl[i].id; | ||
940 | else | ||
941 | intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID); | ||
942 | |||
943 | if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) | ||
944 | sds_mbx.intrpt_id = intrpt_id; | ||
945 | else | ||
946 | sds_mbx.intrpt_id = 0xffff; | ||
947 | sds_mbx.intrpt_val = 0; | ||
948 | buf = &cmd.req.arg[index]; | ||
949 | memcpy(buf, &sds_mbx, sds_mbx_size); | ||
950 | index += sds_mbx_size / sizeof(u32); | ||
951 | } | ||
952 | |||
953 | /* send the mailbox command */ | ||
954 | err = ahw->hw_ops->mbx_cmd(adapter, &cmd); | ||
955 | if (err) { | ||
956 | dev_err(&adapter->pdev->dev, | ||
957 | "Failed to add rings %d\n", err); | ||
958 | goto out; | ||
959 | } | ||
960 | |||
961 | mbx_out = (struct qlcnic_add_rings_mbx_out *)&cmd.rsp.arg[1]; | ||
962 | index = 0; | ||
963 | /* status descriptor ring */ | ||
964 | for (i = 8; i < adapter->max_sds_rings; i++) { | ||
965 | sds = &recv_ctx->sds_rings[i]; | ||
966 | sds->crb_sts_consumer = ahw->pci_base0 + | ||
967 | mbx_out->host_csmr[index]; | ||
968 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
969 | intr_mask = ahw->intr_tbl[i].src; | ||
970 | else | ||
971 | intr_mask = QLCRDX(ahw, QLCNIC_DEF_INT_MASK); | ||
972 | |||
973 | sds->crb_intr_mask = ahw->pci_base0 + intr_mask; | ||
974 | index++; | ||
975 | } | ||
976 | out: | ||
977 | qlcnic_free_mbx_args(&cmd); | ||
978 | return err; | ||
979 | } | ||
980 | |||
981 | int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter) | ||
982 | { | ||
983 | int i, err, index, sds_mbx_size, rds_mbx_size; | ||
984 | u8 num_sds, num_rds; | ||
985 | u32 *buf, intrpt_id, intr_mask, cap = 0; | ||
986 | struct qlcnic_host_sds_ring *sds; | ||
987 | struct qlcnic_host_rds_ring *rds; | ||
988 | struct qlcnic_sds_mbx sds_mbx; | ||
989 | struct qlcnic_rds_mbx rds_mbx; | ||
990 | struct qlcnic_cmd_args cmd; | ||
991 | struct qlcnic_rcv_mbx_out *mbx_out; | ||
992 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
993 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
994 | num_rds = adapter->max_rds_rings; | ||
995 | |||
996 | if (adapter->max_sds_rings <= QLCNIC_MAX_RING_SETS) | ||
997 | num_sds = adapter->max_sds_rings; | ||
998 | else | ||
999 | num_sds = QLCNIC_MAX_RING_SETS; | ||
1000 | |||
1001 | sds_mbx_size = sizeof(struct qlcnic_sds_mbx); | ||
1002 | rds_mbx_size = sizeof(struct qlcnic_rds_mbx); | ||
1003 | cap = QLCNIC_CAP0_LEGACY_CONTEXT; | ||
1004 | |||
1005 | if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) | ||
1006 | cap |= QLC_83XX_FW_CAP_LRO_MSS; | ||
1007 | |||
1008 | /* set mailbox hdr and capabilities */ | ||
1009 | qlcnic_alloc_mbx_args(&cmd, adapter, | ||
1010 | QLCNIC_CMD_CREATE_RX_CTX); | ||
1011 | cmd.req.arg[1] = cap; | ||
1012 | cmd.req.arg[5] = 1 | (num_rds << 5) | (num_sds << 8) | | ||
1013 | (QLC_83XX_HOST_RDS_MODE_UNIQUE << 16); | ||
1014 | /* set up status rings, mbx 8-57/87 */ | ||
1015 | index = QLC_83XX_HOST_SDS_MBX_IDX; | ||
1016 | for (i = 0; i < num_sds; i++) { | ||
1017 | memset(&sds_mbx, 0, sds_mbx_size); | ||
1018 | sds = &recv_ctx->sds_rings[i]; | ||
1019 | sds->consumer = 0; | ||
1020 | memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds)); | ||
1021 | sds_mbx.phy_addr = sds->phys_addr; | ||
1022 | sds_mbx.sds_ring_size = sds->num_desc; | ||
1023 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
1024 | intrpt_id = ahw->intr_tbl[i].id; | ||
1025 | else | ||
1026 | intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID); | ||
1027 | if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) | ||
1028 | sds_mbx.intrpt_id = intrpt_id; | ||
1029 | else | ||
1030 | sds_mbx.intrpt_id = 0xffff; | ||
1031 | sds_mbx.intrpt_val = 0; | ||
1032 | buf = &cmd.req.arg[index]; | ||
1033 | memcpy(buf, &sds_mbx, sds_mbx_size); | ||
1034 | index += sds_mbx_size / sizeof(u32); | ||
1035 | } | ||
1036 | /* set up receive rings, mbx 88-111/135 */ | ||
1037 | index = QLCNIC_HOST_RDS_MBX_IDX; | ||
1038 | rds = &recv_ctx->rds_rings[0]; | ||
1039 | rds->producer = 0; | ||
1040 | memset(&rds_mbx, 0, rds_mbx_size); | ||
1041 | rds_mbx.phy_addr_reg = rds->phys_addr; | ||
1042 | rds_mbx.reg_ring_sz = rds->dma_size; | ||
1043 | rds_mbx.reg_ring_len = rds->num_desc; | ||
1044 | /* Jumbo ring */ | ||
1045 | rds = &recv_ctx->rds_rings[1]; | ||
1046 | rds->producer = 0; | ||
1047 | rds_mbx.phy_addr_jmb = rds->phys_addr; | ||
1048 | rds_mbx.jmb_ring_sz = rds->dma_size; | ||
1049 | rds_mbx.jmb_ring_len = rds->num_desc; | ||
1050 | buf = &cmd.req.arg[index]; | ||
1051 | memcpy(buf, &rds_mbx, rds_mbx_size); | ||
1052 | |||
1053 | /* send the mailbox command */ | ||
1054 | err = ahw->hw_ops->mbx_cmd(adapter, &cmd); | ||
1055 | if (err) { | ||
1056 | dev_err(&adapter->pdev->dev, | ||
1057 | "Failed to create Rx ctx in firmware%d\n", err); | ||
1058 | goto out; | ||
1059 | } | ||
1060 | mbx_out = (struct qlcnic_rcv_mbx_out *)&cmd.rsp.arg[1]; | ||
1061 | recv_ctx->context_id = mbx_out->ctx_id; | ||
1062 | recv_ctx->state = mbx_out->state; | ||
1063 | recv_ctx->virt_port = mbx_out->vport_id; | ||
1064 | dev_info(&adapter->pdev->dev, "Rx Context[%d] Created, state:0x%x\n", | ||
1065 | recv_ctx->context_id, recv_ctx->state); | ||
1066 | /* Receive descriptor ring */ | ||
1067 | /* Standard ring */ | ||
1068 | rds = &recv_ctx->rds_rings[0]; | ||
1069 | rds->crb_rcv_producer = ahw->pci_base0 + | ||
1070 | mbx_out->host_prod[0].reg_buf; | ||
1071 | /* Jumbo ring */ | ||
1072 | rds = &recv_ctx->rds_rings[1]; | ||
1073 | rds->crb_rcv_producer = ahw->pci_base0 + | ||
1074 | mbx_out->host_prod[0].jmb_buf; | ||
1075 | /* status descriptor ring */ | ||
1076 | for (i = 0; i < num_sds; i++) { | ||
1077 | sds = &recv_ctx->sds_rings[i]; | ||
1078 | sds->crb_sts_consumer = ahw->pci_base0 + | ||
1079 | mbx_out->host_csmr[i]; | ||
1080 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
1081 | intr_mask = ahw->intr_tbl[i].src; | ||
1082 | else | ||
1083 | intr_mask = QLCRDX(ahw, QLCNIC_DEF_INT_MASK); | ||
1084 | sds->crb_intr_mask = ahw->pci_base0 + intr_mask; | ||
1085 | } | ||
1086 | |||
1087 | if (adapter->max_sds_rings > QLCNIC_MAX_RING_SETS) | ||
1088 | err = qlcnic_83xx_add_rings(adapter); | ||
1089 | out: | ||
1090 | qlcnic_free_mbx_args(&cmd); | ||
1091 | return err; | ||
1092 | } | ||
1093 | |||
1094 | int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter, | ||
1095 | struct qlcnic_host_tx_ring *tx, int ring) | ||
1096 | { | ||
1097 | int err; | ||
1098 | u16 msix_id; | ||
1099 | u32 *buf, intr_mask; | ||
1100 | struct qlcnic_cmd_args cmd; | ||
1101 | struct qlcnic_tx_mbx mbx; | ||
1102 | struct qlcnic_tx_mbx_out *mbx_out; | ||
1103 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
1104 | |||
1105 | /* Reset host resources */ | ||
1106 | tx->producer = 0; | ||
1107 | tx->sw_consumer = 0; | ||
1108 | *(tx->hw_consumer) = 0; | ||
1109 | |||
1110 | memset(&mbx, 0, sizeof(struct qlcnic_tx_mbx)); | ||
1111 | |||
1112 | /* setup mailbox inbox registerss */ | ||
1113 | mbx.phys_addr = tx->phys_addr; | ||
1114 | mbx.cnsmr_index = tx->hw_cons_phys_addr; | ||
1115 | mbx.size = tx->num_desc; | ||
1116 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
1117 | msix_id = ahw->intr_tbl[adapter->max_sds_rings + ring].id; | ||
1118 | else | ||
1119 | msix_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID); | ||
1120 | if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) | ||
1121 | mbx.intr_id = msix_id; | ||
1122 | else | ||
1123 | mbx.intr_id = 0xffff; | ||
1124 | mbx.src = 0; | ||
1125 | |||
1126 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX); | ||
1127 | cmd.req.arg[1] = QLCNIC_CAP0_LEGACY_CONTEXT; | ||
1128 | cmd.req.arg[5] = QLCNIC_MAX_TX_QUEUES; | ||
1129 | buf = &cmd.req.arg[6]; | ||
1130 | memcpy(buf, &mbx, sizeof(struct qlcnic_tx_mbx)); | ||
1131 | /* send the mailbox command*/ | ||
1132 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1133 | if (err) { | ||
1134 | dev_err(&adapter->pdev->dev, | ||
1135 | "Failed to create Tx ctx in firmware 0x%x\n", err); | ||
1136 | goto out; | ||
1137 | } | ||
1138 | mbx_out = (struct qlcnic_tx_mbx_out *)&cmd.rsp.arg[2]; | ||
1139 | tx->crb_cmd_producer = ahw->pci_base0 + mbx_out->host_prod; | ||
1140 | tx->ctx_id = mbx_out->ctx_id; | ||
1141 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { | ||
1142 | intr_mask = ahw->intr_tbl[adapter->max_sds_rings + ring].src; | ||
1143 | tx->crb_intr_mask = ahw->pci_base0 + intr_mask; | ||
1144 | } | ||
1145 | dev_info(&adapter->pdev->dev, "Tx Context[0x%x] Created, state:0x%x\n", | ||
1146 | tx->ctx_id, mbx_out->state); | ||
1147 | out: | ||
1148 | qlcnic_free_mbx_args(&cmd); | ||
1149 | return err; | ||
1150 | } | ||
1151 | |||
1152 | void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *adapter, | ||
1153 | int enable) | ||
1154 | { | ||
1155 | struct qlcnic_cmd_args cmd; | ||
1156 | int status; | ||
1157 | |||
1158 | if (enable) { | ||
1159 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INIT_NIC_FUNC); | ||
1160 | cmd.req.arg[1] = 1 | BIT_0; | ||
1161 | } else { | ||
1162 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_STOP_NIC_FUNC); | ||
1163 | cmd.req.arg[1] = 0 | BIT_0; | ||
1164 | } | ||
1165 | status = qlcnic_issue_cmd(adapter, &cmd); | ||
1166 | if (status) | ||
1167 | dev_err(&adapter->pdev->dev, | ||
1168 | "Failed to %s in NIC IDC function event.\n", | ||
1169 | (enable ? "register" : "unregister")); | ||
1170 | |||
1171 | qlcnic_free_mbx_args(&cmd); | ||
1172 | } | ||
1173 | |||
1174 | int qlcnic_83xx_set_port_config(struct qlcnic_adapter *adapter) | ||
1175 | { | ||
1176 | struct qlcnic_cmd_args cmd; | ||
1177 | int err; | ||
1178 | |||
1179 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_PORT_CONFIG); | ||
1180 | cmd.req.arg[1] = adapter->ahw->port_config; | ||
1181 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1182 | if (err) | ||
1183 | dev_info(&adapter->pdev->dev, "Set Port Config failed.\n"); | ||
1184 | qlcnic_free_mbx_args(&cmd); | ||
1185 | return err; | ||
1186 | } | ||
1187 | |||
1188 | int qlcnic_83xx_get_port_config(struct qlcnic_adapter *adapter) | ||
1189 | { | ||
1190 | struct qlcnic_cmd_args cmd; | ||
1191 | int err; | ||
1192 | |||
1193 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PORT_CONFIG); | ||
1194 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1195 | if (err) | ||
1196 | dev_info(&adapter->pdev->dev, "Get Port config failed\n"); | ||
1197 | else | ||
1198 | adapter->ahw->port_config = cmd.rsp.arg[1]; | ||
1199 | qlcnic_free_mbx_args(&cmd); | ||
1200 | return err; | ||
1201 | } | ||
1202 | |||
1203 | int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *adapter, int enable) | ||
1204 | { | ||
1205 | int err; | ||
1206 | u32 temp; | ||
1207 | struct qlcnic_cmd_args cmd; | ||
1208 | |||
1209 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_EVENT); | ||
1210 | temp = adapter->recv_ctx->context_id << 16; | ||
1211 | cmd.req.arg[1] = (enable ? 1 : 0) | BIT_8 | temp; | ||
1212 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1213 | if (err) | ||
1214 | dev_info(&adapter->pdev->dev, | ||
1215 | "Setup linkevent mailbox failed\n"); | ||
1216 | qlcnic_free_mbx_args(&cmd); | ||
1217 | return err; | ||
1218 | } | ||
1219 | |||
1220 | int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) | ||
1221 | { | ||
1222 | int err; | ||
1223 | u32 temp; | ||
1224 | struct qlcnic_cmd_args cmd; | ||
1225 | |||
1226 | if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED) | ||
1227 | return -EIO; | ||
1228 | |||
1229 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_MAC_RX_MODE); | ||
1230 | temp = adapter->recv_ctx->context_id << 16; | ||
1231 | cmd.req.arg[1] = (mode ? 1 : 0) | temp; | ||
1232 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1233 | if (err) | ||
1234 | dev_info(&adapter->pdev->dev, | ||
1235 | "Promiscous mode config failed\n"); | ||
1236 | qlcnic_free_mbx_args(&cmd); | ||
1237 | |||
1238 | return err; | ||
1239 | } | ||
1240 | |||
1241 | int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode) | ||
1242 | { | ||
1243 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
1244 | int status = 0; | ||
1245 | u32 config; | ||
1246 | |||
1247 | status = qlcnic_83xx_get_port_config(adapter); | ||
1248 | if (status) | ||
1249 | return status; | ||
1250 | |||
1251 | config = ahw->port_config; | ||
1252 | |||
1253 | if (mode == QLCNIC_ILB_MODE) | ||
1254 | ahw->port_config |= QLC_83XX_CFG_LOOPBACK_HSS; | ||
1255 | if (mode == QLCNIC_ELB_MODE) | ||
1256 | ahw->port_config |= QLC_83XX_CFG_LOOPBACK_EXT; | ||
1257 | |||
1258 | status = qlcnic_83xx_set_port_config(adapter); | ||
1259 | if (status) { | ||
1260 | dev_err(&adapter->pdev->dev, | ||
1261 | "Failed to Set Loopback Mode = 0x%x.\n", | ||
1262 | ahw->port_config); | ||
1263 | ahw->port_config = config; | ||
1264 | return status; | ||
1265 | } | ||
1266 | |||
1267 | qlcnic_sre_macaddr_change(adapter, adapter->mac_addr, 0, | ||
1268 | QLCNIC_MAC_ADD); | ||
1269 | return status; | ||
1270 | } | ||
1271 | |||
1272 | int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode) | ||
1273 | { | ||
1274 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
1275 | int status = 0; | ||
1276 | u32 config = ahw->port_config; | ||
1277 | |||
1278 | if (mode == QLCNIC_ILB_MODE) | ||
1279 | ahw->port_config &= ~QLC_83XX_CFG_LOOPBACK_HSS; | ||
1280 | if (mode == QLCNIC_ELB_MODE) | ||
1281 | ahw->port_config &= ~QLC_83XX_CFG_LOOPBACK_EXT; | ||
1282 | |||
1283 | status = qlcnic_83xx_set_port_config(adapter); | ||
1284 | if (status) { | ||
1285 | dev_err(&adapter->pdev->dev, | ||
1286 | "Failed to Clear Loopback Mode = 0x%x.\n", | ||
1287 | ahw->port_config); | ||
1288 | ahw->port_config = config; | ||
1289 | return status; | ||
1290 | } | ||
1291 | |||
1292 | qlcnic_sre_macaddr_change(adapter, adapter->mac_addr, 0, | ||
1293 | QLCNIC_MAC_DEL); | ||
1294 | return status; | ||
1295 | } | ||
1296 | |||
1297 | void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, | ||
1298 | int mode) | ||
1299 | { | ||
1300 | int err; | ||
1301 | u32 temp; | ||
1302 | struct qlcnic_cmd_args cmd; | ||
1303 | |||
1304 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_IP_ADDR); | ||
1305 | if (mode == QLCNIC_IP_UP) { | ||
1306 | temp = adapter->recv_ctx->context_id << 16; | ||
1307 | cmd.req.arg[1] = 1 | temp; | ||
1308 | } else { | ||
1309 | temp = adapter->recv_ctx->context_id << 16; | ||
1310 | cmd.req.arg[1] = 2 | temp; | ||
1311 | } | ||
1312 | cmd.req.arg[2] = ntohl(ip); | ||
1313 | |||
1314 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1315 | if (err != QLCNIC_RCODE_SUCCESS) | ||
1316 | dev_err(&adapter->netdev->dev, | ||
1317 | "could not notify %s IP 0x%x request\n", | ||
1318 | (mode == QLCNIC_IP_UP) ? "Add" : "Remove", ip); | ||
1319 | qlcnic_free_mbx_args(&cmd); | ||
1320 | } | ||
1321 | |||
1322 | int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *adapter, int mode) | ||
1323 | { | ||
1324 | int err; | ||
1325 | u32 temp, arg1; | ||
1326 | struct qlcnic_cmd_args cmd; | ||
1327 | |||
1328 | if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED) | ||
1329 | return 0; | ||
1330 | |||
1331 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_HW_LRO); | ||
1332 | temp = adapter->recv_ctx->context_id << 16; | ||
1333 | arg1 = (mode ? (BIT_0 | BIT_1 | BIT_3) : 0) | temp; | ||
1334 | cmd.req.arg[1] = arg1; | ||
1335 | |||
1336 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1337 | if (err) | ||
1338 | dev_info(&adapter->pdev->dev, "LRO config failed\n"); | ||
1339 | qlcnic_free_mbx_args(&cmd); | ||
1340 | |||
1341 | return err; | ||
1342 | } | ||
1343 | |||
1344 | int qlcnic_83xx_config_rss(struct qlcnic_adapter *adapter, int enable) | ||
1345 | { | ||
1346 | int err; | ||
1347 | u32 word; | ||
1348 | struct qlcnic_cmd_args cmd; | ||
1349 | const u64 key[] = { 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL, | ||
1350 | 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL, | ||
1351 | 0x255b0ec26d5a56daULL }; | ||
1352 | |||
1353 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_RSS); | ||
1354 | |||
1355 | /* | ||
1356 | * RSS request: | ||
1357 | * bits 3-0: Rsvd | ||
1358 | * 5-4: hash_type_ipv4 | ||
1359 | * 7-6: hash_type_ipv6 | ||
1360 | * 8: enable | ||
1361 | * 9: use indirection table | ||
1362 | * 16-31: indirection table mask | ||
1363 | */ | ||
1364 | word = ((u32)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) | | ||
1365 | ((u32)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) | | ||
1366 | ((u32)(enable & 0x1) << 8) | | ||
1367 | ((0x7ULL) << 16); | ||
1368 | cmd.req.arg[1] = (adapter->recv_ctx->context_id); | ||
1369 | cmd.req.arg[2] = word; | ||
1370 | memcpy(&cmd.req.arg[4], key, sizeof(key)); | ||
1371 | |||
1372 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1373 | |||
1374 | if (err) | ||
1375 | dev_info(&adapter->pdev->dev, "RSS config failed\n"); | ||
1376 | qlcnic_free_mbx_args(&cmd); | ||
1377 | |||
1378 | return err; | ||
1379 | |||
1380 | } | ||
1381 | |||
1382 | int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, | ||
1383 | __le16 vlan_id, u8 op) | ||
1384 | { | ||
1385 | int err; | ||
1386 | u32 *buf; | ||
1387 | struct qlcnic_cmd_args cmd; | ||
1388 | struct qlcnic_macvlan_mbx mv; | ||
1389 | |||
1390 | if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED) | ||
1391 | return -EIO; | ||
1392 | |||
1393 | err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN); | ||
1394 | if (err) | ||
1395 | return err; | ||
1396 | cmd.req.arg[1] = op | (1 << 8) | | ||
1397 | (adapter->recv_ctx->context_id << 16); | ||
1398 | |||
1399 | mv.vlan = le16_to_cpu(vlan_id); | ||
1400 | memcpy(&mv.mac, addr, ETH_ALEN); | ||
1401 | buf = &cmd.req.arg[2]; | ||
1402 | memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx)); | ||
1403 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1404 | if (err) | ||
1405 | dev_err(&adapter->pdev->dev, | ||
1406 | "MAC-VLAN %s to CAM failed, err=%d.\n", | ||
1407 | ((op == 1) ? "add " : "delete "), err); | ||
1408 | qlcnic_free_mbx_args(&cmd); | ||
1409 | return err; | ||
1410 | } | ||
1411 | |||
1412 | void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *adapter, u64 *addr, | ||
1413 | __le16 vlan_id) | ||
1414 | { | ||
1415 | u8 mac[ETH_ALEN]; | ||
1416 | memcpy(&mac, addr, ETH_ALEN); | ||
1417 | qlcnic_83xx_sre_macaddr_change(adapter, mac, vlan_id, QLCNIC_MAC_ADD); | ||
1418 | } | ||
1419 | |||
1420 | void qlcnic_83xx_configure_mac(struct qlcnic_adapter *adapter, u8 *mac, | ||
1421 | u8 type, struct qlcnic_cmd_args *cmd) | ||
1422 | { | ||
1423 | switch (type) { | ||
1424 | case QLCNIC_SET_STATION_MAC: | ||
1425 | case QLCNIC_SET_FAC_DEF_MAC: | ||
1426 | memcpy(&cmd->req.arg[2], mac, sizeof(u32)); | ||
1427 | memcpy(&cmd->req.arg[3], &mac[4], sizeof(u16)); | ||
1428 | break; | ||
1429 | } | ||
1430 | cmd->req.arg[1] = type; | ||
1431 | } | ||
1432 | |||
1433 | int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac) | ||
1434 | { | ||
1435 | int err, i; | ||
1436 | struct qlcnic_cmd_args cmd; | ||
1437 | u32 mac_low, mac_high; | ||
1438 | |||
1439 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS); | ||
1440 | qlcnic_83xx_configure_mac(adapter, mac, QLCNIC_GET_CURRENT_MAC, &cmd); | ||
1441 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1442 | |||
1443 | if (err == QLCNIC_RCODE_SUCCESS) { | ||
1444 | mac_low = cmd.rsp.arg[1]; | ||
1445 | mac_high = cmd.rsp.arg[2]; | ||
1446 | |||
1447 | for (i = 0; i < 2; i++) | ||
1448 | mac[i] = (u8) (mac_high >> ((1 - i) * 8)); | ||
1449 | for (i = 2; i < 6; i++) | ||
1450 | mac[i] = (u8) (mac_low >> ((5 - i) * 8)); | ||
1451 | } else { | ||
1452 | dev_err(&adapter->pdev->dev, "Failed to get mac address%d\n", | ||
1453 | err); | ||
1454 | err = -EIO; | ||
1455 | } | ||
1456 | qlcnic_free_mbx_args(&cmd); | ||
1457 | return err; | ||
1458 | } | ||
1459 | |||
1460 | void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *adapter) | ||
1461 | { | ||
1462 | int err; | ||
1463 | u32 temp; | ||
1464 | struct qlcnic_cmd_args cmd; | ||
1465 | struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal; | ||
1466 | |||
1467 | if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED) | ||
1468 | return; | ||
1469 | |||
1470 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL); | ||
1471 | cmd.req.arg[1] = 1 | (adapter->recv_ctx->context_id << 16); | ||
1472 | cmd.req.arg[3] = coal->flag; | ||
1473 | temp = coal->rx_time_us << 16; | ||
1474 | cmd.req.arg[2] = coal->rx_packets | temp; | ||
1475 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1476 | if (err != QLCNIC_RCODE_SUCCESS) | ||
1477 | dev_info(&adapter->pdev->dev, | ||
1478 | "Failed to send interrupt coalescence parameters\n"); | ||
1479 | qlcnic_free_mbx_args(&cmd); | ||
1480 | } | ||
1481 | |||
1482 | static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter, | ||
1483 | u32 data[]) | ||
1484 | { | ||
1485 | u8 link_status, duplex; | ||
1486 | /* link speed */ | ||
1487 | link_status = LSB(data[3]) & 1; | ||
1488 | adapter->ahw->link_speed = MSW(data[2]); | ||
1489 | adapter->ahw->link_autoneg = MSB(MSW(data[3])); | ||
1490 | adapter->ahw->module_type = MSB(LSW(data[3])); | ||
1491 | duplex = LSB(MSW(data[3])); | ||
1492 | if (duplex) | ||
1493 | adapter->ahw->link_duplex = DUPLEX_FULL; | ||
1494 | else | ||
1495 | adapter->ahw->link_duplex = DUPLEX_HALF; | ||
1496 | adapter->ahw->has_link_events = 1; | ||
1497 | qlcnic_advert_link_change(adapter, link_status); | ||
1498 | } | ||
1499 | |||
1500 | irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data) | ||
1501 | { | ||
1502 | struct qlcnic_adapter *adapter = data; | ||
1503 | qlcnic_83xx_process_aen(adapter); | ||
1504 | return IRQ_HANDLED; | ||
1505 | } | ||
1506 | |||
1507 | int qlcnic_enable_eswitch(struct qlcnic_adapter *adapter, u8 port, u8 enable) | ||
1508 | { | ||
1509 | int err = -EIO; | ||
1510 | struct qlcnic_cmd_args cmd; | ||
1511 | |||
1512 | if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) { | ||
1513 | dev_err(&adapter->pdev->dev, | ||
1514 | "%s: Error, invoked by non management func\n", | ||
1515 | __func__); | ||
1516 | return err; | ||
1517 | } | ||
1518 | |||
1519 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_TOGGLE_ESWITCH); | ||
1520 | cmd.req.arg[1] = (port & 0xf) | BIT_4; | ||
1521 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1522 | |||
1523 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
1524 | dev_err(&adapter->pdev->dev, "Failed to enable eswitch%d\n", | ||
1525 | err); | ||
1526 | err = -EIO; | ||
1527 | } | ||
1528 | qlcnic_free_mbx_args(&cmd); | ||
1529 | |||
1530 | return err; | ||
1531 | |||
1532 | } | ||
1533 | |||
1534 | int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *adapter, | ||
1535 | struct qlcnic_info *nic) | ||
1536 | { | ||
1537 | int i, err = -EIO; | ||
1538 | struct qlcnic_cmd_args cmd; | ||
1539 | |||
1540 | if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) { | ||
1541 | dev_err(&adapter->pdev->dev, | ||
1542 | "%s: Error, invoked by non management func\n", | ||
1543 | __func__); | ||
1544 | return err; | ||
1545 | } | ||
1546 | |||
1547 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO); | ||
1548 | cmd.req.arg[1] = (nic->pci_func << 16); | ||
1549 | cmd.req.arg[2] = 0x1 << 16; | ||
1550 | cmd.req.arg[3] = nic->phys_port | (nic->switch_mode << 16); | ||
1551 | cmd.req.arg[4] = nic->capabilities; | ||
1552 | cmd.req.arg[5] = (nic->max_mac_filters & 0xFF) | ((nic->max_mtu) << 16); | ||
1553 | cmd.req.arg[6] = (nic->max_tx_ques) | ((nic->max_rx_ques) << 16); | ||
1554 | cmd.req.arg[7] = (nic->min_tx_bw) | ((nic->max_tx_bw) << 16); | ||
1555 | for (i = 8; i < 32; i++) | ||
1556 | cmd.req.arg[i] = 0; | ||
1557 | |||
1558 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1559 | |||
1560 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
1561 | dev_err(&adapter->pdev->dev, "Failed to set nic info%d\n", | ||
1562 | err); | ||
1563 | err = -EIO; | ||
1564 | } | ||
1565 | |||
1566 | qlcnic_free_mbx_args(&cmd); | ||
1567 | |||
1568 | return err; | ||
1569 | } | ||
1570 | |||
1571 | int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter, | ||
1572 | struct qlcnic_info *npar_info, u8 func_id) | ||
1573 | { | ||
1574 | int err; | ||
1575 | u32 temp; | ||
1576 | u8 op = 0; | ||
1577 | struct qlcnic_cmd_args cmd; | ||
1578 | |||
1579 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO); | ||
1580 | if (func_id != adapter->ahw->pci_func) { | ||
1581 | temp = func_id << 16; | ||
1582 | cmd.req.arg[1] = op | BIT_31 | temp; | ||
1583 | } else { | ||
1584 | cmd.req.arg[1] = adapter->ahw->pci_func << 16; | ||
1585 | } | ||
1586 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1587 | if (err) { | ||
1588 | dev_info(&adapter->pdev->dev, | ||
1589 | "Failed to get nic info %d\n", err); | ||
1590 | goto out; | ||
1591 | } | ||
1592 | |||
1593 | npar_info->op_type = cmd.rsp.arg[1]; | ||
1594 | npar_info->pci_func = cmd.rsp.arg[2] & 0xFFFF; | ||
1595 | npar_info->op_mode = (cmd.rsp.arg[2] & 0xFFFF0000) >> 16; | ||
1596 | npar_info->phys_port = cmd.rsp.arg[3] & 0xFFFF; | ||
1597 | npar_info->switch_mode = (cmd.rsp.arg[3] & 0xFFFF0000) >> 16; | ||
1598 | npar_info->capabilities = cmd.rsp.arg[4]; | ||
1599 | npar_info->max_mac_filters = cmd.rsp.arg[5] & 0xFF; | ||
1600 | npar_info->max_mtu = (cmd.rsp.arg[5] & 0xFFFF0000) >> 16; | ||
1601 | npar_info->max_tx_ques = cmd.rsp.arg[6] & 0xFFFF; | ||
1602 | npar_info->max_rx_ques = (cmd.rsp.arg[6] & 0xFFFF0000) >> 16; | ||
1603 | npar_info->min_tx_bw = cmd.rsp.arg[7] & 0xFFFF; | ||
1604 | npar_info->max_tx_bw = (cmd.rsp.arg[7] & 0xFFFF0000) >> 16; | ||
1605 | if (cmd.rsp.arg[8] & 0x1) | ||
1606 | npar_info->max_bw_reg_offset = (cmd.rsp.arg[8] & 0x7FFE) >> 1; | ||
1607 | if (cmd.rsp.arg[8] & 0x10000) { | ||
1608 | temp = (cmd.rsp.arg[8] & 0x7FFE0000) >> 17; | ||
1609 | npar_info->max_linkspeed_reg_offset = temp; | ||
1610 | } | ||
1611 | |||
1612 | out: | ||
1613 | qlcnic_free_mbx_args(&cmd); | ||
1614 | return err; | ||
1615 | } | ||
1616 | |||
1617 | int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter, | ||
1618 | struct qlcnic_pci_info *pci_info) | ||
1619 | { | ||
1620 | int i, err = 0, j = 0; | ||
1621 | u32 temp; | ||
1622 | struct qlcnic_cmd_args cmd; | ||
1623 | |||
1624 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO); | ||
1625 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1626 | |||
1627 | adapter->ahw->act_pci_func = 0; | ||
1628 | if (err == QLCNIC_RCODE_SUCCESS) { | ||
1629 | pci_info->func_count = cmd.rsp.arg[1] & 0xFF; | ||
1630 | dev_info(&adapter->pdev->dev, | ||
1631 | "%s: total functions = %d\n", | ||
1632 | __func__, pci_info->func_count); | ||
1633 | for (i = 2, j = 0; j < QLCNIC_MAX_PCI_FUNC; j++, pci_info++) { | ||
1634 | pci_info->id = cmd.rsp.arg[i] & 0xFFFF; | ||
1635 | pci_info->active = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16; | ||
1636 | i++; | ||
1637 | pci_info->type = cmd.rsp.arg[i] & 0xFFFF; | ||
1638 | if (pci_info->type == QLCNIC_TYPE_NIC) | ||
1639 | adapter->ahw->act_pci_func++; | ||
1640 | temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16; | ||
1641 | pci_info->default_port = temp; | ||
1642 | i++; | ||
1643 | pci_info->tx_min_bw = cmd.rsp.arg[i] & 0xFFFF; | ||
1644 | temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16; | ||
1645 | pci_info->tx_max_bw = temp; | ||
1646 | i = i + 2; | ||
1647 | memcpy(pci_info->mac, &cmd.rsp.arg[i], ETH_ALEN - 2); | ||
1648 | i++; | ||
1649 | memcpy(pci_info->mac + sizeof(u32), &cmd.rsp.arg[i], 2); | ||
1650 | i = i + 3; | ||
1651 | |||
1652 | dev_info(&adapter->pdev->dev, "%s:\n" | ||
1653 | "\tid = %d active = %d type = %d\n" | ||
1654 | "\tport = %d min bw = %d max bw = %d\n" | ||
1655 | "\tmac_addr = %pM\n", __func__, | ||
1656 | pci_info->id, pci_info->active, pci_info->type, | ||
1657 | pci_info->default_port, pci_info->tx_min_bw, | ||
1658 | pci_info->tx_max_bw, pci_info->mac); | ||
1659 | } | ||
1660 | } else { | ||
1661 | dev_err(&adapter->pdev->dev, "Failed to get PCI Info%d\n", | ||
1662 | err); | ||
1663 | err = -EIO; | ||
1664 | } | ||
1665 | |||
1666 | qlcnic_free_mbx_args(&cmd); | ||
1667 | |||
1668 | return err; | ||
1669 | } | ||
1670 | |||
1671 | int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *adapter, bool op_type) | ||
1672 | { | ||
1673 | int i, index, err; | ||
1674 | bool type; | ||
1675 | u8 max_ints; | ||
1676 | u32 val, temp; | ||
1677 | struct qlcnic_cmd_args cmd; | ||
1678 | |||
1679 | max_ints = adapter->ahw->num_msix; | ||
1680 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTRPT); | ||
1681 | cmd.req.arg[1] = max_ints; | ||
1682 | for (i = 0, index = 2; i < max_ints; i++) { | ||
1683 | type = op_type ? QLCNIC_INTRPT_ADD : QLCNIC_INTRPT_DEL; | ||
1684 | val = type | (adapter->ahw->intr_tbl[i].type << 4); | ||
1685 | if (adapter->ahw->intr_tbl[i].type == QLCNIC_INTRPT_MSIX) | ||
1686 | val |= (adapter->ahw->intr_tbl[i].id << 16); | ||
1687 | cmd.req.arg[index++] = val; | ||
1688 | } | ||
1689 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1690 | if (err) { | ||
1691 | dev_err(&adapter->pdev->dev, | ||
1692 | "Failed to configure interrupts 0x%x\n", err); | ||
1693 | goto out; | ||
1694 | } | ||
1695 | |||
1696 | max_ints = cmd.rsp.arg[1]; | ||
1697 | for (i = 0, index = 2; i < max_ints; i++, index += 2) { | ||
1698 | val = cmd.rsp.arg[index]; | ||
1699 | if (LSB(val)) { | ||
1700 | dev_info(&adapter->pdev->dev, | ||
1701 | "Can't configure interrupt %d\n", | ||
1702 | adapter->ahw->intr_tbl[i].id); | ||
1703 | continue; | ||
1704 | } | ||
1705 | if (op_type) { | ||
1706 | adapter->ahw->intr_tbl[i].id = MSW(val); | ||
1707 | adapter->ahw->intr_tbl[i].enabled = 1; | ||
1708 | temp = cmd.rsp.arg[index + 1]; | ||
1709 | adapter->ahw->intr_tbl[i].src = temp; | ||
1710 | } else { | ||
1711 | adapter->ahw->intr_tbl[i].id = i; | ||
1712 | adapter->ahw->intr_tbl[i].enabled = 0; | ||
1713 | adapter->ahw->intr_tbl[i].src = 0; | ||
1714 | } | ||
1715 | } | ||
1716 | out: | ||
1717 | qlcnic_free_mbx_args(&cmd); | ||
1718 | return err; | ||
1719 | } | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h new file mode 100644 index 000000000000..9d707be27ca2 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | |||
@@ -0,0 +1,250 @@ | |||
1 | #ifndef __QLCNIC_83XX_HW_H | ||
2 | #define __QLCNIC_83XX_HW_H | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | #include <linux/etherdevice.h> | ||
6 | #include "qlcnic_hw.h" | ||
7 | |||
8 | /* Directly mapped registers */ | ||
9 | #define QLC_83XX_CRB_WIN_BASE 0x3800 | ||
10 | #define QLC_83XX_CRB_WIN_FUNC(f) (QLC_83XX_CRB_WIN_BASE+((f)*4)) | ||
11 | #define QLC_83XX_SEM_LOCK_BASE 0x3840 | ||
12 | #define QLC_83XX_SEM_UNLOCK_BASE 0x3844 | ||
13 | #define QLC_83XX_SEM_LOCK_FUNC(f) (QLC_83XX_SEM_LOCK_BASE+((f)*8)) | ||
14 | #define QLC_83XX_SEM_UNLOCK_FUNC(f) (QLC_83XX_SEM_UNLOCK_BASE+((f)*8)) | ||
15 | #define QLC_83XX_LINK_STATE(f) (0x3698+((f) > 7 ? 4 : 0)) | ||
16 | #define QLC_83XX_LINK_SPEED(f) (0x36E0+(((f) >> 2) * 4)) | ||
17 | #define QLC_83XX_LINK_SPEED_FACTOR 10 | ||
18 | #define QLC_83xx_FUNC_VAL(v, f) ((v) & (1 << (f * 4))) | ||
19 | #define QLC_83XX_INTX_PTR 0x38C0 | ||
20 | #define QLC_83XX_INTX_TRGR 0x38C4 | ||
21 | #define QLC_83XX_INTX_MASK 0x38C8 | ||
22 | |||
23 | #define QLC_83XX_DRV_LOCK_WAIT_COUNTER 100 | ||
24 | #define QLC_83XX_DRV_LOCK_WAIT_DELAY 20 | ||
25 | #define QLC_83XX_NEED_DRV_LOCK_RECOVERY 1 | ||
26 | #define QLC_83XX_DRV_LOCK_RECOVERY_IN_PROGRESS 2 | ||
27 | #define QLC_83XX_MAX_DRV_LOCK_RECOVERY_ATTEMPT 3 | ||
28 | #define QLC_83XX_DRV_LOCK_RECOVERY_DELAY 200 | ||
29 | #define QLC_83XX_DRV_LOCK_RECOVERY_STATUS_MASK 0x3 | ||
30 | |||
31 | #define QLC_83XX_NO_NIC_RESOURCE 0x5 | ||
32 | #define QLC_83XX_MAC_PRESENT 0xC | ||
33 | #define QLC_83XX_MAC_ABSENT 0xD | ||
34 | |||
35 | |||
36 | #define QLC_83XX_FLASH_SECTOR_SIZE (64 * 1024) | ||
37 | |||
38 | /* PEG status definitions */ | ||
39 | #define QLC_83XX_CMDPEG_COMPLETE 0xff01 | ||
40 | #define QLC_83XX_VALID_INTX_BIT30(val) ((val) & BIT_30) | ||
41 | #define QLC_83XX_VALID_INTX_BIT31(val) ((val) & BIT_31) | ||
42 | #define QLC_83XX_INTX_FUNC(val) ((val) & 0xFF) | ||
43 | #define QLC_83XX_LEGACY_INTX_MAX_RETRY 100 | ||
44 | #define QLC_83XX_LEGACY_INTX_DELAY 4 | ||
45 | #define QLC_83XX_REG_DESC 1 | ||
46 | #define QLC_83XX_LRO_DESC 2 | ||
47 | #define QLC_83XX_CTRL_DESC 3 | ||
48 | #define QLC_83XX_FW_CAPABILITY_TSO BIT_6 | ||
49 | #define QLC_83XX_FW_CAP_LRO_MSS BIT_17 | ||
50 | #define QLC_83XX_HOST_RDS_MODE_UNIQUE 0 | ||
51 | #define QLC_83XX_HOST_SDS_MBX_IDX 8 | ||
52 | |||
53 | #define QLCNIC_HOST_RDS_MBX_IDX 88 | ||
54 | #define QLCNIC_MAX_RING_SETS 8 | ||
55 | |||
56 | struct qlcnic_intrpt_config { | ||
57 | u8 type; | ||
58 | u8 enabled; | ||
59 | u16 id; | ||
60 | u32 src; | ||
61 | }; | ||
62 | |||
63 | struct qlcnic_macvlan_mbx { | ||
64 | u8 mac[ETH_ALEN]; | ||
65 | u16 vlan; | ||
66 | }; | ||
67 | |||
68 | |||
69 | /* Mailbox process AEN count */ | ||
70 | #define QLC_83XX_IDC_COMP_AEN 3 | ||
71 | #define QLC_83XX_MBX_AEN_CNT 5 | ||
72 | #define QLC_83XX_MODULE_LOADED 1 | ||
73 | #define QLC_83XX_MBX_READY 2 | ||
74 | #define QLC_83XX_MBX_AEN_ACK 3 | ||
75 | #define QLC_83XX_SFP_PRESENT(data) ((data) & 3) | ||
76 | #define QLC_83XX_SFP_ERR(data) (((data) >> 2) & 3) | ||
77 | #define QLC_83XX_SFP_MODULE_TYPE(data) (((data) >> 4) & 0x1F) | ||
78 | #define QLC_83XX_SFP_CU_LENGTH(data) (LSB((data) >> 16)) | ||
79 | #define QLC_83XX_SFP_TX_FAULT(data) ((data) & BIT_10) | ||
80 | #define QLC_83XX_SFP_10G_CAPABLE(data) ((data) & BIT_11) | ||
81 | #define QLC_83XX_LINK_STATS(data) ((data) & BIT_0) | ||
82 | #define QLC_83XX_CURRENT_LINK_SPEED(data) (((data) >> 3) & 7) | ||
83 | #define QLC_83XX_LINK_PAUSE(data) (((data) >> 6) & 3) | ||
84 | #define QLC_83XX_LINK_LB(data) (((data) >> 8) & 7) | ||
85 | #define QLC_83XX_LINK_FEC(data) ((data) & BIT_12) | ||
86 | #define QLC_83XX_LINK_EEE(data) ((data) & BIT_13) | ||
87 | #define QLC_83XX_DCBX(data) (((data) >> 28) & 7) | ||
88 | #define QLC_83XX_AUTONEG(data) ((data) & BIT_15) | ||
89 | #define QLC_83XX_CFG_STD_PAUSE (1 << 5) | ||
90 | #define QLC_83XX_CFG_STD_TX_PAUSE (1 << 20) | ||
91 | #define QLC_83XX_CFG_STD_RX_PAUSE (2 << 20) | ||
92 | #define QLC_83XX_CFG_STD_TX_RX_PAUSE (3 << 20) | ||
93 | #define QLC_83XX_ENABLE_AUTONEG (1 << 15) | ||
94 | #define QLC_83XX_CFG_LOOPBACK_HSS (2 << 1) | ||
95 | #define QLC_83XX_CFG_LOOPBACK_PHY (3 << 1) | ||
96 | #define QLC_83XX_CFG_LOOPBACK_EXT (4 << 1) | ||
97 | |||
98 | /* LED configuration settings */ | ||
99 | #define QLC_83XX_ENABLE_BEACON 0xe | ||
100 | #define QLC_83XX_LED_RATE 0xff | ||
101 | #define QLC_83XX_LED_ACT (1 << 10) | ||
102 | #define QLC_83XX_LED_MOD (0 << 13) | ||
103 | #define QLC_83XX_LED_CONFIG (QLC_83XX_LED_RATE | QLC_83XX_LED_ACT | \ | ||
104 | QLC_83XX_LED_MOD) | ||
105 | |||
106 | #define QLC_83XX_10M_LINK 1 | ||
107 | #define QLC_83XX_100M_LINK 2 | ||
108 | #define QLC_83XX_1G_LINK 3 | ||
109 | #define QLC_83XX_10G_LINK 4 | ||
110 | #define QLC_83XX_STAT_TX 3 | ||
111 | #define QLC_83XX_STAT_RX 2 | ||
112 | #define QLC_83XX_STAT_MAC 1 | ||
113 | #define QLC_83XX_TX_STAT_REGS 14 | ||
114 | #define QLC_83XX_RX_STAT_REGS 40 | ||
115 | #define QLC_83XX_MAC_STAT_REGS 80 | ||
116 | |||
117 | #define QLC_83XX_GET_FUNC_PRIVILEGE(VAL, FN) (0x3 & ((VAL) >> (FN * 2))) | ||
118 | #define QLC_83XX_SET_FUNC_OPMODE(VAL, FN) ((VAL) << (FN * 2)) | ||
119 | #define QLC_83XX_DEFAULT_OPMODE 0x55555555 | ||
120 | #define QLC_83XX_PRIVLEGED_FUNC 0x1 | ||
121 | #define QLC_83XX_VIRTUAL_FUNC 0x2 | ||
122 | |||
123 | #define QLC_83XX_LB_MAX_FILTERS 2048 | ||
124 | #define QLC_83XX_LB_BUCKET_SIZE 256 | ||
125 | #define QLC_83XX_MINIMUM_VECTOR 3 | ||
126 | |||
127 | #define QLC_83XX_GET_FUNC_MODE_FROM_NPAR_INFO(val) (val & 0x80000000) | ||
128 | #define QLC_83XX_GET_LRO_CAPABILITY(val) (val & 0x20) | ||
129 | #define QLC_83XX_GET_LSO_CAPABILITY(val) (val & 0x40) | ||
130 | #define QLC_83XX_GET_LSO_CAPABILITY(val) (val & 0x40) | ||
131 | #define QLC_83XX_GET_HW_LRO_CAPABILITY(val) (val & 0x400) | ||
132 | #define QLC_83XX_GET_VLAN_ALIGN_CAPABILITY(val) (val & 0x4000) | ||
133 | #define QLC_83XX_VIRTUAL_NIC_MODE 0xFF | ||
134 | #define QLC_83XX_DEFAULT_MODE 0x0 | ||
135 | #define QLCNIC_BRDTYPE_83XX_10G 0x0083 | ||
136 | |||
137 | /* Additional registers in 83xx */ | ||
138 | enum qlc_83xx_ext_regs { | ||
139 | QLCNIC_GLOBAL_RESET = 0, | ||
140 | QLCNIC_WILDCARD, | ||
141 | QLCNIC_INFORMANT, | ||
142 | QLCNIC_HOST_MBX_CTRL, | ||
143 | QLCNIC_FW_MBX_CTRL, | ||
144 | QLCNIC_BOOTLOADER_ADDR, | ||
145 | QLCNIC_BOOTLOADER_SIZE, | ||
146 | QLCNIC_FW_IMAGE_ADDR, | ||
147 | QLCNIC_MBX_INTR_ENBL, | ||
148 | QLCNIC_DEF_INT_MASK, | ||
149 | QLCNIC_DEF_INT_ID, | ||
150 | QLC_83XX_IDC_MAJ_VERSION, | ||
151 | QLC_83XX_IDC_DEV_STATE, | ||
152 | QLC_83XX_IDC_DRV_PRESENCE, | ||
153 | QLC_83XX_IDC_DRV_ACK, | ||
154 | QLC_83XX_IDC_CTRL, | ||
155 | QLC_83XX_IDC_DRV_AUDIT, | ||
156 | QLC_83XX_IDC_MIN_VERSION, | ||
157 | QLC_83XX_RECOVER_DRV_LOCK, | ||
158 | QLC_83XX_IDC_PF_0, | ||
159 | QLC_83XX_IDC_PF_1, | ||
160 | QLC_83XX_IDC_PF_2, | ||
161 | QLC_83XX_IDC_PF_3, | ||
162 | QLC_83XX_IDC_PF_4, | ||
163 | QLC_83XX_IDC_PF_5, | ||
164 | QLC_83XX_IDC_PF_6, | ||
165 | QLC_83XX_IDC_PF_7, | ||
166 | QLC_83XX_IDC_PF_8, | ||
167 | QLC_83XX_IDC_PF_9, | ||
168 | QLC_83XX_IDC_PF_10, | ||
169 | QLC_83XX_IDC_PF_11, | ||
170 | QLC_83XX_IDC_PF_12, | ||
171 | QLC_83XX_IDC_PF_13, | ||
172 | QLC_83XX_IDC_PF_14, | ||
173 | QLC_83XX_IDC_PF_15, | ||
174 | QLC_83XX_IDC_DEV_PARTITION_INFO_1, | ||
175 | QLC_83XX_IDC_DEV_PARTITION_INFO_2, | ||
176 | QLC_83XX_DRV_OP_MODE, | ||
177 | QLC_83XX_VNIC_STATE, | ||
178 | QLC_83XX_DRV_LOCK, | ||
179 | QLC_83XX_DRV_UNLOCK, | ||
180 | QLC_83XX_DRV_LOCK_ID, | ||
181 | QLC_83XX_ASIC_TEMP, | ||
182 | }; | ||
183 | |||
184 | /* 83xx funcitons */ | ||
185 | int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *); | ||
186 | int qlcnic_83xx_mbx_op(struct qlcnic_adapter *, struct qlcnic_cmd_args *); | ||
187 | int qlcnic_83xx_setup_intr(struct qlcnic_adapter *, u8); | ||
188 | void qlcnic_83xx_get_func_no(struct qlcnic_adapter *); | ||
189 | int qlcnic_83xx_cam_lock(struct qlcnic_adapter *); | ||
190 | void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *); | ||
191 | int qlcnic_send_ctrl_op(struct qlcnic_adapter *, struct qlcnic_cmd_args *, u32); | ||
192 | void qlcnic_83xx_write_crb(struct qlcnic_adapter *, char *, loff_t, size_t); | ||
193 | void qlcnic_83xx_read_crb(struct qlcnic_adapter *, char *, loff_t, size_t); | ||
194 | int qlcnic_83xx_rd_reg_indirect(struct qlcnic_adapter *, ulong); | ||
195 | int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *, ulong, u32); | ||
196 | void qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter *, | ||
197 | struct qlcnic_host_sds_ring *, int, u64 []); | ||
198 | int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *, u32); | ||
199 | int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *, u8); | ||
200 | int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *, u8); | ||
201 | int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *, int); | ||
202 | int qlcnic_83xx_config_rss(struct qlcnic_adapter *, int); | ||
203 | int qlcnic_83xx_config_intr_coalesce(struct qlcnic_adapter *); | ||
204 | void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *, u64 *, __le16); | ||
205 | int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info *); | ||
206 | int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *); | ||
207 | void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *, int); | ||
208 | |||
209 | void qlcnic_ind_wr(struct qlcnic_adapter *, u32, u32); | ||
210 | int qlcnic_ind_rd(struct qlcnic_adapter *, u32); | ||
211 | void qlcnic_83xx_get_stats(struct qlcnic_adapter *, | ||
212 | struct ethtool_stats *, u64 *); | ||
213 | int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *); | ||
214 | int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *, | ||
215 | struct qlcnic_host_tx_ring *, int); | ||
216 | int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8); | ||
217 | int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *, int); | ||
218 | void qlcnic_83xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *); | ||
219 | int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *, bool); | ||
220 | int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *, u8 *, __le16, u8); | ||
221 | int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *, u8 *); | ||
222 | void qlcnic_83xx_configure_mac(struct qlcnic_adapter *, u8 *, u8, | ||
223 | struct qlcnic_cmd_args *); | ||
224 | int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *, | ||
225 | struct qlcnic_adapter *, u32); | ||
226 | void qlcnic_free_mbx_args(struct qlcnic_cmd_args *); | ||
227 | void qlcnic_set_npar_data(struct qlcnic_adapter *, const struct qlcnic_info *, | ||
228 | struct qlcnic_info *); | ||
229 | void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *); | ||
230 | irqreturn_t qlcnic_83xx_handle_aen(int, void *); | ||
231 | int qlcnic_83xx_get_port_info(struct qlcnic_adapter *); | ||
232 | void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *); | ||
233 | irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *); | ||
234 | irqreturn_t qlcnic_83xx_tmp_intr(int, void *); | ||
235 | void qlcnic_83xx_enable_intr(struct qlcnic_adapter *, | ||
236 | struct qlcnic_host_sds_ring *); | ||
237 | void qlcnic_83xx_check_vf(struct qlcnic_adapter *, | ||
238 | const struct pci_device_id *); | ||
239 | void qlcnic_83xx_process_aen(struct qlcnic_adapter *); | ||
240 | int qlcnic_83xx_get_port_config(struct qlcnic_adapter *); | ||
241 | int qlcnic_83xx_set_port_config(struct qlcnic_adapter *); | ||
242 | int qlcnic_enable_eswitch(struct qlcnic_adapter *, u8, u8); | ||
243 | int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *); | ||
244 | int qlcnic_83xx_config_default_opmode(struct qlcnic_adapter *); | ||
245 | int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *); | ||
246 | void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *); | ||
247 | void qlcnic_83xx_register_map(struct qlcnic_hardware_context *); | ||
248 | void qlcnic_83xx_idc_aen_work(struct work_struct *); | ||
249 | void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *, __be32, int); | ||
250 | #endif | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h index fa2b8c63eedb..458b9aea2bb4 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h | |||
@@ -493,7 +493,7 @@ enum { | |||
493 | #define QLCNIC_NIU_GB_MAC_CONFIG_1(I) \ | 493 | #define QLCNIC_NIU_GB_MAC_CONFIG_1(I) \ |
494 | (QLCNIC_CRB_NIU + 0x30004 + (I)*0x10000) | 494 | (QLCNIC_CRB_NIU + 0x30004 + (I)*0x10000) |
495 | 495 | ||
496 | 496 | #define MAX_CTL_CHECK 1000 | |
497 | #define TEST_AGT_CTRL (0x00) | 497 | #define TEST_AGT_CTRL (0x00) |
498 | 498 | ||
499 | #define TA_CTL_START BIT_0 | 499 | #define TA_CTL_START BIT_0 |
@@ -749,6 +749,9 @@ enum { | |||
749 | #define QLCNIC_HEARTBEAT_PERIOD_MSECS 200 | 749 | #define QLCNIC_HEARTBEAT_PERIOD_MSECS 200 |
750 | #define QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT 45 | 750 | #define QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT 45 |
751 | 751 | ||
752 | #define QLCNIC_MAX_MC_COUNT 38 | ||
753 | #define QLCNIC_WATCHDOG_TIMEOUTVALUE 5 | ||
754 | |||
752 | #define ISR_MSI_INT_TRIGGER(FUNC) (QLCNIC_PCIX_PS_REG(PCIX_MSI_F(FUNC))) | 755 | #define ISR_MSI_INT_TRIGGER(FUNC) (QLCNIC_PCIX_PS_REG(PCIX_MSI_F(FUNC))) |
753 | #define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) | 756 | #define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) |
754 | 757 | ||
@@ -801,7 +804,8 @@ static const u32 MIU_TEST_READ_DATA[] = { | |||
801 | enum { | 804 | enum { |
802 | QLCNIC_MGMT_FUNC = 0, | 805 | QLCNIC_MGMT_FUNC = 0, |
803 | QLCNIC_PRIV_FUNC = 1, | 806 | QLCNIC_PRIV_FUNC = 1, |
804 | QLCNIC_NON_PRIV_FUNC = 2 | 807 | QLCNIC_NON_PRIV_FUNC = 2, |
808 | QLCNIC_UNKNOWN_FUNC_MODE = 3 | ||
805 | }; | 809 | }; |
806 | 810 | ||
807 | enum { | 811 | enum { |
@@ -1018,6 +1022,8 @@ enum { | |||
1018 | #define QLCNIC_NIU_PROMISC_MODE 1 | 1022 | #define QLCNIC_NIU_PROMISC_MODE 1 |
1019 | #define QLCNIC_NIU_ALLMULTI_MODE 2 | 1023 | #define QLCNIC_NIU_ALLMULTI_MODE 2 |
1020 | 1024 | ||
1025 | #define QLCNIC_PCIE_SEM_TIMEOUT 10000 | ||
1026 | |||
1021 | struct crb_128M_2M_sub_block_map { | 1027 | struct crb_128M_2M_sub_block_map { |
1022 | unsigned valid; | 1028 | unsigned valid; |
1023 | unsigned start_128M; | 1029 | unsigned start_128M; |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index 284618be3402..d692aa8d4054 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | |||
@@ -344,21 +344,26 @@ qlcnic_pcie_sem_unlock(struct qlcnic_adapter *adapter, int sem) | |||
344 | QLCRD32(adapter, QLCNIC_PCIE_REG(PCIE_SEM_UNLOCK(sem))); | 344 | QLCRD32(adapter, QLCNIC_PCIE_REG(PCIE_SEM_UNLOCK(sem))); |
345 | } | 345 | } |
346 | 346 | ||
347 | static int qlcnic_ind_rd(struct qlcnic_adapter *adapter, u32 addr) | 347 | int qlcnic_ind_rd(struct qlcnic_adapter *adapter, u32 addr) |
348 | { | 348 | { |
349 | u32 data; | 349 | u32 data; |
350 | 350 | ||
351 | if (qlcnic_82xx_check(adapter)) | 351 | if (qlcnic_82xx_check(adapter)) |
352 | qlcnic_read_window_reg(addr, adapter->ahw->pci_base0, &data); | 352 | qlcnic_read_window_reg(addr, adapter->ahw->pci_base0, &data); |
353 | else | 353 | else { |
354 | return -EIO; | 354 | data = qlcnic_83xx_rd_reg_indirect(adapter, addr); |
355 | if (data == -EIO) | ||
356 | return -EIO; | ||
357 | } | ||
355 | return data; | 358 | return data; |
356 | } | 359 | } |
357 | 360 | ||
358 | static void qlcnic_ind_wr(struct qlcnic_adapter *adapter, u32 addr, u32 data) | 361 | void qlcnic_ind_wr(struct qlcnic_adapter *adapter, u32 addr, u32 data) |
359 | { | 362 | { |
360 | if (qlcnic_82xx_check(adapter)) | 363 | if (qlcnic_82xx_check(adapter)) |
361 | qlcnic_write_window_reg(addr, adapter->ahw->pci_base0, data); | 364 | qlcnic_write_window_reg(addr, adapter->ahw->pci_base0, data); |
365 | else | ||
366 | qlcnic_83xx_wrt_reg_indirect(adapter, addr, data); | ||
362 | } | 367 | } |
363 | 368 | ||
364 | static int | 369 | static int |
@@ -553,19 +558,20 @@ void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter) | |||
553 | struct qlcnic_filter *tmp_fil; | 558 | struct qlcnic_filter *tmp_fil; |
554 | struct hlist_node *tmp_hnode, *n; | 559 | struct hlist_node *tmp_hnode, *n; |
555 | struct hlist_head *head; | 560 | struct hlist_head *head; |
556 | int i; | 561 | int i, time; |
562 | u8 cmd; | ||
557 | 563 | ||
558 | for (i = 0; i < adapter->fhash.fmax; i++) { | 564 | for (i = 0; i < adapter->fhash.fbucket_size; i++) { |
559 | head = &(adapter->fhash.fhead[i]); | 565 | head = &(adapter->fhash.fhead[i]); |
560 | 566 | hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) { | |
561 | hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) | 567 | cmd = tmp_fil->vlan_id ? QLCNIC_MAC_VLAN_DEL : |
562 | { | 568 | QLCNIC_MAC_DEL; |
563 | if (jiffies > | 569 | time = tmp_fil->ftime; |
564 | (QLCNIC_FILTER_AGE * HZ + tmp_fil->ftime)) { | 570 | if (jiffies > (QLCNIC_FILTER_AGE * HZ + time)) { |
565 | qlcnic_sre_macaddr_change(adapter, | 571 | qlcnic_sre_macaddr_change(adapter, |
566 | tmp_fil->faddr, tmp_fil->vlan_id, | 572 | tmp_fil->faddr, |
567 | tmp_fil->vlan_id ? QLCNIC_MAC_VLAN_DEL : | 573 | tmp_fil->vlan_id, |
568 | QLCNIC_MAC_DEL); | 574 | cmd); |
569 | spin_lock_bh(&adapter->mac_learn_lock); | 575 | spin_lock_bh(&adapter->mac_learn_lock); |
570 | adapter->fhash.fnum--; | 576 | adapter->fhash.fnum--; |
571 | hlist_del(&tmp_fil->fnode); | 577 | hlist_del(&tmp_fil->fnode); |
@@ -582,14 +588,17 @@ void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter) | |||
582 | struct hlist_node *tmp_hnode, *n; | 588 | struct hlist_node *tmp_hnode, *n; |
583 | struct hlist_head *head; | 589 | struct hlist_head *head; |
584 | int i; | 590 | int i; |
591 | u8 cmd; | ||
585 | 592 | ||
586 | for (i = 0; i < adapter->fhash.fmax; i++) { | 593 | for (i = 0; i < adapter->fhash.fbucket_size; i++) { |
587 | head = &(adapter->fhash.fhead[i]); | 594 | head = &(adapter->fhash.fhead[i]); |
588 | |||
589 | hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) { | 595 | hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) { |
590 | qlcnic_sre_macaddr_change(adapter, tmp_fil->faddr, | 596 | cmd = tmp_fil->vlan_id ? QLCNIC_MAC_VLAN_DEL : |
591 | tmp_fil->vlan_id, tmp_fil->vlan_id ? | 597 | QLCNIC_MAC_DEL; |
592 | QLCNIC_MAC_VLAN_DEL : QLCNIC_MAC_DEL); | 598 | qlcnic_sre_macaddr_change(adapter, |
599 | tmp_fil->faddr, | ||
600 | tmp_fil->vlan_id, | ||
601 | cmd); | ||
593 | spin_lock_bh(&adapter->mac_learn_lock); | 602 | spin_lock_bh(&adapter->mac_learn_lock); |
594 | adapter->fhash.fnum--; | 603 | adapter->fhash.fnum--; |
595 | hlist_del(&tmp_fil->fnode); | 604 | hlist_del(&tmp_fil->fnode); |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h index 937d75f939aa..9673e2bcff06 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h | |||
@@ -36,6 +36,14 @@ enum qlcnic_regs { | |||
36 | #define QLC_SHARED_REG_WR32(a, addr, value) \ | 36 | #define QLC_SHARED_REG_WR32(a, addr, value) \ |
37 | writel(value, ((a)->ahw->pci_base0) + ((a)->ahw->reg_tbl[addr])) | 37 | writel(value, ((a)->ahw->pci_base0) + ((a)->ahw->reg_tbl[addr])) |
38 | 38 | ||
39 | /* Read from a direct address offset from BAR0, additional registers */ | ||
40 | #define QLCRDX(ahw, addr) \ | ||
41 | readl(((ahw)->pci_base0) + ((ahw)->ext_reg_tbl[addr])) | ||
42 | |||
43 | /* Write to a direct address offset from BAR0, additional registers */ | ||
44 | #define QLCWRX(ahw, addr, value) \ | ||
45 | writel(value, (((ahw)->pci_base0) + ((ahw)->ext_reg_tbl[addr]))) | ||
46 | |||
39 | #define QLCNIC_CMD_CONFIGURE_IP_ADDR 0x1 | 47 | #define QLCNIC_CMD_CONFIGURE_IP_ADDR 0x1 |
40 | #define QLCNIC_CMD_CONFIG_INTRPT 0x2 | 48 | #define QLCNIC_CMD_CONFIG_INTRPT 0x2 |
41 | #define QLCNIC_CMD_CREATE_RX_CTX 0x7 | 49 | #define QLCNIC_CMD_CREATE_RX_CTX 0x7 |
@@ -85,6 +93,7 @@ enum qlcnic_regs { | |||
85 | #define QLCNIC_CMD_GET_LINK_STATUS 0x68 | 93 | #define QLCNIC_CMD_GET_LINK_STATUS 0x68 |
86 | #define QLCNIC_CMD_SET_LED_CONFIG 0x69 | 94 | #define QLCNIC_CMD_SET_LED_CONFIG 0x69 |
87 | #define QLCNIC_CMD_GET_LED_CONFIG 0x6A | 95 | #define QLCNIC_CMD_GET_LED_CONFIG 0x6A |
96 | #define QLCNIC_CMD_ADD_RCV_RINGS 0x0B | ||
88 | 97 | ||
89 | #define QLCNIC_INTRPT_INTX 1 | 98 | #define QLCNIC_INTRPT_INTX 1 |
90 | #define QLCNIC_INTRPT_MSIX 3 | 99 | #define QLCNIC_INTRPT_MSIX 3 |
@@ -110,6 +119,13 @@ struct qlcnic_mailbox_metadata { | |||
110 | u32 out_args; | 119 | u32 out_args; |
111 | }; | 120 | }; |
112 | 121 | ||
122 | /* Mailbox ownership */ | ||
123 | #define QLCNIC_GET_OWNER(val) ((val) & (BIT_0 | BIT_1)) | ||
124 | |||
125 | #define QLCNIC_SET_OWNER 1 | ||
126 | #define QLCNIC_CLR_OWNER 0 | ||
127 | #define QLCNIC_MBX_TIMEOUT 10000 | ||
128 | |||
113 | #define QLCNIC_MBX_RSP_OK 1 | 129 | #define QLCNIC_MBX_RSP_OK 1 |
114 | #define QLCNIC_MBX_PORT_RSP_OK 0x1a | 130 | #define QLCNIC_MBX_PORT_RSP_OK 0x1a |
115 | 131 | ||
@@ -166,4 +182,5 @@ int qlcnic_82xx_api_lock(struct qlcnic_adapter *); | |||
166 | void qlcnic_82xx_api_unlock(struct qlcnic_adapter *); | 182 | void qlcnic_82xx_api_unlock(struct qlcnic_adapter *); |
167 | void qlcnic_82xx_napi_enable(struct qlcnic_adapter *); | 183 | void qlcnic_82xx_napi_enable(struct qlcnic_adapter *); |
168 | void qlcnic_82xx_napi_disable(struct qlcnic_adapter *); | 184 | void qlcnic_82xx_napi_disable(struct qlcnic_adapter *); |
185 | void qlcnic_82xx_napi_del(struct qlcnic_adapter *); | ||
169 | #endif /* __QLCNIC_HW_H_ */ | 186 | #endif /* __QLCNIC_HW_H_ */ |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c index 8d9202fe2dee..d678e6d763e1 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | |||
@@ -487,8 +487,7 @@ drop_packet: | |||
487 | return NETDEV_TX_OK; | 487 | return NETDEV_TX_OK; |
488 | } | 488 | } |
489 | 489 | ||
490 | static void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, | 490 | void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup) |
491 | int linkup) | ||
492 | { | 491 | { |
493 | struct net_device *netdev = adapter->netdev; | 492 | struct net_device *netdev = adapter->netdev; |
494 | 493 | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 73b4f670e1c2..9498b39770bb 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
@@ -347,7 +347,7 @@ static struct qlcnic_hardware_ops qlcnic_hw_ops = { | |||
347 | .get_board_info = qlcnic_82xx_get_board_info, | 347 | .get_board_info = qlcnic_82xx_get_board_info, |
348 | }; | 348 | }; |
349 | 349 | ||
350 | static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) | 350 | int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) |
351 | { | 351 | { |
352 | struct pci_dev *pdev = adapter->pdev; | 352 | struct pci_dev *pdev = adapter->pdev; |
353 | int err = -1; | 353 | int err = -1; |