diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2013-04-20 12:16:44 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2013-04-20 12:16:44 -0400 |
commit | f53f292eeaa234615c31a1306babe703fc4263f2 (patch) | |
tree | 707b0933a20f7dc05495e974243a23b5c9f8c918 /drivers/net/ethernet/qlogic | |
parent | 15b9c359f288b09003cb70f7ed204affc0c6614d (diff) | |
parent | a9499fa7cd3fd4824a7202d00c766b269fa3bda6 (diff) |
Merge remote-tracking branch 'efi/chainsaw' into x86/efi
Resolved Conflicts:
drivers/firmware/efivars.c
fs/efivarsfs/file.c
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'drivers/net/ethernet/qlogic')
22 files changed, 9613 insertions, 1642 deletions
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c index 7f556a84925d..1bcaf45aa864 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c | |||
@@ -201,11 +201,8 @@ netxen_setup_minidump(struct netxen_adapter *adapter) | |||
201 | adapter->mdump.md_template = | 201 | adapter->mdump.md_template = |
202 | kmalloc(adapter->mdump.md_template_size, GFP_KERNEL); | 202 | kmalloc(adapter->mdump.md_template_size, GFP_KERNEL); |
203 | 203 | ||
204 | if (!adapter->mdump.md_template) { | 204 | if (!adapter->mdump.md_template) |
205 | dev_err(&adapter->pdev->dev, "Unable to allocate memory " | ||
206 | "for minidump template.\n"); | ||
207 | return -ENOMEM; | 205 | return -ENOMEM; |
208 | } | ||
209 | 206 | ||
210 | err = netxen_get_minidump_template(adapter); | 207 | err = netxen_get_minidump_template(adapter); |
211 | if (err) { | 208 | if (err) { |
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c index 946160fa5843..9fbb1cdbfa47 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_hw.c | |||
@@ -670,11 +670,9 @@ static int nx_p3_nic_add_mac(struct netxen_adapter *adapter, | |||
670 | } | 670 | } |
671 | 671 | ||
672 | cur = kzalloc(sizeof(nx_mac_list_t), GFP_ATOMIC); | 672 | cur = kzalloc(sizeof(nx_mac_list_t), GFP_ATOMIC); |
673 | if (cur == NULL) { | 673 | if (cur == NULL) |
674 | printk(KERN_ERR "%s: failed to add mac address filter\n", | ||
675 | adapter->netdev->name); | ||
676 | return -ENOMEM; | 674 | return -ENOMEM; |
677 | } | 675 | |
678 | memcpy(cur->mac_addr, addr, ETH_ALEN); | 676 | memcpy(cur->mac_addr, addr, ETH_ALEN); |
679 | list_add_tail(&cur->list, &adapter->mac_list); | 677 | list_add_tail(&cur->list, &adapter->mac_list); |
680 | return nx_p3_sre_macaddr_change(adapter, | 678 | return nx_p3_sre_macaddr_change(adapter, |
@@ -2568,16 +2566,10 @@ netxen_dump_fw(struct netxen_adapter *adapter) | |||
2568 | adapter->mdump.md_capture_size; | 2566 | adapter->mdump.md_capture_size; |
2569 | if (!adapter->mdump.md_capture_buff) { | 2567 | if (!adapter->mdump.md_capture_buff) { |
2570 | adapter->mdump.md_capture_buff = | 2568 | adapter->mdump.md_capture_buff = |
2571 | vmalloc(adapter->mdump.md_dump_size); | 2569 | vzalloc(adapter->mdump.md_dump_size); |
2572 | if (!adapter->mdump.md_capture_buff) { | 2570 | if (!adapter->mdump.md_capture_buff) |
2573 | dev_info(&adapter->pdev->dev, | ||
2574 | "Unable to allocate memory for minidump " | ||
2575 | "capture_buffer(%d bytes).\n", | ||
2576 | adapter->mdump.md_dump_size); | ||
2577 | return; | 2571 | return; |
2578 | } | 2572 | |
2579 | memset(adapter->mdump.md_capture_buff, 0, | ||
2580 | adapter->mdump.md_dump_size); | ||
2581 | if (netxen_collect_minidump(adapter)) { | 2573 | if (netxen_collect_minidump(adapter)) { |
2582 | adapter->mdump.has_valid_dump = 0; | 2574 | adapter->mdump.has_valid_dump = 0; |
2583 | adapter->mdump.md_dump_size = 0; | 2575 | adapter->mdump.md_dump_size = 0; |
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c index 695667d471a1..4782dcfde736 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c | |||
@@ -197,41 +197,33 @@ int netxen_alloc_sw_resources(struct netxen_adapter *adapter) | |||
197 | struct nx_host_sds_ring *sds_ring; | 197 | struct nx_host_sds_ring *sds_ring; |
198 | struct nx_host_tx_ring *tx_ring; | 198 | struct nx_host_tx_ring *tx_ring; |
199 | struct netxen_rx_buffer *rx_buf; | 199 | struct netxen_rx_buffer *rx_buf; |
200 | int ring, i, size; | 200 | int ring, i; |
201 | 201 | ||
202 | struct netxen_cmd_buffer *cmd_buf_arr; | 202 | struct netxen_cmd_buffer *cmd_buf_arr; |
203 | struct net_device *netdev = adapter->netdev; | 203 | struct net_device *netdev = adapter->netdev; |
204 | struct pci_dev *pdev = adapter->pdev; | ||
205 | 204 | ||
206 | size = sizeof(struct nx_host_tx_ring); | 205 | tx_ring = kzalloc(sizeof(struct nx_host_tx_ring), GFP_KERNEL); |
207 | tx_ring = kzalloc(size, GFP_KERNEL); | 206 | if (tx_ring == NULL) |
208 | if (tx_ring == NULL) { | ||
209 | dev_err(&pdev->dev, "%s: failed to allocate tx ring struct\n", | ||
210 | netdev->name); | ||
211 | return -ENOMEM; | 207 | return -ENOMEM; |
212 | } | 208 | |
213 | adapter->tx_ring = tx_ring; | 209 | adapter->tx_ring = tx_ring; |
214 | 210 | ||
215 | tx_ring->num_desc = adapter->num_txd; | 211 | tx_ring->num_desc = adapter->num_txd; |
216 | tx_ring->txq = netdev_get_tx_queue(netdev, 0); | 212 | tx_ring->txq = netdev_get_tx_queue(netdev, 0); |
217 | 213 | ||
218 | cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring)); | 214 | cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring)); |
219 | if (cmd_buf_arr == NULL) { | 215 | if (cmd_buf_arr == NULL) |
220 | dev_err(&pdev->dev, "%s: failed to allocate cmd buffer ring\n", | ||
221 | netdev->name); | ||
222 | goto err_out; | 216 | goto err_out; |
223 | } | 217 | |
224 | tx_ring->cmd_buf_arr = cmd_buf_arr; | 218 | tx_ring->cmd_buf_arr = cmd_buf_arr; |
225 | 219 | ||
226 | recv_ctx = &adapter->recv_ctx; | 220 | recv_ctx = &adapter->recv_ctx; |
227 | 221 | ||
228 | size = adapter->max_rds_rings * sizeof (struct nx_host_rds_ring); | 222 | rds_ring = kcalloc(adapter->max_rds_rings, |
229 | rds_ring = kzalloc(size, GFP_KERNEL); | 223 | sizeof(struct nx_host_rds_ring), GFP_KERNEL); |
230 | if (rds_ring == NULL) { | 224 | if (rds_ring == NULL) |
231 | dev_err(&pdev->dev, "%s: failed to allocate rds ring struct\n", | ||
232 | netdev->name); | ||
233 | goto err_out; | 225 | goto err_out; |
234 | } | 226 | |
235 | recv_ctx->rds_rings = rds_ring; | 227 | recv_ctx->rds_rings = rds_ring; |
236 | 228 | ||
237 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | 229 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { |
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 69e321a65077..501f49207da5 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | |||
@@ -501,12 +501,11 @@ netxen_read_mac_addr(struct netxen_adapter *adapter) | |||
501 | for (i = 0; i < 6; i++) | 501 | for (i = 0; i < 6; i++) |
502 | netdev->dev_addr[i] = *(p + 5 - i); | 502 | netdev->dev_addr[i] = *(p + 5 - i); |
503 | 503 | ||
504 | memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len); | ||
505 | memcpy(adapter->mac_addr, netdev->dev_addr, netdev->addr_len); | 504 | memcpy(adapter->mac_addr, netdev->dev_addr, netdev->addr_len); |
506 | 505 | ||
507 | /* set station address */ | 506 | /* set station address */ |
508 | 507 | ||
509 | if (!is_valid_ether_addr(netdev->perm_addr)) | 508 | if (!is_valid_ether_addr(netdev->dev_addr)) |
510 | dev_warn(&pdev->dev, "Bad MAC address %pM.\n", netdev->dev_addr); | 509 | dev_warn(&pdev->dev, "Bad MAC address %pM.\n", netdev->dev_addr); |
511 | 510 | ||
512 | return 0; | 511 | return 0; |
@@ -3177,11 +3176,8 @@ netxen_list_config_vlan_ip(struct netxen_adapter *adapter, | |||
3177 | } | 3176 | } |
3178 | 3177 | ||
3179 | cur = kzalloc(sizeof(struct nx_vlan_ip_list), GFP_ATOMIC); | 3178 | cur = kzalloc(sizeof(struct nx_vlan_ip_list), GFP_ATOMIC); |
3180 | if (cur == NULL) { | 3179 | if (cur == NULL) |
3181 | printk(KERN_ERR "%s: failed to add vlan ip to list\n", | ||
3182 | adapter->netdev->name); | ||
3183 | return; | 3180 | return; |
3184 | } | ||
3185 | 3181 | ||
3186 | cur->ip_addr = ifa->ifa_address; | 3182 | cur->ip_addr = ifa->ifa_address; |
3187 | list_add_tail(&cur->list, &adapter->vlan_ip_list); | 3183 | list_add_tail(&cur->list, &adapter->vlan_ip_list); |
diff --git a/drivers/net/ethernet/qlogic/qla3xxx.c b/drivers/net/ethernet/qlogic/qla3xxx.c index 67a679aaf29a..8fd38cb6d26a 100644 --- a/drivers/net/ethernet/qlogic/qla3xxx.c +++ b/drivers/net/ethernet/qlogic/qla3xxx.c | |||
@@ -2591,13 +2591,11 @@ static int ql_alloc_buffer_queues(struct ql3_adapter *qdev) | |||
2591 | else | 2591 | else |
2592 | qdev->lrg_buf_q_alloc_size = qdev->lrg_buf_q_size * 2; | 2592 | qdev->lrg_buf_q_alloc_size = qdev->lrg_buf_q_size * 2; |
2593 | 2593 | ||
2594 | qdev->lrg_buf = | 2594 | qdev->lrg_buf = kmalloc_array(qdev->num_large_buffers, |
2595 | kmalloc(qdev->num_large_buffers * sizeof(struct ql_rcv_buf_cb), | 2595 | sizeof(struct ql_rcv_buf_cb), |
2596 | GFP_KERNEL); | 2596 | GFP_KERNEL); |
2597 | if (qdev->lrg_buf == NULL) { | 2597 | if (qdev->lrg_buf == NULL) |
2598 | netdev_err(qdev->ndev, "qdev->lrg_buf alloc failed\n"); | ||
2599 | return -ENOMEM; | 2598 | return -ENOMEM; |
2600 | } | ||
2601 | 2599 | ||
2602 | qdev->lrg_buf_q_alloc_virt_addr = | 2600 | qdev->lrg_buf_q_alloc_virt_addr = |
2603 | pci_alloc_consistent(qdev->pdev, | 2601 | pci_alloc_consistent(qdev->pdev, |
@@ -3867,7 +3865,6 @@ static int ql3xxx_probe(struct pci_dev *pdev, | |||
3867 | ndev->mtu = qdev->nvram_data.macCfg_port0.etherMtu_mac ; | 3865 | ndev->mtu = qdev->nvram_data.macCfg_port0.etherMtu_mac ; |
3868 | ql_set_mac_addr(ndev, qdev->nvram_data.funcCfg_fn0.macAddress); | 3866 | ql_set_mac_addr(ndev, qdev->nvram_data.funcCfg_fn0.macAddress); |
3869 | } | 3867 | } |
3870 | memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len); | ||
3871 | 3868 | ||
3872 | ndev->tx_queue_len = NUM_REQ_Q_ENTRIES; | 3869 | ndev->tx_queue_len = NUM_REQ_Q_ENTRIES; |
3873 | 3870 | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/Makefile b/drivers/net/ethernet/qlogic/qlcnic/Makefile index c4b8ced83829..7722a203e388 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/Makefile +++ b/drivers/net/ethernet/qlogic/qlcnic/Makefile | |||
@@ -6,4 +6,6 @@ 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 \ |
10 | qlcnic_83xx_init.o qlcnic_83xx_vnic.o \ | ||
11 | qlcnic_minidump.o | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h index bc7ec64e9c7a..ba3c72fce1f2 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * QLogic qlcnic NIC Driver | 2 | * QLogic qlcnic NIC Driver |
3 | * Copyright (c) 2009-2010 QLogic Corporation | 3 | * Copyright (c) 2009-2013 QLogic Corporation |
4 | * | 4 | * |
5 | * See LICENSE.qlcnic for copyright and licensing details. | 5 | * See LICENSE.qlcnic for copyright and licensing details. |
6 | */ | 6 | */ |
@@ -33,11 +33,13 @@ | |||
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 1 |
39 | #define _QLCNIC_LINUX_SUBVERSION 30 | 41 | #define _QLCNIC_LINUX_SUBVERSION 35 |
40 | #define QLCNIC_LINUX_VERSIONID "5.0.30" | 42 | #define QLCNIC_LINUX_VERSIONID "5.1.35" |
41 | #define QLCNIC_DRV_IDC_VER 0x01 | 43 | #define QLCNIC_DRV_IDC_VER 0x01 |
42 | #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ | 44 | #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ |
43 | (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) | 45 | (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) |
@@ -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. |
@@ -203,6 +204,7 @@ struct uni_data_desc{ | |||
203 | 204 | ||
204 | /* Flash Defines and Structures */ | 205 | /* Flash Defines and Structures */ |
205 | #define QLCNIC_FLT_LOCATION 0x3F1000 | 206 | #define QLCNIC_FLT_LOCATION 0x3F1000 |
207 | #define QLCNIC_FDT_LOCATION 0x3F0000 | ||
206 | #define QLCNIC_B0_FW_IMAGE_REGION 0x74 | 208 | #define QLCNIC_B0_FW_IMAGE_REGION 0x74 |
207 | #define QLCNIC_C0_FW_IMAGE_REGION 0x97 | 209 | #define QLCNIC_C0_FW_IMAGE_REGION 0x97 |
208 | #define QLCNIC_BOOTLD_REGION 0X72 | 210 | #define QLCNIC_BOOTLD_REGION 0X72 |
@@ -223,6 +225,36 @@ struct qlcnic_flt_entry { | |||
223 | u32 end_addr; | 225 | u32 end_addr; |
224 | }; | 226 | }; |
225 | 227 | ||
228 | /* Flash Descriptor Table */ | ||
229 | struct qlcnic_fdt { | ||
230 | u32 valid; | ||
231 | u16 ver; | ||
232 | u16 len; | ||
233 | u16 cksum; | ||
234 | u16 unused; | ||
235 | u8 model[16]; | ||
236 | u16 mfg_id; | ||
237 | u16 id; | ||
238 | u8 flag; | ||
239 | u8 erase_cmd; | ||
240 | u8 alt_erase_cmd; | ||
241 | u8 write_enable_cmd; | ||
242 | u8 write_enable_bits; | ||
243 | u8 write_statusreg_cmd; | ||
244 | u8 unprotected_sec_cmd; | ||
245 | u8 read_manuf_cmd; | ||
246 | u32 block_size; | ||
247 | u32 alt_block_size; | ||
248 | u32 flash_size; | ||
249 | u32 write_enable_data; | ||
250 | u8 readid_addr_len; | ||
251 | u8 write_disable_bits; | ||
252 | u8 read_dev_id_len; | ||
253 | u8 chip_erase_cmd; | ||
254 | u16 read_timeo; | ||
255 | u8 protected_sec_cmd; | ||
256 | u8 resvd[65]; | ||
257 | }; | ||
226 | /* Magic number to let user know flash is programmed */ | 258 | /* Magic number to let user know flash is programmed */ |
227 | #define QLCNIC_BDINFO_MAGIC 0x12345678 | 259 | #define QLCNIC_BDINFO_MAGIC 0x12345678 |
228 | 260 | ||
@@ -267,6 +299,12 @@ struct qlcnic_flt_entry { | |||
267 | 299 | ||
268 | extern char qlcnic_driver_name[]; | 300 | extern char qlcnic_driver_name[]; |
269 | 301 | ||
302 | extern int qlcnic_use_msi; | ||
303 | extern int qlcnic_use_msi_x; | ||
304 | extern int qlcnic_auto_fw_reset; | ||
305 | extern int qlcnic_load_fw_file; | ||
306 | extern int qlcnic_config_npars; | ||
307 | |||
270 | /* Number of status descriptors to handle per interrupt */ | 308 | /* Number of status descriptors to handle per interrupt */ |
271 | #define MAX_STATUS_HANDLE (64) | 309 | #define MAX_STATUS_HANDLE (64) |
272 | 310 | ||
@@ -314,6 +352,7 @@ struct qlcnic_rx_buffer { | |||
314 | 352 | ||
315 | #define QLCNIC_INTR_DEFAULT 0x04 | 353 | #define QLCNIC_INTR_DEFAULT 0x04 |
316 | #define QLCNIC_CONFIG_INTR_COALESCE 3 | 354 | #define QLCNIC_CONFIG_INTR_COALESCE 3 |
355 | #define QLCNIC_DEV_INFO_SIZE 1 | ||
317 | 356 | ||
318 | struct qlcnic_nic_intr_coalesce { | 357 | struct qlcnic_nic_intr_coalesce { |
319 | u8 type; | 358 | u8 type; |
@@ -337,6 +376,7 @@ struct qlcnic_dump_template_hdr { | |||
337 | u32 sys_info[3]; | 376 | u32 sys_info[3]; |
338 | u32 saved_state[16]; | 377 | u32 saved_state[16]; |
339 | u32 cap_sizes[8]; | 378 | u32 cap_sizes[8]; |
379 | u32 ocm_wnd_reg[16]; | ||
340 | u32 rsvd[0]; | 380 | u32 rsvd[0]; |
341 | }; | 381 | }; |
342 | 382 | ||
@@ -396,12 +436,24 @@ struct qlcnic_hardware_context { | |||
396 | u16 act_pci_func; | 436 | u16 act_pci_func; |
397 | 437 | ||
398 | u32 capabilities; | 438 | u32 capabilities; |
439 | u32 capabilities2; | ||
399 | u32 temp; | 440 | u32 temp; |
400 | u32 int_vec_bit; | 441 | u32 int_vec_bit; |
401 | u32 fw_hal_version; | 442 | u32 fw_hal_version; |
443 | u32 port_config; | ||
402 | struct qlcnic_hardware_ops *hw_ops; | 444 | struct qlcnic_hardware_ops *hw_ops; |
403 | struct qlcnic_nic_intr_coalesce coal; | 445 | struct qlcnic_nic_intr_coalesce coal; |
404 | struct qlcnic_fw_dump fw_dump; | 446 | struct qlcnic_fw_dump fw_dump; |
447 | struct qlcnic_fdt fdt; | ||
448 | struct qlc_83xx_reset reset; | ||
449 | struct qlc_83xx_idc idc; | ||
450 | struct qlc_83xx_fw_info fw_info; | ||
451 | struct qlcnic_intrpt_config *intr_tbl; | ||
452 | u32 *reg_tbl; | ||
453 | u32 *ext_reg_tbl; | ||
454 | u32 mbox_aen[QLC_83XX_MBX_AEN_CNT]; | ||
455 | u32 mbox_reg[4]; | ||
456 | spinlock_t mbx_lock; | ||
405 | }; | 457 | }; |
406 | 458 | ||
407 | struct qlcnic_adapter_stats { | 459 | struct qlcnic_adapter_stats { |
@@ -422,6 +474,8 @@ struct qlcnic_adapter_stats { | |||
422 | u64 null_rxbuf; | 474 | u64 null_rxbuf; |
423 | u64 rx_dma_map_error; | 475 | u64 rx_dma_map_error; |
424 | u64 tx_dma_map_error; | 476 | u64 tx_dma_map_error; |
477 | u64 spurious_intr; | ||
478 | u64 mac_filter_limit_overrun; | ||
425 | }; | 479 | }; |
426 | 480 | ||
427 | /* | 481 | /* |
@@ -460,12 +514,17 @@ struct qlcnic_host_sds_ring { | |||
460 | } ____cacheline_internodealigned_in_smp; | 514 | } ____cacheline_internodealigned_in_smp; |
461 | 515 | ||
462 | struct qlcnic_host_tx_ring { | 516 | struct qlcnic_host_tx_ring { |
517 | int irq; | ||
518 | void __iomem *crb_intr_mask; | ||
519 | char name[IFNAMSIZ+4]; | ||
463 | u16 ctx_id; | 520 | u16 ctx_id; |
464 | u32 producer; | 521 | u32 producer; |
465 | u32 sw_consumer; | 522 | u32 sw_consumer; |
466 | u32 num_desc; | 523 | u32 num_desc; |
467 | void __iomem *crb_cmd_producer; | 524 | void __iomem *crb_cmd_producer; |
468 | struct cmd_desc_type0 *desc_head; | 525 | struct cmd_desc_type0 *desc_head; |
526 | struct qlcnic_adapter *adapter; | ||
527 | struct napi_struct napi; | ||
469 | struct qlcnic_cmd_buffer *cmd_buf_arr; | 528 | struct qlcnic_cmd_buffer *cmd_buf_arr; |
470 | __le32 *hw_consumer; | 529 | __le32 *hw_consumer; |
471 | 530 | ||
@@ -492,8 +551,6 @@ struct qlcnic_recv_context { | |||
492 | /* HW context creation */ | 551 | /* HW context creation */ |
493 | 552 | ||
494 | #define QLCNIC_OS_CRB_RETRY_COUNT 4000 | 553 | #define QLCNIC_OS_CRB_RETRY_COUNT 4000 |
495 | #define QLCNIC_CDRP_SIGNATURE_MAKE(pcifn, version) \ | ||
496 | (((pcifn) & 0xff) | (((version) & 0xff) << 8) | (0xcafe << 16)) | ||
497 | 554 | ||
498 | #define QLCNIC_CDRP_CMD_BIT 0x80000000 | 555 | #define QLCNIC_CDRP_CMD_BIT 0x80000000 |
499 | 556 | ||
@@ -513,43 +570,6 @@ struct qlcnic_recv_context { | |||
513 | * the crb QLCNIC_CDRP_CRB_OFFSET. | 570 | * the crb QLCNIC_CDRP_CRB_OFFSET. |
514 | */ | 571 | */ |
515 | #define QLCNIC_CDRP_FORM_CMD(cmd) (QLCNIC_CDRP_CMD_BIT | (cmd)) | 572 | #define QLCNIC_CDRP_FORM_CMD(cmd) (QLCNIC_CDRP_CMD_BIT | (cmd)) |
516 | #define QLCNIC_CDRP_IS_CMD(cmd) (((cmd) & QLCNIC_CDRP_CMD_BIT) != 0) | ||
517 | |||
518 | #define QLCNIC_CDRP_CMD_SUBMIT_CAPABILITIES 0x00000001 | ||
519 | #define QLCNIC_CDRP_CMD_READ_MAX_RDS_PER_CTX 0x00000002 | ||
520 | #define QLCNIC_CDRP_CMD_READ_MAX_SDS_PER_CTX 0x00000003 | ||
521 | #define QLCNIC_CDRP_CMD_READ_MAX_RULES_PER_CTX 0x00000004 | ||
522 | #define QLCNIC_CDRP_CMD_READ_MAX_RX_CTX 0x00000005 | ||
523 | #define QLCNIC_CDRP_CMD_READ_MAX_TX_CTX 0x00000006 | ||
524 | #define QLCNIC_CDRP_CMD_CREATE_RX_CTX 0x00000007 | ||
525 | #define QLCNIC_CDRP_CMD_DESTROY_RX_CTX 0x00000008 | ||
526 | #define QLCNIC_CDRP_CMD_CREATE_TX_CTX 0x00000009 | ||
527 | #define QLCNIC_CDRP_CMD_DESTROY_TX_CTX 0x0000000a | ||
528 | #define QLCNIC_CDRP_CMD_INTRPT_TEST 0x00000011 | ||
529 | #define QLCNIC_CDRP_CMD_SET_MTU 0x00000012 | ||
530 | #define QLCNIC_CDRP_CMD_READ_PHY 0x00000013 | ||
531 | #define QLCNIC_CDRP_CMD_WRITE_PHY 0x00000014 | ||
532 | #define QLCNIC_CDRP_CMD_READ_HW_REG 0x00000015 | ||
533 | #define QLCNIC_CDRP_CMD_GET_FLOW_CTL 0x00000016 | ||
534 | #define QLCNIC_CDRP_CMD_SET_FLOW_CTL 0x00000017 | ||
535 | #define QLCNIC_CDRP_CMD_READ_MAX_MTU 0x00000018 | ||
536 | #define QLCNIC_CDRP_CMD_READ_MAX_LRO 0x00000019 | ||
537 | #define QLCNIC_CDRP_CMD_MAC_ADDRESS 0x0000001f | ||
538 | |||
539 | #define QLCNIC_CDRP_CMD_GET_PCI_INFO 0x00000020 | ||
540 | #define QLCNIC_CDRP_CMD_GET_NIC_INFO 0x00000021 | ||
541 | #define QLCNIC_CDRP_CMD_SET_NIC_INFO 0x00000022 | ||
542 | #define QLCNIC_CDRP_CMD_GET_ESWITCH_CAPABILITY 0x00000024 | ||
543 | #define QLCNIC_CDRP_CMD_TOGGLE_ESWITCH 0x00000025 | ||
544 | #define QLCNIC_CDRP_CMD_GET_ESWITCH_STATUS 0x00000026 | ||
545 | #define QLCNIC_CDRP_CMD_SET_PORTMIRRORING 0x00000027 | ||
546 | #define QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH 0x00000028 | ||
547 | #define QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG 0x00000029 | ||
548 | #define QLCNIC_CDRP_CMD_GET_ESWITCH_STATS 0x0000002a | ||
549 | #define QLCNIC_CDRP_CMD_CONFIG_PORT 0x0000002E | ||
550 | #define QLCNIC_CDRP_CMD_TEMP_SIZE 0x0000002f | ||
551 | #define QLCNIC_CDRP_CMD_GET_TEMP_HDR 0x00000030 | ||
552 | #define QLCNIC_CDRP_CMD_GET_MAC_STATS 0x00000037 | ||
553 | 573 | ||
554 | #define QLCNIC_RCODE_SUCCESS 0 | 574 | #define QLCNIC_RCODE_SUCCESS 0 |
555 | #define QLCNIC_RCODE_INVALID_ARGS 6 | 575 | #define QLCNIC_RCODE_INVALID_ARGS 6 |
@@ -726,6 +746,11 @@ struct qlcnic_mac_list_s { | |||
726 | uint8_t mac_addr[ETH_ALEN+2]; | 746 | uint8_t mac_addr[ETH_ALEN+2]; |
727 | }; | 747 | }; |
728 | 748 | ||
749 | /* MAC Learn */ | ||
750 | #define NO_MAC_LEARN 0 | ||
751 | #define DRV_MAC_LEARN 1 | ||
752 | #define FDB_MAC_LEARN 2 | ||
753 | |||
729 | #define QLCNIC_HOST_REQUEST 0x13 | 754 | #define QLCNIC_HOST_REQUEST 0x13 |
730 | #define QLCNIC_REQUEST 0x14 | 755 | #define QLCNIC_REQUEST 0x14 |
731 | 756 | ||
@@ -762,7 +787,7 @@ struct qlcnic_mac_list_s { | |||
762 | */ | 787 | */ |
763 | 788 | ||
764 | #define QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK 0x8f | 789 | #define QLCNIC_C2H_OPCODE_CONFIG_LOOPBACK 0x8f |
765 | #define QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE 141 | 790 | #define QLCNIC_C2H_OPCODE_GET_LINKEVENT_RESPONSE 0x8D |
766 | 791 | ||
767 | #define VPORT_MISS_MODE_DROP 0 /* drop all unmatched */ | 792 | #define VPORT_MISS_MODE_DROP 0 /* drop all unmatched */ |
768 | #define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */ | 793 | #define VPORT_MISS_MODE_ACCEPT_ALL 1 /* accept all packets */ |
@@ -779,6 +804,8 @@ struct qlcnic_mac_list_s { | |||
779 | #define QLCNIC_FW_CAPABILITY_MORE_CAPS BIT_31 | 804 | #define QLCNIC_FW_CAPABILITY_MORE_CAPS BIT_31 |
780 | 805 | ||
781 | #define QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG BIT_2 | 806 | #define QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG BIT_2 |
807 | #define QLCNIC_FW_CAP2_HW_LRO_IPV6 BIT_3 | ||
808 | #define QLCNIC_FW_CAPABILITY_2_OCBB BIT_5 | ||
782 | 809 | ||
783 | /* module types */ | 810 | /* module types */ |
784 | #define LINKEVENT_MODULE_NOT_PRESENT 1 | 811 | #define LINKEVENT_MODULE_NOT_PRESENT 1 |
@@ -855,7 +882,7 @@ struct qlcnic_ipaddr { | |||
855 | 882 | ||
856 | #define QLCNIC_MSI_ENABLED 0x02 | 883 | #define QLCNIC_MSI_ENABLED 0x02 |
857 | #define QLCNIC_MSIX_ENABLED 0x04 | 884 | #define QLCNIC_MSIX_ENABLED 0x04 |
858 | #define QLCNIC_LRO_ENABLED 0x08 | 885 | #define QLCNIC_LRO_ENABLED 0x01 |
859 | #define QLCNIC_LRO_DISABLED 0x00 | 886 | #define QLCNIC_LRO_DISABLED 0x00 |
860 | #define QLCNIC_BRIDGE_ENABLED 0X10 | 887 | #define QLCNIC_BRIDGE_ENABLED 0X10 |
861 | #define QLCNIC_DIAG_ENABLED 0x20 | 888 | #define QLCNIC_DIAG_ENABLED 0x20 |
@@ -887,6 +914,7 @@ struct qlcnic_ipaddr { | |||
887 | #define __QLCNIC_AER 5 | 914 | #define __QLCNIC_AER 5 |
888 | #define __QLCNIC_DIAG_RES_ALLOC 6 | 915 | #define __QLCNIC_DIAG_RES_ALLOC 6 |
889 | #define __QLCNIC_LED_ENABLE 7 | 916 | #define __QLCNIC_LED_ENABLE 7 |
917 | #define __QLCNIC_ELB_INPROGRESS 8 | ||
890 | 918 | ||
891 | #define QLCNIC_INTERRUPT_TEST 1 | 919 | #define QLCNIC_INTERRUPT_TEST 1 |
892 | #define QLCNIC_LOOPBACK_TEST 2 | 920 | #define QLCNIC_LOOPBACK_TEST 2 |
@@ -895,12 +923,14 @@ struct qlcnic_ipaddr { | |||
895 | #define QLCNIC_FILTER_AGE 80 | 923 | #define QLCNIC_FILTER_AGE 80 |
896 | #define QLCNIC_READD_AGE 20 | 924 | #define QLCNIC_READD_AGE 20 |
897 | #define QLCNIC_LB_MAX_FILTERS 64 | 925 | #define QLCNIC_LB_MAX_FILTERS 64 |
926 | #define QLCNIC_LB_BUCKET_SIZE 32 | ||
898 | 927 | ||
899 | /* QLCNIC Driver Error Code */ | 928 | /* QLCNIC Driver Error Code */ |
900 | #define QLCNIC_FW_NOT_RESPOND 51 | 929 | #define QLCNIC_FW_NOT_RESPOND 51 |
901 | #define QLCNIC_TEST_IN_PROGRESS 52 | 930 | #define QLCNIC_TEST_IN_PROGRESS 52 |
902 | #define QLCNIC_UNDEFINED_ERROR 53 | 931 | #define QLCNIC_UNDEFINED_ERROR 53 |
903 | #define QLCNIC_LB_CABLE_NOT_CONN 54 | 932 | #define QLCNIC_LB_CABLE_NOT_CONN 54 |
933 | #define QLCNIC_ILB_MAX_RCV_LOOP 10 | ||
904 | 934 | ||
905 | struct qlcnic_filter { | 935 | struct qlcnic_filter { |
906 | struct hlist_node fnode; | 936 | struct hlist_node fnode; |
@@ -912,7 +942,8 @@ struct qlcnic_filter { | |||
912 | struct qlcnic_filter_hash { | 942 | struct qlcnic_filter_hash { |
913 | struct hlist_head *fhead; | 943 | struct hlist_head *fhead; |
914 | u8 fnum; | 944 | u8 fnum; |
915 | u8 fmax; | 945 | u16 fmax; |
946 | u16 fbucket_size; | ||
916 | }; | 947 | }; |
917 | 948 | ||
918 | struct qlcnic_adapter { | 949 | struct qlcnic_adapter { |
@@ -934,6 +965,7 @@ struct qlcnic_adapter { | |||
934 | 965 | ||
935 | u8 max_rds_rings; | 966 | u8 max_rds_rings; |
936 | u8 max_sds_rings; | 967 | u8 max_sds_rings; |
968 | u8 rx_csum; | ||
937 | u8 portnum; | 969 | u8 portnum; |
938 | 970 | ||
939 | u8 fw_wait_cnt; | 971 | u8 fw_wait_cnt; |
@@ -954,8 +986,10 @@ struct qlcnic_adapter { | |||
954 | u8 mac_addr[ETH_ALEN]; | 986 | u8 mac_addr[ETH_ALEN]; |
955 | 987 | ||
956 | u64 dev_rst_time; | 988 | u64 dev_rst_time; |
957 | u8 mac_learn; | 989 | bool drv_mac_learn; |
990 | bool fdb_mac_learn; | ||
958 | unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)]; | 991 | unsigned long vlans[BITS_TO_LONGS(VLAN_N_VID)]; |
992 | u8 flash_mfg_id; | ||
959 | struct qlcnic_npar_info *npars; | 993 | struct qlcnic_npar_info *npars; |
960 | struct qlcnic_eswitch *eswitch; | 994 | struct qlcnic_eswitch *eswitch; |
961 | struct qlcnic_nic_template *nic_ops; | 995 | struct qlcnic_nic_template *nic_ops; |
@@ -969,12 +1003,17 @@ struct qlcnic_adapter { | |||
969 | void __iomem *isr_int_vec; | 1003 | void __iomem *isr_int_vec; |
970 | 1004 | ||
971 | struct msix_entry *msix_entries; | 1005 | struct msix_entry *msix_entries; |
1006 | struct workqueue_struct *qlcnic_wq; | ||
972 | struct delayed_work fw_work; | 1007 | struct delayed_work fw_work; |
1008 | struct delayed_work idc_aen_work; | ||
973 | 1009 | ||
974 | struct qlcnic_filter_hash fhash; | 1010 | struct qlcnic_filter_hash fhash; |
1011 | struct qlcnic_filter_hash rx_fhash; | ||
975 | 1012 | ||
976 | spinlock_t tx_clean_lock; | 1013 | spinlock_t tx_clean_lock; |
977 | spinlock_t mac_learn_lock; | 1014 | spinlock_t mac_learn_lock; |
1015 | /* spinlock for catching rcv filters for eswitch traffic */ | ||
1016 | spinlock_t rx_mac_learn_lock; | ||
978 | u32 file_prd_off; /*File fw product offset*/ | 1017 | u32 file_prd_off; /*File fw product offset*/ |
979 | u32 fw_version; | 1018 | u32 fw_version; |
980 | const struct firmware *fw; | 1019 | const struct firmware *fw; |
@@ -995,7 +1034,24 @@ struct qlcnic_info_le { | |||
995 | __le16 max_rx_ques; | 1034 | __le16 max_rx_ques; |
996 | __le16 min_tx_bw; | 1035 | __le16 min_tx_bw; |
997 | __le16 max_tx_bw; | 1036 | __le16 max_tx_bw; |
998 | u8 reserved2[104]; | 1037 | __le32 op_type; |
1038 | __le16 max_bw_reg_offset; | ||
1039 | __le16 max_linkspeed_reg_offset; | ||
1040 | __le32 capability1; | ||
1041 | __le32 capability2; | ||
1042 | __le32 capability3; | ||
1043 | __le16 max_tx_mac_filters; | ||
1044 | __le16 max_rx_mcast_mac_filters; | ||
1045 | __le16 max_rx_ucast_mac_filters; | ||
1046 | __le16 max_rx_ip_addr; | ||
1047 | __le16 max_rx_lro_flow; | ||
1048 | __le16 max_rx_status_rings; | ||
1049 | __le16 max_rx_buf_rings; | ||
1050 | __le16 max_tx_vlan_keys; | ||
1051 | u8 total_pf; | ||
1052 | u8 total_rss_engines; | ||
1053 | __le16 max_vports; | ||
1054 | u8 reserved2[64]; | ||
999 | } __packed; | 1055 | } __packed; |
1000 | 1056 | ||
1001 | struct qlcnic_info { | 1057 | struct qlcnic_info { |
@@ -1005,12 +1061,28 @@ struct qlcnic_info { | |||
1005 | u16 switch_mode; | 1061 | u16 switch_mode; |
1006 | u32 capabilities; | 1062 | u32 capabilities; |
1007 | u8 max_mac_filters; | 1063 | u8 max_mac_filters; |
1008 | u8 reserved1; | ||
1009 | u16 max_mtu; | 1064 | u16 max_mtu; |
1010 | u16 max_tx_ques; | 1065 | u16 max_tx_ques; |
1011 | u16 max_rx_ques; | 1066 | u16 max_rx_ques; |
1012 | u16 min_tx_bw; | 1067 | u16 min_tx_bw; |
1013 | u16 max_tx_bw; | 1068 | u16 max_tx_bw; |
1069 | u32 op_type; | ||
1070 | u16 max_bw_reg_offset; | ||
1071 | u16 max_linkspeed_reg_offset; | ||
1072 | u32 capability1; | ||
1073 | u32 capability2; | ||
1074 | u32 capability3; | ||
1075 | u16 max_tx_mac_filters; | ||
1076 | u16 max_rx_mcast_mac_filters; | ||
1077 | u16 max_rx_ucast_mac_filters; | ||
1078 | u16 max_rx_ip_addr; | ||
1079 | u16 max_rx_lro_flow; | ||
1080 | u16 max_rx_status_rings; | ||
1081 | u16 max_rx_buf_rings; | ||
1082 | u16 max_tx_vlan_keys; | ||
1083 | u8 total_pf; | ||
1084 | u8 total_rss_engines; | ||
1085 | u16 max_vports; | ||
1014 | }; | 1086 | }; |
1015 | 1087 | ||
1016 | struct qlcnic_pci_info_le { | 1088 | struct qlcnic_pci_info_le { |
@@ -1024,7 +1096,9 @@ struct qlcnic_pci_info_le { | |||
1024 | __le16 reserved1[2]; | 1096 | __le16 reserved1[2]; |
1025 | 1097 | ||
1026 | u8 mac[ETH_ALEN]; | 1098 | u8 mac[ETH_ALEN]; |
1027 | u8 reserved2[106]; | 1099 | __le16 func_count; |
1100 | u8 reserved2[104]; | ||
1101 | |||
1028 | } __packed; | 1102 | } __packed; |
1029 | 1103 | ||
1030 | struct qlcnic_pci_info { | 1104 | struct qlcnic_pci_info { |
@@ -1035,6 +1109,7 @@ struct qlcnic_pci_info { | |||
1035 | u16 tx_min_bw; | 1109 | u16 tx_min_bw; |
1036 | u16 tx_max_bw; | 1110 | u16 tx_max_bw; |
1037 | u8 mac[ETH_ALEN]; | 1111 | u8 mac[ETH_ALEN]; |
1112 | u16 func_count; | ||
1038 | }; | 1113 | }; |
1039 | 1114 | ||
1040 | struct qlcnic_npar_info { | 1115 | struct qlcnic_npar_info { |
@@ -1266,10 +1341,8 @@ struct qlcnic_esw_statistics { | |||
1266 | #define QLCNIC_RESET_QUIESCENT 0xadd00020 | 1341 | #define QLCNIC_RESET_QUIESCENT 0xadd00020 |
1267 | 1342 | ||
1268 | struct _cdrp_cmd { | 1343 | struct _cdrp_cmd { |
1269 | u32 cmd; | 1344 | u32 num; |
1270 | u32 arg1; | 1345 | u32 *arg; |
1271 | u32 arg2; | ||
1272 | u32 arg3; | ||
1273 | }; | 1346 | }; |
1274 | 1347 | ||
1275 | struct qlcnic_cmd_args { | 1348 | struct qlcnic_cmd_args { |
@@ -1279,9 +1352,6 @@ struct qlcnic_cmd_args { | |||
1279 | 1352 | ||
1280 | int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter); | 1353 | int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter); |
1281 | int qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config); | 1354 | int qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config); |
1282 | |||
1283 | int qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off); | ||
1284 | int qlcnic_hw_write_wx_2M(struct qlcnic_adapter *, ulong off, u32 data); | ||
1285 | int qlcnic_pci_mem_write_2M(struct qlcnic_adapter *, u64 off, u64 data); | 1355 | int qlcnic_pci_mem_write_2M(struct qlcnic_adapter *, u64 off, u64 data); |
1286 | int qlcnic_pci_mem_read_2M(struct qlcnic_adapter *, u64 off, u64 *data); | 1356 | int qlcnic_pci_mem_read_2M(struct qlcnic_adapter *, u64 off, u64 *data); |
1287 | void qlcnic_pci_camqm_read_2M(struct qlcnic_adapter *, u64, u64 *); | 1357 | void qlcnic_pci_camqm_read_2M(struct qlcnic_adapter *, u64, u64 *); |
@@ -1291,9 +1361,10 @@ void qlcnic_pci_camqm_write_2M(struct qlcnic_adapter *, u64, u64); | |||
1291 | (((addr) < (high)) && ((addr) >= (low))) | 1361 | (((addr) < (high)) && ((addr) >= (low))) |
1292 | 1362 | ||
1293 | #define QLCRD32(adapter, off) \ | 1363 | #define QLCRD32(adapter, off) \ |
1294 | (qlcnic_hw_read_wx_2M(adapter, off)) | 1364 | (adapter->ahw->hw_ops->read_reg)(adapter, off) |
1365 | |||
1295 | #define QLCWR32(adapter, off, val) \ | 1366 | #define QLCWR32(adapter, off, val) \ |
1296 | (qlcnic_hw_write_wx_2M(adapter, off, val)) | 1367 | adapter->ahw->hw_ops->write_reg(adapter, off, val) |
1297 | 1368 | ||
1298 | int qlcnic_pcie_sem_lock(struct qlcnic_adapter *, int, u32); | 1369 | int qlcnic_pcie_sem_lock(struct qlcnic_adapter *, int, u32); |
1299 | void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int); | 1370 | void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int); |
@@ -1306,10 +1377,6 @@ void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int); | |||
1306 | qlcnic_pcie_sem_lock((a), 3, QLCNIC_PHY_LOCK_ID) | 1377 | qlcnic_pcie_sem_lock((a), 3, QLCNIC_PHY_LOCK_ID) |
1307 | #define qlcnic_phy_unlock(a) \ | 1378 | #define qlcnic_phy_unlock(a) \ |
1308 | qlcnic_pcie_sem_unlock((a), 3) | 1379 | qlcnic_pcie_sem_unlock((a), 3) |
1309 | #define qlcnic_api_lock(a) \ | ||
1310 | qlcnic_pcie_sem_lock((a), 5, 0) | ||
1311 | #define qlcnic_api_unlock(a) \ | ||
1312 | qlcnic_pcie_sem_unlock((a), 5) | ||
1313 | #define qlcnic_sw_lock(a) \ | 1380 | #define qlcnic_sw_lock(a) \ |
1314 | qlcnic_pcie_sem_lock((a), 6, 0) | 1381 | qlcnic_pcie_sem_lock((a), 6, 0) |
1315 | #define qlcnic_sw_unlock(a) \ | 1382 | #define qlcnic_sw_unlock(a) \ |
@@ -1324,14 +1391,13 @@ void qlcnic_pcie_sem_unlock(struct qlcnic_adapter *, int); | |||
1324 | 1391 | ||
1325 | #define MAX_CTL_CHECK 1000 | 1392 | #define MAX_CTL_CHECK 1000 |
1326 | 1393 | ||
1327 | int qlcnic_get_board_info(struct qlcnic_adapter *adapter); | ||
1328 | int qlcnic_wol_supported(struct qlcnic_adapter *adapter); | 1394 | int qlcnic_wol_supported(struct qlcnic_adapter *adapter); |
1329 | int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate); | ||
1330 | void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter); | 1395 | void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter); |
1331 | void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter); | 1396 | void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter); |
1332 | int qlcnic_dump_fw(struct qlcnic_adapter *); | 1397 | int qlcnic_dump_fw(struct qlcnic_adapter *); |
1333 | 1398 | ||
1334 | /* Functions from qlcnic_init.c */ | 1399 | /* Functions from qlcnic_init.c */ |
1400 | void qlcnic_schedule_work(struct qlcnic_adapter *, work_func_t, int); | ||
1335 | int qlcnic_load_firmware(struct qlcnic_adapter *adapter); | 1401 | int qlcnic_load_firmware(struct qlcnic_adapter *adapter); |
1336 | int qlcnic_need_fw_reset(struct qlcnic_adapter *adapter); | 1402 | int qlcnic_need_fw_reset(struct qlcnic_adapter *adapter); |
1337 | void qlcnic_request_firmware(struct qlcnic_adapter *adapter); | 1403 | void qlcnic_request_firmware(struct qlcnic_adapter *adapter); |
@@ -1361,54 +1427,42 @@ void qlcnic_release_tx_buffers(struct qlcnic_adapter *adapter); | |||
1361 | int qlcnic_check_fw_status(struct qlcnic_adapter *adapter); | 1427 | int qlcnic_check_fw_status(struct qlcnic_adapter *adapter); |
1362 | void qlcnic_watchdog_task(struct work_struct *work); | 1428 | void qlcnic_watchdog_task(struct work_struct *work); |
1363 | void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, | 1429 | void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, |
1364 | struct qlcnic_host_rds_ring *rds_ring); | 1430 | struct qlcnic_host_rds_ring *rds_ring, u8 ring_id); |
1365 | int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max); | 1431 | int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max); |
1366 | void qlcnic_set_multi(struct net_device *netdev); | 1432 | void qlcnic_set_multi(struct net_device *netdev); |
1433 | int qlcnic_nic_add_mac(struct qlcnic_adapter *, const u8 *); | ||
1434 | int qlcnic_nic_del_mac(struct qlcnic_adapter *, const u8 *); | ||
1367 | void qlcnic_free_mac_list(struct qlcnic_adapter *adapter); | 1435 | void qlcnic_free_mac_list(struct qlcnic_adapter *adapter); |
1368 | int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter, u32); | ||
1369 | int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter); | ||
1370 | int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable); | ||
1371 | int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd); | ||
1372 | int qlcnic_linkevent_request(struct qlcnic_adapter *adapter, int enable); | ||
1373 | void qlcnic_advert_link_change(struct qlcnic_adapter *adapter, int linkup); | ||
1374 | 1436 | ||
1375 | int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu); | 1437 | int qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu); |
1438 | int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *); | ||
1376 | int qlcnic_change_mtu(struct net_device *netdev, int new_mtu); | 1439 | int qlcnic_change_mtu(struct net_device *netdev, int new_mtu); |
1377 | netdev_features_t qlcnic_fix_features(struct net_device *netdev, | 1440 | netdev_features_t qlcnic_fix_features(struct net_device *netdev, |
1378 | netdev_features_t features); | 1441 | netdev_features_t features); |
1379 | int qlcnic_set_features(struct net_device *netdev, netdev_features_t features); | 1442 | int qlcnic_set_features(struct net_device *netdev, netdev_features_t features); |
1380 | int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable); | ||
1381 | int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable); | 1443 | int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable); |
1382 | int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter); | 1444 | int qlcnic_send_lro_cleanup(struct qlcnic_adapter *adapter); |
1383 | void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *); | 1445 | void qlcnic_update_cmd_producer(struct qlcnic_host_tx_ring *); |
1384 | void qlcnic_fetch_mac(u32, u32, u8, u8 *); | ||
1385 | void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring); | ||
1386 | void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter); | ||
1387 | int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode); | ||
1388 | 1446 | ||
1389 | /* Functions from qlcnic_ethtool.c */ | 1447 | /* Functions from qlcnic_ethtool.c */ |
1390 | int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[]); | 1448 | int qlcnic_check_loopback_buff(unsigned char *, u8 []); |
1449 | int qlcnic_do_lb_test(struct qlcnic_adapter *, u8); | ||
1450 | int qlcnic_loopback_test(struct net_device *, u8); | ||
1391 | 1451 | ||
1392 | /* Functions from qlcnic_main.c */ | 1452 | /* Functions from qlcnic_main.c */ |
1393 | int qlcnic_reset_context(struct qlcnic_adapter *); | 1453 | int qlcnic_reset_context(struct qlcnic_adapter *); |
1394 | void qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *); | ||
1395 | void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings); | 1454 | void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings); |
1396 | int qlcnic_diag_alloc_res(struct net_device *netdev, int test); | 1455 | int qlcnic_diag_alloc_res(struct net_device *netdev, int test); |
1397 | netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev); | 1456 | netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev); |
1398 | int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val); | 1457 | int qlcnic_set_max_rss(struct qlcnic_adapter *, u8, size_t); |
1399 | int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data); | 1458 | int qlcnic_validate_max_rss(u8, u8); |
1400 | void qlcnic_dev_request_reset(struct qlcnic_adapter *); | ||
1401 | void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter); | 1459 | void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter); |
1402 | 1460 | int qlcnic_enable_msix(struct qlcnic_adapter *, u32); | |
1403 | /* Management functions */ | ||
1404 | int qlcnic_get_mac_address(struct qlcnic_adapter *, u8*); | ||
1405 | int qlcnic_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8); | ||
1406 | int qlcnic_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *); | ||
1407 | int qlcnic_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info*); | ||
1408 | 1461 | ||
1409 | /* eSwitch management functions */ | 1462 | /* eSwitch management functions */ |
1410 | int qlcnic_config_switch_port(struct qlcnic_adapter *, | 1463 | int qlcnic_config_switch_port(struct qlcnic_adapter *, |
1411 | struct qlcnic_esw_func_cfg *); | 1464 | struct qlcnic_esw_func_cfg *); |
1465 | |||
1412 | int qlcnic_get_eswitch_port_config(struct qlcnic_adapter *, | 1466 | int qlcnic_get_eswitch_port_config(struct qlcnic_adapter *, |
1413 | struct qlcnic_esw_func_cfg *); | 1467 | struct qlcnic_esw_func_cfg *); |
1414 | int qlcnic_config_port_mirroring(struct qlcnic_adapter *, u8, u8, u8); | 1468 | int qlcnic_config_port_mirroring(struct qlcnic_adapter *, u8, u8, u8); |
@@ -1418,14 +1472,12 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *, const u8, u8, | |||
1418 | struct __qlcnic_esw_statistics *); | 1472 | struct __qlcnic_esw_statistics *); |
1419 | int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8); | 1473 | int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, u8, u8, u8); |
1420 | int qlcnic_get_mac_stats(struct qlcnic_adapter *, struct qlcnic_mac_statistics *); | 1474 | int qlcnic_get_mac_stats(struct qlcnic_adapter *, struct qlcnic_mac_statistics *); |
1421 | extern int qlcnic_config_tso; | ||
1422 | 1475 | ||
1423 | int qlcnic_napi_add(struct qlcnic_adapter *, struct net_device *); | 1476 | void qlcnic_free_mbx_args(struct qlcnic_cmd_args *cmd); |
1424 | void qlcnic_napi_del(struct qlcnic_adapter *adapter); | 1477 | |
1425 | void qlcnic_napi_enable(struct qlcnic_adapter *adapter); | ||
1426 | void qlcnic_napi_disable(struct qlcnic_adapter *adapter); | ||
1427 | int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *, int); | 1478 | int qlcnic_alloc_sds_rings(struct qlcnic_recv_context *, int); |
1428 | void qlcnic_free_sds_rings(struct qlcnic_recv_context *); | 1479 | void qlcnic_free_sds_rings(struct qlcnic_recv_context *); |
1480 | void qlcnic_advert_link_change(struct qlcnic_adapter *, int); | ||
1429 | void qlcnic_free_tx_rings(struct qlcnic_adapter *); | 1481 | void qlcnic_free_tx_rings(struct qlcnic_adapter *); |
1430 | int qlcnic_alloc_tx_rings(struct qlcnic_adapter *, struct net_device *); | 1482 | int qlcnic_alloc_tx_rings(struct qlcnic_adapter *, struct net_device *); |
1431 | 1483 | ||
@@ -1433,6 +1485,9 @@ void qlcnic_create_sysfs_entries(struct qlcnic_adapter *adapter); | |||
1433 | void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter); | 1485 | void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter); |
1434 | void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter); | 1486 | void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter); |
1435 | void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter); | 1487 | void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter); |
1488 | void qlcnic_82xx_add_sysfs(struct qlcnic_adapter *adapter); | ||
1489 | void qlcnic_82xx_remove_sysfs(struct qlcnic_adapter *adapter); | ||
1490 | |||
1436 | int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32); | 1491 | int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *, u32); |
1437 | int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32); | 1492 | int qlcnicvf_config_led(struct qlcnic_adapter *, u32, u32); |
1438 | void qlcnic_set_vlan_config(struct qlcnic_adapter *, | 1493 | void qlcnic_set_vlan_config(struct qlcnic_adapter *, |
@@ -1440,6 +1495,22 @@ void qlcnic_set_vlan_config(struct qlcnic_adapter *, | |||
1440 | void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *, | 1495 | void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *, |
1441 | struct qlcnic_esw_func_cfg *); | 1496 | struct qlcnic_esw_func_cfg *); |
1442 | 1497 | ||
1498 | void qlcnic_down(struct qlcnic_adapter *, struct net_device *); | ||
1499 | int qlcnic_up(struct qlcnic_adapter *, struct net_device *); | ||
1500 | void __qlcnic_down(struct qlcnic_adapter *, struct net_device *); | ||
1501 | void qlcnic_detach(struct qlcnic_adapter *); | ||
1502 | void qlcnic_teardown_intr(struct qlcnic_adapter *); | ||
1503 | int qlcnic_attach(struct qlcnic_adapter *); | ||
1504 | int __qlcnic_up(struct qlcnic_adapter *, struct net_device *); | ||
1505 | void qlcnic_restore_indev_addr(struct net_device *, unsigned long); | ||
1506 | |||
1507 | int qlcnic_check_temp(struct qlcnic_adapter *); | ||
1508 | int qlcnic_init_pci_info(struct qlcnic_adapter *); | ||
1509 | int qlcnic_set_default_offload_settings(struct qlcnic_adapter *); | ||
1510 | int qlcnic_reset_npar_config(struct qlcnic_adapter *); | ||
1511 | int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *); | ||
1512 | void qlcnic_add_lb_filter(struct qlcnic_adapter *, struct sk_buff *, int, | ||
1513 | __le16); | ||
1443 | /* | 1514 | /* |
1444 | * QLOGIC Board information | 1515 | * QLOGIC Board information |
1445 | */ | 1516 | */ |
@@ -1462,6 +1533,277 @@ static inline u32 qlcnic_tx_avail(struct qlcnic_host_tx_ring *tx_ring) | |||
1462 | tx_ring->producer; | 1533 | tx_ring->producer; |
1463 | } | 1534 | } |
1464 | 1535 | ||
1536 | struct qlcnic_nic_template { | ||
1537 | int (*config_bridged_mode) (struct qlcnic_adapter *, u32); | ||
1538 | int (*config_led) (struct qlcnic_adapter *, u32, u32); | ||
1539 | int (*start_firmware) (struct qlcnic_adapter *); | ||
1540 | int (*init_driver) (struct qlcnic_adapter *); | ||
1541 | void (*request_reset) (struct qlcnic_adapter *, u32); | ||
1542 | void (*cancel_idc_work) (struct qlcnic_adapter *); | ||
1543 | int (*napi_add)(struct qlcnic_adapter *, struct net_device *); | ||
1544 | void (*napi_del)(struct qlcnic_adapter *); | ||
1545 | void (*config_ipaddr)(struct qlcnic_adapter *, __be32, int); | ||
1546 | irqreturn_t (*clear_legacy_intr)(struct qlcnic_adapter *); | ||
1547 | }; | ||
1548 | |||
1549 | /* Adapter hardware abstraction */ | ||
1550 | struct qlcnic_hardware_ops { | ||
1551 | void (*read_crb) (struct qlcnic_adapter *, char *, loff_t, size_t); | ||
1552 | void (*write_crb) (struct qlcnic_adapter *, char *, loff_t, size_t); | ||
1553 | int (*read_reg) (struct qlcnic_adapter *, ulong); | ||
1554 | int (*write_reg) (struct qlcnic_adapter *, ulong, u32); | ||
1555 | void (*get_ocm_win) (struct qlcnic_hardware_context *); | ||
1556 | int (*get_mac_address) (struct qlcnic_adapter *, u8 *); | ||
1557 | int (*setup_intr) (struct qlcnic_adapter *, u8); | ||
1558 | int (*alloc_mbx_args)(struct qlcnic_cmd_args *, | ||
1559 | struct qlcnic_adapter *, u32); | ||
1560 | int (*mbx_cmd) (struct qlcnic_adapter *, struct qlcnic_cmd_args *); | ||
1561 | void (*get_func_no) (struct qlcnic_adapter *); | ||
1562 | int (*api_lock) (struct qlcnic_adapter *); | ||
1563 | void (*api_unlock) (struct qlcnic_adapter *); | ||
1564 | void (*add_sysfs) (struct qlcnic_adapter *); | ||
1565 | void (*remove_sysfs) (struct qlcnic_adapter *); | ||
1566 | void (*process_lb_rcv_ring_diag) (struct qlcnic_host_sds_ring *); | ||
1567 | int (*create_rx_ctx) (struct qlcnic_adapter *); | ||
1568 | int (*create_tx_ctx) (struct qlcnic_adapter *, | ||
1569 | struct qlcnic_host_tx_ring *, int); | ||
1570 | int (*setup_link_event) (struct qlcnic_adapter *, int); | ||
1571 | int (*get_nic_info) (struct qlcnic_adapter *, struct qlcnic_info *, u8); | ||
1572 | int (*get_pci_info) (struct qlcnic_adapter *, struct qlcnic_pci_info *); | ||
1573 | int (*set_nic_info) (struct qlcnic_adapter *, struct qlcnic_info *); | ||
1574 | int (*change_macvlan) (struct qlcnic_adapter *, u8*, __le16, u8); | ||
1575 | void (*napi_enable) (struct qlcnic_adapter *); | ||
1576 | void (*napi_disable) (struct qlcnic_adapter *); | ||
1577 | void (*config_intr_coal) (struct qlcnic_adapter *); | ||
1578 | int (*config_rss) (struct qlcnic_adapter *, int); | ||
1579 | int (*config_hw_lro) (struct qlcnic_adapter *, int); | ||
1580 | int (*config_loopback) (struct qlcnic_adapter *, u8); | ||
1581 | int (*clear_loopback) (struct qlcnic_adapter *, u8); | ||
1582 | int (*config_promisc_mode) (struct qlcnic_adapter *, u32); | ||
1583 | void (*change_l2_filter) (struct qlcnic_adapter *, u64 *, __le16); | ||
1584 | int (*get_board_info) (struct qlcnic_adapter *); | ||
1585 | }; | ||
1586 | |||
1587 | extern struct qlcnic_nic_template qlcnic_vf_ops; | ||
1588 | |||
1589 | static inline int qlcnic_start_firmware(struct qlcnic_adapter *adapter) | ||
1590 | { | ||
1591 | return adapter->nic_ops->start_firmware(adapter); | ||
1592 | } | ||
1593 | |||
1594 | static inline void qlcnic_read_crb(struct qlcnic_adapter *adapter, char *buf, | ||
1595 | loff_t offset, size_t size) | ||
1596 | { | ||
1597 | adapter->ahw->hw_ops->read_crb(adapter, buf, offset, size); | ||
1598 | } | ||
1599 | |||
1600 | static inline void qlcnic_write_crb(struct qlcnic_adapter *adapter, char *buf, | ||
1601 | loff_t offset, size_t size) | ||
1602 | { | ||
1603 | adapter->ahw->hw_ops->write_crb(adapter, buf, offset, size); | ||
1604 | } | ||
1605 | |||
1606 | static inline int qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, | ||
1607 | ulong off) | ||
1608 | { | ||
1609 | return adapter->ahw->hw_ops->read_reg(adapter, off); | ||
1610 | } | ||
1611 | |||
1612 | static inline int qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, | ||
1613 | ulong off, u32 data) | ||
1614 | { | ||
1615 | return adapter->ahw->hw_ops->write_reg(adapter, off, data); | ||
1616 | } | ||
1617 | |||
1618 | static inline int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, | ||
1619 | u8 *mac) | ||
1620 | { | ||
1621 | return adapter->ahw->hw_ops->get_mac_address(adapter, mac); | ||
1622 | } | ||
1623 | |||
1624 | static inline int qlcnic_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr) | ||
1625 | { | ||
1626 | return adapter->ahw->hw_ops->setup_intr(adapter, num_intr); | ||
1627 | } | ||
1628 | |||
1629 | static inline int qlcnic_alloc_mbx_args(struct qlcnic_cmd_args *mbx, | ||
1630 | struct qlcnic_adapter *adapter, u32 arg) | ||
1631 | { | ||
1632 | return adapter->ahw->hw_ops->alloc_mbx_args(mbx, adapter, arg); | ||
1633 | } | ||
1634 | |||
1635 | static inline int qlcnic_issue_cmd(struct qlcnic_adapter *adapter, | ||
1636 | struct qlcnic_cmd_args *cmd) | ||
1637 | { | ||
1638 | return adapter->ahw->hw_ops->mbx_cmd(adapter, cmd); | ||
1639 | } | ||
1640 | |||
1641 | static inline void qlcnic_get_func_no(struct qlcnic_adapter *adapter) | ||
1642 | { | ||
1643 | adapter->ahw->hw_ops->get_func_no(adapter); | ||
1644 | } | ||
1645 | |||
1646 | static inline int qlcnic_api_lock(struct qlcnic_adapter *adapter) | ||
1647 | { | ||
1648 | return adapter->ahw->hw_ops->api_lock(adapter); | ||
1649 | } | ||
1650 | |||
1651 | static inline void qlcnic_api_unlock(struct qlcnic_adapter *adapter) | ||
1652 | { | ||
1653 | adapter->ahw->hw_ops->api_unlock(adapter); | ||
1654 | } | ||
1655 | |||
1656 | static inline void qlcnic_add_sysfs(struct qlcnic_adapter *adapter) | ||
1657 | { | ||
1658 | adapter->ahw->hw_ops->add_sysfs(adapter); | ||
1659 | } | ||
1660 | |||
1661 | static inline void qlcnic_remove_sysfs(struct qlcnic_adapter *adapter) | ||
1662 | { | ||
1663 | adapter->ahw->hw_ops->remove_sysfs(adapter); | ||
1664 | } | ||
1665 | |||
1666 | static inline void | ||
1667 | qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring) | ||
1668 | { | ||
1669 | sds_ring->adapter->ahw->hw_ops->process_lb_rcv_ring_diag(sds_ring); | ||
1670 | } | ||
1671 | |||
1672 | static inline int qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | ||
1673 | { | ||
1674 | return adapter->ahw->hw_ops->create_rx_ctx(adapter); | ||
1675 | } | ||
1676 | |||
1677 | static inline int qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter, | ||
1678 | struct qlcnic_host_tx_ring *ptr, | ||
1679 | int ring) | ||
1680 | { | ||
1681 | return adapter->ahw->hw_ops->create_tx_ctx(adapter, ptr, ring); | ||
1682 | } | ||
1683 | |||
1684 | static inline int qlcnic_linkevent_request(struct qlcnic_adapter *adapter, | ||
1685 | int enable) | ||
1686 | { | ||
1687 | return adapter->ahw->hw_ops->setup_link_event(adapter, enable); | ||
1688 | } | ||
1689 | |||
1690 | static inline int qlcnic_get_nic_info(struct qlcnic_adapter *adapter, | ||
1691 | struct qlcnic_info *info, u8 id) | ||
1692 | { | ||
1693 | return adapter->ahw->hw_ops->get_nic_info(adapter, info, id); | ||
1694 | } | ||
1695 | |||
1696 | static inline int qlcnic_get_pci_info(struct qlcnic_adapter *adapter, | ||
1697 | struct qlcnic_pci_info *info) | ||
1698 | { | ||
1699 | return adapter->ahw->hw_ops->get_pci_info(adapter, info); | ||
1700 | } | ||
1701 | |||
1702 | static inline int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, | ||
1703 | struct qlcnic_info *info) | ||
1704 | { | ||
1705 | return adapter->ahw->hw_ops->set_nic_info(adapter, info); | ||
1706 | } | ||
1707 | |||
1708 | static inline int qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, | ||
1709 | u8 *addr, __le16 id, u8 cmd) | ||
1710 | { | ||
1711 | return adapter->ahw->hw_ops->change_macvlan(adapter, addr, id, cmd); | ||
1712 | } | ||
1713 | |||
1714 | static inline int qlcnic_napi_add(struct qlcnic_adapter *adapter, | ||
1715 | struct net_device *netdev) | ||
1716 | { | ||
1717 | return adapter->nic_ops->napi_add(adapter, netdev); | ||
1718 | } | ||
1719 | |||
1720 | static inline void qlcnic_napi_del(struct qlcnic_adapter *adapter) | ||
1721 | { | ||
1722 | adapter->nic_ops->napi_del(adapter); | ||
1723 | } | ||
1724 | |||
1725 | static inline void qlcnic_napi_enable(struct qlcnic_adapter *adapter) | ||
1726 | { | ||
1727 | adapter->ahw->hw_ops->napi_enable(adapter); | ||
1728 | } | ||
1729 | |||
1730 | static inline void qlcnic_napi_disable(struct qlcnic_adapter *adapter) | ||
1731 | { | ||
1732 | adapter->ahw->hw_ops->napi_disable(adapter); | ||
1733 | } | ||
1734 | |||
1735 | static inline void qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter) | ||
1736 | { | ||
1737 | adapter->ahw->hw_ops->config_intr_coal(adapter); | ||
1738 | } | ||
1739 | |||
1740 | static inline int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable) | ||
1741 | { | ||
1742 | return adapter->ahw->hw_ops->config_rss(adapter, enable); | ||
1743 | } | ||
1744 | |||
1745 | static inline int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, | ||
1746 | int enable) | ||
1747 | { | ||
1748 | return adapter->ahw->hw_ops->config_hw_lro(adapter, enable); | ||
1749 | } | ||
1750 | |||
1751 | static inline int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode) | ||
1752 | { | ||
1753 | return adapter->ahw->hw_ops->config_loopback(adapter, mode); | ||
1754 | } | ||
1755 | |||
1756 | static inline int qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode) | ||
1757 | { | ||
1758 | return adapter->ahw->hw_ops->clear_loopback(adapter, mode); | ||
1759 | } | ||
1760 | |||
1761 | static inline int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter, | ||
1762 | u32 mode) | ||
1763 | { | ||
1764 | return adapter->ahw->hw_ops->config_promisc_mode(adapter, mode); | ||
1765 | } | ||
1766 | |||
1767 | static inline void qlcnic_change_filter(struct qlcnic_adapter *adapter, | ||
1768 | u64 *addr, __le16 id) | ||
1769 | { | ||
1770 | adapter->ahw->hw_ops->change_l2_filter(adapter, addr, id); | ||
1771 | } | ||
1772 | |||
1773 | static inline int qlcnic_get_board_info(struct qlcnic_adapter *adapter) | ||
1774 | { | ||
1775 | return adapter->ahw->hw_ops->get_board_info(adapter); | ||
1776 | } | ||
1777 | |||
1778 | static inline void qlcnic_dev_request_reset(struct qlcnic_adapter *adapter, | ||
1779 | u32 key) | ||
1780 | { | ||
1781 | adapter->nic_ops->request_reset(adapter, key); | ||
1782 | } | ||
1783 | |||
1784 | static inline void qlcnic_cancel_idc_work(struct qlcnic_adapter *adapter) | ||
1785 | { | ||
1786 | adapter->nic_ops->cancel_idc_work(adapter); | ||
1787 | } | ||
1788 | |||
1789 | static inline irqreturn_t | ||
1790 | qlcnic_clear_legacy_intr(struct qlcnic_adapter *adapter) | ||
1791 | { | ||
1792 | return adapter->nic_ops->clear_legacy_intr(adapter); | ||
1793 | } | ||
1794 | |||
1795 | static inline int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, | ||
1796 | u32 rate) | ||
1797 | { | ||
1798 | return adapter->nic_ops->config_led(adapter, state, rate); | ||
1799 | } | ||
1800 | |||
1801 | static inline void qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, | ||
1802 | __be32 ip, int cmd) | ||
1803 | { | ||
1804 | adapter->nic_ops->config_ipaddr(adapter, ip, cmd); | ||
1805 | } | ||
1806 | |||
1465 | static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring) | 1807 | static inline void qlcnic_disable_int(struct qlcnic_host_sds_ring *sds_ring) |
1466 | { | 1808 | { |
1467 | writel(0, sds_ring->crb_intr_mask); | 1809 | writel(0, sds_ring->crb_intr_mask); |
@@ -1480,12 +1822,6 @@ static inline void qlcnic_enable_int(struct qlcnic_host_sds_ring *sds_ring) | |||
1480 | extern const struct ethtool_ops qlcnic_ethtool_ops; | 1822 | extern const struct ethtool_ops qlcnic_ethtool_ops; |
1481 | extern const struct ethtool_ops qlcnic_ethtool_failed_ops; | 1823 | extern const struct ethtool_ops qlcnic_ethtool_failed_ops; |
1482 | 1824 | ||
1483 | struct qlcnic_nic_template { | ||
1484 | int (*config_bridged_mode) (struct qlcnic_adapter *, u32); | ||
1485 | int (*config_led) (struct qlcnic_adapter *, u32, u32); | ||
1486 | int (*start_firmware) (struct qlcnic_adapter *); | ||
1487 | }; | ||
1488 | |||
1489 | #define QLCDB(adapter, lvl, _fmt, _args...) do { \ | 1825 | #define QLCDB(adapter, lvl, _fmt, _args...) do { \ |
1490 | if (NETIF_MSG_##lvl & adapter->ahw->msg_enable) \ | 1826 | if (NETIF_MSG_##lvl & adapter->ahw->msg_enable) \ |
1491 | printk(KERN_INFO "%s: %s: " _fmt, \ | 1827 | printk(KERN_INFO "%s: %s: " _fmt, \ |
@@ -1493,6 +1829,7 @@ struct qlcnic_nic_template { | |||
1493 | __func__, ##_args); \ | 1829 | __func__, ##_args); \ |
1494 | } while (0) | 1830 | } while (0) |
1495 | 1831 | ||
1832 | #define PCI_DEVICE_ID_QLOGIC_QLE834X 0x8030 | ||
1496 | #define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020 | 1833 | #define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020 |
1497 | static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter) | 1834 | static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter) |
1498 | { | 1835 | { |
@@ -1500,4 +1837,11 @@ static inline bool qlcnic_82xx_check(struct qlcnic_adapter *adapter) | |||
1500 | return (device == PCI_DEVICE_ID_QLOGIC_QLE824X) ? true : false; | 1837 | return (device == PCI_DEVICE_ID_QLOGIC_QLE824X) ? true : false; |
1501 | } | 1838 | } |
1502 | 1839 | ||
1840 | static inline bool qlcnic_83xx_check(struct qlcnic_adapter *adapter) | ||
1841 | { | ||
1842 | unsigned short device = adapter->pdev->device; | ||
1843 | return (device == PCI_DEVICE_ID_QLOGIC_QLE834X) ? true : false; | ||
1844 | } | ||
1845 | |||
1846 | |||
1503 | #endif /* __QLCNIC_H_ */ | 1847 | #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..cd5ae8813cb3 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c | |||
@@ -0,0 +1,3011 @@ | |||
1 | /* | ||
2 | * QLogic qlcnic NIC Driver | ||
3 | * Copyright (c) 2009-2013 QLogic Corporation | ||
4 | * | ||
5 | * See LICENSE.qlcnic for copyright and licensing details. | ||
6 | */ | ||
7 | |||
8 | #include "qlcnic.h" | ||
9 | #include <linux/if_vlan.h> | ||
10 | #include <linux/ipv6.h> | ||
11 | #include <linux/ethtool.h> | ||
12 | #include <linux/interrupt.h> | ||
13 | |||
14 | #define QLCNIC_MAX_TX_QUEUES 1 | ||
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 | .add_sysfs = qlcnic_83xx_add_sysfs, | ||
246 | .remove_sysfs = qlcnic_83xx_remove_sysfs, | ||
247 | .process_lb_rcv_ring_diag = qlcnic_83xx_process_rcv_ring_diag, | ||
248 | .create_rx_ctx = qlcnic_83xx_create_rx_ctx, | ||
249 | .create_tx_ctx = qlcnic_83xx_create_tx_ctx, | ||
250 | .setup_link_event = qlcnic_83xx_setup_link_event, | ||
251 | .get_nic_info = qlcnic_83xx_get_nic_info, | ||
252 | .get_pci_info = qlcnic_83xx_get_pci_info, | ||
253 | .set_nic_info = qlcnic_83xx_set_nic_info, | ||
254 | .change_macvlan = qlcnic_83xx_sre_macaddr_change, | ||
255 | .napi_enable = qlcnic_83xx_napi_enable, | ||
256 | .napi_disable = qlcnic_83xx_napi_disable, | ||
257 | .config_intr_coal = qlcnic_83xx_config_intr_coal, | ||
258 | .config_rss = qlcnic_83xx_config_rss, | ||
259 | .config_hw_lro = qlcnic_83xx_config_hw_lro, | ||
260 | .config_promisc_mode = qlcnic_83xx_nic_set_promisc, | ||
261 | .change_l2_filter = qlcnic_83xx_change_l2_filter, | ||
262 | .get_board_info = qlcnic_83xx_get_port_info, | ||
263 | }; | ||
264 | |||
265 | static struct qlcnic_nic_template qlcnic_83xx_ops = { | ||
266 | .config_bridged_mode = qlcnic_config_bridged_mode, | ||
267 | .config_led = qlcnic_config_led, | ||
268 | .request_reset = qlcnic_83xx_idc_request_reset, | ||
269 | .cancel_idc_work = qlcnic_83xx_idc_exit, | ||
270 | .napi_add = qlcnic_83xx_napi_add, | ||
271 | .napi_del = qlcnic_83xx_napi_del, | ||
272 | .config_ipaddr = qlcnic_83xx_config_ipaddr, | ||
273 | .clear_legacy_intr = qlcnic_83xx_clear_legacy_intr, | ||
274 | }; | ||
275 | |||
276 | void qlcnic_83xx_register_map(struct qlcnic_hardware_context *ahw) | ||
277 | { | ||
278 | ahw->hw_ops = &qlcnic_83xx_hw_ops; | ||
279 | ahw->reg_tbl = (u32 *)qlcnic_83xx_reg_tbl; | ||
280 | ahw->ext_reg_tbl = (u32 *)qlcnic_83xx_ext_reg_tbl; | ||
281 | } | ||
282 | |||
283 | int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *adapter) | ||
284 | { | ||
285 | u32 fw_major, fw_minor, fw_build; | ||
286 | struct pci_dev *pdev = adapter->pdev; | ||
287 | |||
288 | fw_major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR); | ||
289 | fw_minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR); | ||
290 | fw_build = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB); | ||
291 | adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build); | ||
292 | |||
293 | dev_info(&pdev->dev, "Driver v%s, firmware version %d.%d.%d\n", | ||
294 | QLCNIC_LINUX_VERSIONID, fw_major, fw_minor, fw_build); | ||
295 | |||
296 | return adapter->fw_version; | ||
297 | } | ||
298 | |||
299 | static int __qlcnic_set_win_base(struct qlcnic_adapter *adapter, u32 addr) | ||
300 | { | ||
301 | void __iomem *base; | ||
302 | u32 val; | ||
303 | |||
304 | base = adapter->ahw->pci_base0 + | ||
305 | QLC_83XX_CRB_WIN_FUNC(adapter->ahw->pci_func); | ||
306 | writel(addr, base); | ||
307 | val = readl(base); | ||
308 | if (val != addr) | ||
309 | return -EIO; | ||
310 | |||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | int qlcnic_83xx_rd_reg_indirect(struct qlcnic_adapter *adapter, ulong addr) | ||
315 | { | ||
316 | int ret; | ||
317 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
318 | |||
319 | ret = __qlcnic_set_win_base(adapter, (u32) addr); | ||
320 | if (!ret) { | ||
321 | return QLCRDX(ahw, QLCNIC_WILDCARD); | ||
322 | } else { | ||
323 | dev_err(&adapter->pdev->dev, | ||
324 | "%s failed, addr = 0x%x\n", __func__, (int)addr); | ||
325 | return -EIO; | ||
326 | } | ||
327 | } | ||
328 | |||
329 | int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *adapter, ulong addr, | ||
330 | u32 data) | ||
331 | { | ||
332 | int err; | ||
333 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
334 | |||
335 | err = __qlcnic_set_win_base(adapter, (u32) addr); | ||
336 | if (!err) { | ||
337 | QLCWRX(ahw, QLCNIC_WILDCARD, data); | ||
338 | return 0; | ||
339 | } else { | ||
340 | dev_err(&adapter->pdev->dev, | ||
341 | "%s failed, addr = 0x%x data = 0x%x\n", | ||
342 | __func__, (int)addr, data); | ||
343 | return err; | ||
344 | } | ||
345 | } | ||
346 | |||
347 | int qlcnic_83xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr) | ||
348 | { | ||
349 | int err, i, num_msix; | ||
350 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
351 | |||
352 | if (!num_intr) | ||
353 | num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS; | ||
354 | num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(), | ||
355 | num_intr)); | ||
356 | /* account for AEN interrupt MSI-X based interrupts */ | ||
357 | num_msix += 1; | ||
358 | num_msix += adapter->max_drv_tx_rings; | ||
359 | err = qlcnic_enable_msix(adapter, num_msix); | ||
360 | if (err == -ENOMEM) | ||
361 | return err; | ||
362 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
363 | num_msix = adapter->ahw->num_msix; | ||
364 | else | ||
365 | num_msix = 1; | ||
366 | /* setup interrupt mapping table for fw */ | ||
367 | ahw->intr_tbl = vzalloc(num_msix * | ||
368 | sizeof(struct qlcnic_intrpt_config)); | ||
369 | if (!ahw->intr_tbl) | ||
370 | return -ENOMEM; | ||
371 | if (!(adapter->flags & QLCNIC_MSIX_ENABLED)) { | ||
372 | /* MSI-X enablement failed, use legacy interrupt */ | ||
373 | adapter->tgt_status_reg = ahw->pci_base0 + QLC_83XX_INTX_PTR; | ||
374 | adapter->tgt_mask_reg = ahw->pci_base0 + QLC_83XX_INTX_MASK; | ||
375 | adapter->isr_int_vec = ahw->pci_base0 + QLC_83XX_INTX_TRGR; | ||
376 | adapter->msix_entries[0].vector = adapter->pdev->irq; | ||
377 | dev_info(&adapter->pdev->dev, "using legacy interrupt\n"); | ||
378 | } | ||
379 | |||
380 | for (i = 0; i < num_msix; i++) { | ||
381 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
382 | ahw->intr_tbl[i].type = QLCNIC_INTRPT_MSIX; | ||
383 | else | ||
384 | ahw->intr_tbl[i].type = QLCNIC_INTRPT_INTX; | ||
385 | ahw->intr_tbl[i].id = i; | ||
386 | ahw->intr_tbl[i].src = 0; | ||
387 | } | ||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | inline void qlcnic_83xx_clear_legacy_intr_mask(struct qlcnic_adapter *adapter) | ||
392 | { | ||
393 | writel(0, adapter->tgt_mask_reg); | ||
394 | } | ||
395 | |||
396 | /* Enable MSI-x and INT-x interrupts */ | ||
397 | void qlcnic_83xx_enable_intr(struct qlcnic_adapter *adapter, | ||
398 | struct qlcnic_host_sds_ring *sds_ring) | ||
399 | { | ||
400 | writel(0, sds_ring->crb_intr_mask); | ||
401 | } | ||
402 | |||
403 | /* Disable MSI-x and INT-x interrupts */ | ||
404 | void qlcnic_83xx_disable_intr(struct qlcnic_adapter *adapter, | ||
405 | struct qlcnic_host_sds_ring *sds_ring) | ||
406 | { | ||
407 | writel(1, sds_ring->crb_intr_mask); | ||
408 | } | ||
409 | |||
410 | inline void qlcnic_83xx_enable_legacy_msix_mbx_intr(struct qlcnic_adapter | ||
411 | *adapter) | ||
412 | { | ||
413 | u32 mask; | ||
414 | |||
415 | /* Mailbox in MSI-x mode and Legacy Interrupt share the same | ||
416 | * source register. We could be here before contexts are created | ||
417 | * and sds_ring->crb_intr_mask has not been initialized, calculate | ||
418 | * BAR offset for Interrupt Source Register | ||
419 | */ | ||
420 | mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK); | ||
421 | writel(0, adapter->ahw->pci_base0 + mask); | ||
422 | } | ||
423 | |||
424 | inline void qlcnic_83xx_disable_mbx_intr(struct qlcnic_adapter *adapter) | ||
425 | { | ||
426 | u32 mask; | ||
427 | |||
428 | mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK); | ||
429 | writel(1, adapter->ahw->pci_base0 + mask); | ||
430 | } | ||
431 | |||
432 | static inline void qlcnic_83xx_get_mbx_data(struct qlcnic_adapter *adapter, | ||
433 | struct qlcnic_cmd_args *cmd) | ||
434 | { | ||
435 | int i; | ||
436 | for (i = 0; i < cmd->rsp.num; i++) | ||
437 | cmd->rsp.arg[i] = readl(QLCNIC_MBX_FW(adapter->ahw, i)); | ||
438 | } | ||
439 | |||
440 | irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *adapter) | ||
441 | { | ||
442 | u32 intr_val; | ||
443 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
444 | int retries = 0; | ||
445 | |||
446 | intr_val = readl(adapter->tgt_status_reg); | ||
447 | |||
448 | if (!QLC_83XX_VALID_INTX_BIT31(intr_val)) | ||
449 | return IRQ_NONE; | ||
450 | |||
451 | if (QLC_83XX_INTX_FUNC(intr_val) != adapter->ahw->pci_func) { | ||
452 | adapter->stats.spurious_intr++; | ||
453 | return IRQ_NONE; | ||
454 | } | ||
455 | /* The barrier is required to ensure writes to the registers */ | ||
456 | wmb(); | ||
457 | |||
458 | /* clear the interrupt trigger control register */ | ||
459 | writel(0, adapter->isr_int_vec); | ||
460 | intr_val = readl(adapter->isr_int_vec); | ||
461 | do { | ||
462 | intr_val = readl(adapter->tgt_status_reg); | ||
463 | if (QLC_83XX_INTX_FUNC(intr_val) != ahw->pci_func) | ||
464 | break; | ||
465 | retries++; | ||
466 | } while (QLC_83XX_VALID_INTX_BIT30(intr_val) && | ||
467 | (retries < QLC_83XX_LEGACY_INTX_MAX_RETRY)); | ||
468 | |||
469 | return IRQ_HANDLED; | ||
470 | } | ||
471 | |||
472 | static void qlcnic_83xx_poll_process_aen(struct qlcnic_adapter *adapter) | ||
473 | { | ||
474 | u32 resp, event; | ||
475 | unsigned long flags; | ||
476 | |||
477 | spin_lock_irqsave(&adapter->ahw->mbx_lock, flags); | ||
478 | |||
479 | resp = QLCRDX(adapter->ahw, QLCNIC_FW_MBX_CTRL); | ||
480 | if (!(resp & QLCNIC_SET_OWNER)) | ||
481 | goto out; | ||
482 | |||
483 | event = readl(QLCNIC_MBX_FW(adapter->ahw, 0)); | ||
484 | if (event & QLCNIC_MBX_ASYNC_EVENT) | ||
485 | qlcnic_83xx_process_aen(adapter); | ||
486 | out: | ||
487 | qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter); | ||
488 | spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags); | ||
489 | } | ||
490 | |||
491 | irqreturn_t qlcnic_83xx_intr(int irq, void *data) | ||
492 | { | ||
493 | struct qlcnic_adapter *adapter = data; | ||
494 | struct qlcnic_host_sds_ring *sds_ring; | ||
495 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
496 | |||
497 | if (qlcnic_83xx_clear_legacy_intr(adapter) == IRQ_NONE) | ||
498 | return IRQ_NONE; | ||
499 | |||
500 | qlcnic_83xx_poll_process_aen(adapter); | ||
501 | |||
502 | if (ahw->diag_test == QLCNIC_INTERRUPT_TEST) { | ||
503 | ahw->diag_cnt++; | ||
504 | qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter); | ||
505 | return IRQ_HANDLED; | ||
506 | } | ||
507 | |||
508 | if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { | ||
509 | qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter); | ||
510 | } else { | ||
511 | sds_ring = &adapter->recv_ctx->sds_rings[0]; | ||
512 | napi_schedule(&sds_ring->napi); | ||
513 | } | ||
514 | |||
515 | return IRQ_HANDLED; | ||
516 | } | ||
517 | |||
518 | irqreturn_t qlcnic_83xx_tmp_intr(int irq, void *data) | ||
519 | { | ||
520 | struct qlcnic_host_sds_ring *sds_ring = data; | ||
521 | struct qlcnic_adapter *adapter = sds_ring->adapter; | ||
522 | |||
523 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
524 | goto done; | ||
525 | |||
526 | if (adapter->nic_ops->clear_legacy_intr(adapter) == IRQ_NONE) | ||
527 | return IRQ_NONE; | ||
528 | |||
529 | done: | ||
530 | adapter->ahw->diag_cnt++; | ||
531 | qlcnic_83xx_enable_intr(adapter, sds_ring); | ||
532 | |||
533 | return IRQ_HANDLED; | ||
534 | } | ||
535 | |||
536 | void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *adapter) | ||
537 | { | ||
538 | u32 val = 0, num_msix = adapter->ahw->num_msix - 1; | ||
539 | |||
540 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
541 | num_msix = adapter->ahw->num_msix - 1; | ||
542 | else | ||
543 | num_msix = 0; | ||
544 | |||
545 | QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, val); | ||
546 | |||
547 | qlcnic_83xx_disable_mbx_intr(adapter); | ||
548 | |||
549 | msleep(20); | ||
550 | synchronize_irq(adapter->msix_entries[num_msix].vector); | ||
551 | free_irq(adapter->msix_entries[num_msix].vector, adapter); | ||
552 | } | ||
553 | |||
554 | int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter) | ||
555 | { | ||
556 | irq_handler_t handler; | ||
557 | u32 val; | ||
558 | char name[32]; | ||
559 | int err = 0; | ||
560 | unsigned long flags = 0; | ||
561 | |||
562 | if (!(adapter->flags & QLCNIC_MSI_ENABLED) && | ||
563 | !(adapter->flags & QLCNIC_MSIX_ENABLED)) | ||
564 | flags |= IRQF_SHARED; | ||
565 | |||
566 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { | ||
567 | handler = qlcnic_83xx_handle_aen; | ||
568 | val = adapter->msix_entries[adapter->ahw->num_msix - 1].vector; | ||
569 | snprintf(name, (IFNAMSIZ + 4), | ||
570 | "%s[%s]", "qlcnic", "aen"); | ||
571 | err = request_irq(val, handler, flags, name, adapter); | ||
572 | if (err) { | ||
573 | dev_err(&adapter->pdev->dev, | ||
574 | "failed to register MBX interrupt\n"); | ||
575 | return err; | ||
576 | } | ||
577 | } else { | ||
578 | handler = qlcnic_83xx_intr; | ||
579 | val = adapter->msix_entries[0].vector; | ||
580 | err = request_irq(val, handler, flags, "qlcnic", adapter); | ||
581 | if (err) { | ||
582 | dev_err(&adapter->pdev->dev, | ||
583 | "failed to register INTx interrupt\n"); | ||
584 | return err; | ||
585 | } | ||
586 | qlcnic_83xx_clear_legacy_intr_mask(adapter); | ||
587 | } | ||
588 | |||
589 | /* Enable mailbox interrupt */ | ||
590 | qlcnic_83xx_enable_mbx_intrpt(adapter); | ||
591 | |||
592 | return err; | ||
593 | } | ||
594 | |||
595 | void qlcnic_83xx_get_func_no(struct qlcnic_adapter *adapter) | ||
596 | { | ||
597 | u32 val = QLCRDX(adapter->ahw, QLCNIC_INFORMANT); | ||
598 | adapter->ahw->pci_func = val & 0xf; | ||
599 | } | ||
600 | |||
601 | int qlcnic_83xx_cam_lock(struct qlcnic_adapter *adapter) | ||
602 | { | ||
603 | void __iomem *addr; | ||
604 | u32 val, limit = 0; | ||
605 | |||
606 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
607 | |||
608 | addr = ahw->pci_base0 + QLC_83XX_SEM_LOCK_FUNC(ahw->pci_func); | ||
609 | do { | ||
610 | val = readl(addr); | ||
611 | if (val) { | ||
612 | /* write the function number to register */ | ||
613 | QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER, | ||
614 | ahw->pci_func); | ||
615 | return 0; | ||
616 | } | ||
617 | usleep_range(1000, 2000); | ||
618 | } while (++limit <= QLCNIC_PCIE_SEM_TIMEOUT); | ||
619 | |||
620 | return -EIO; | ||
621 | } | ||
622 | |||
623 | void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *adapter) | ||
624 | { | ||
625 | void __iomem *addr; | ||
626 | u32 val; | ||
627 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
628 | |||
629 | addr = ahw->pci_base0 + QLC_83XX_SEM_UNLOCK_FUNC(ahw->pci_func); | ||
630 | val = readl(addr); | ||
631 | } | ||
632 | |||
633 | void qlcnic_83xx_read_crb(struct qlcnic_adapter *adapter, char *buf, | ||
634 | loff_t offset, size_t size) | ||
635 | { | ||
636 | int ret; | ||
637 | u32 data; | ||
638 | |||
639 | if (qlcnic_api_lock(adapter)) { | ||
640 | dev_err(&adapter->pdev->dev, | ||
641 | "%s: failed to acquire lock. addr offset 0x%x\n", | ||
642 | __func__, (u32)offset); | ||
643 | return; | ||
644 | } | ||
645 | |||
646 | ret = qlcnic_83xx_rd_reg_indirect(adapter, (u32) offset); | ||
647 | qlcnic_api_unlock(adapter); | ||
648 | |||
649 | if (ret == -EIO) { | ||
650 | dev_err(&adapter->pdev->dev, | ||
651 | "%s: failed. addr offset 0x%x\n", | ||
652 | __func__, (u32)offset); | ||
653 | return; | ||
654 | } | ||
655 | data = ret; | ||
656 | memcpy(buf, &data, size); | ||
657 | } | ||
658 | |||
659 | void qlcnic_83xx_write_crb(struct qlcnic_adapter *adapter, char *buf, | ||
660 | loff_t offset, size_t size) | ||
661 | { | ||
662 | u32 data; | ||
663 | |||
664 | memcpy(&data, buf, size); | ||
665 | qlcnic_83xx_wrt_reg_indirect(adapter, (u32) offset, data); | ||
666 | } | ||
667 | |||
668 | int qlcnic_83xx_get_port_info(struct qlcnic_adapter *adapter) | ||
669 | { | ||
670 | int status; | ||
671 | |||
672 | status = qlcnic_83xx_get_port_config(adapter); | ||
673 | if (status) { | ||
674 | dev_err(&adapter->pdev->dev, | ||
675 | "Get Port Info failed\n"); | ||
676 | } else { | ||
677 | if (QLC_83XX_SFP_10G_CAPABLE(adapter->ahw->port_config)) | ||
678 | adapter->ahw->port_type = QLCNIC_XGBE; | ||
679 | else | ||
680 | adapter->ahw->port_type = QLCNIC_GBE; | ||
681 | |||
682 | if (QLC_83XX_AUTONEG(adapter->ahw->port_config)) | ||
683 | adapter->ahw->link_autoneg = AUTONEG_ENABLE; | ||
684 | } | ||
685 | return status; | ||
686 | } | ||
687 | |||
688 | void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *adapter) | ||
689 | { | ||
690 | u32 val; | ||
691 | |||
692 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
693 | val = BIT_2 | ((adapter->ahw->num_msix - 1) << 8); | ||
694 | else | ||
695 | val = BIT_2; | ||
696 | |||
697 | QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, val); | ||
698 | qlcnic_83xx_enable_legacy_msix_mbx_intr(adapter); | ||
699 | } | ||
700 | |||
701 | void qlcnic_83xx_check_vf(struct qlcnic_adapter *adapter, | ||
702 | const struct pci_device_id *ent) | ||
703 | { | ||
704 | u32 op_mode, priv_level; | ||
705 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
706 | |||
707 | ahw->fw_hal_version = 2; | ||
708 | qlcnic_get_func_no(adapter); | ||
709 | |||
710 | /* Determine function privilege level */ | ||
711 | op_mode = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE); | ||
712 | if (op_mode == QLC_83XX_DEFAULT_OPMODE) | ||
713 | priv_level = QLCNIC_MGMT_FUNC; | ||
714 | else | ||
715 | priv_level = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode, | ||
716 | ahw->pci_func); | ||
717 | |||
718 | if (priv_level == QLCNIC_NON_PRIV_FUNC) { | ||
719 | ahw->op_mode = QLCNIC_NON_PRIV_FUNC; | ||
720 | dev_info(&adapter->pdev->dev, | ||
721 | "HAL Version: %d Non Privileged function\n", | ||
722 | ahw->fw_hal_version); | ||
723 | adapter->nic_ops = &qlcnic_vf_ops; | ||
724 | } else { | ||
725 | adapter->nic_ops = &qlcnic_83xx_ops; | ||
726 | } | ||
727 | } | ||
728 | |||
729 | static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter, | ||
730 | u32 data[]); | ||
731 | static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter, | ||
732 | u32 data[]); | ||
733 | |||
734 | static void qlcnic_dump_mbx(struct qlcnic_adapter *adapter, | ||
735 | struct qlcnic_cmd_args *cmd) | ||
736 | { | ||
737 | int i; | ||
738 | |||
739 | dev_info(&adapter->pdev->dev, | ||
740 | "Host MBX regs(%d)\n", cmd->req.num); | ||
741 | for (i = 0; i < cmd->req.num; i++) { | ||
742 | if (i && !(i % 8)) | ||
743 | pr_info("\n"); | ||
744 | pr_info("%08x ", cmd->req.arg[i]); | ||
745 | } | ||
746 | pr_info("\n"); | ||
747 | dev_info(&adapter->pdev->dev, | ||
748 | "FW MBX regs(%d)\n", cmd->rsp.num); | ||
749 | for (i = 0; i < cmd->rsp.num; i++) { | ||
750 | if (i && !(i % 8)) | ||
751 | pr_info("\n"); | ||
752 | pr_info("%08x ", cmd->rsp.arg[i]); | ||
753 | } | ||
754 | pr_info("\n"); | ||
755 | } | ||
756 | |||
757 | /* Mailbox response for mac rcode */ | ||
758 | static u32 qlcnic_83xx_mac_rcode(struct qlcnic_adapter *adapter) | ||
759 | { | ||
760 | u32 fw_data; | ||
761 | u8 mac_cmd_rcode; | ||
762 | |||
763 | fw_data = readl(QLCNIC_MBX_FW(adapter->ahw, 2)); | ||
764 | mac_cmd_rcode = (u8)fw_data; | ||
765 | if (mac_cmd_rcode == QLC_83XX_NO_NIC_RESOURCE || | ||
766 | mac_cmd_rcode == QLC_83XX_MAC_PRESENT || | ||
767 | mac_cmd_rcode == QLC_83XX_MAC_ABSENT) | ||
768 | return QLCNIC_RCODE_SUCCESS; | ||
769 | return 1; | ||
770 | } | ||
771 | |||
772 | static u32 qlcnic_83xx_mbx_poll(struct qlcnic_adapter *adapter) | ||
773 | { | ||
774 | u32 data; | ||
775 | unsigned long wait_time = 0; | ||
776 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
777 | /* wait for mailbox completion */ | ||
778 | do { | ||
779 | data = QLCRDX(ahw, QLCNIC_FW_MBX_CTRL); | ||
780 | if (++wait_time > QLCNIC_MBX_TIMEOUT) { | ||
781 | data = QLCNIC_RCODE_TIMEOUT; | ||
782 | break; | ||
783 | } | ||
784 | mdelay(1); | ||
785 | } while (!data); | ||
786 | return data; | ||
787 | } | ||
788 | |||
789 | int qlcnic_83xx_mbx_op(struct qlcnic_adapter *adapter, | ||
790 | struct qlcnic_cmd_args *cmd) | ||
791 | { | ||
792 | int i; | ||
793 | u16 opcode; | ||
794 | u8 mbx_err_code; | ||
795 | unsigned long flags; | ||
796 | u32 rsp, mbx_val, fw_data, rsp_num, mbx_cmd; | ||
797 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
798 | |||
799 | opcode = LSW(cmd->req.arg[0]); | ||
800 | if (!test_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status)) { | ||
801 | dev_info(&adapter->pdev->dev, | ||
802 | "Mailbox cmd attempted, 0x%x\n", opcode); | ||
803 | dev_info(&adapter->pdev->dev, "Mailbox detached\n"); | ||
804 | return 0; | ||
805 | } | ||
806 | |||
807 | spin_lock_irqsave(&adapter->ahw->mbx_lock, flags); | ||
808 | mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL); | ||
809 | |||
810 | if (mbx_val) { | ||
811 | QLCDB(adapter, DRV, | ||
812 | "Mailbox cmd attempted, 0x%x\n", opcode); | ||
813 | QLCDB(adapter, DRV, | ||
814 | "Mailbox not available, 0x%x, collect FW dump\n", | ||
815 | mbx_val); | ||
816 | cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT; | ||
817 | spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags); | ||
818 | return cmd->rsp.arg[0]; | ||
819 | } | ||
820 | |||
821 | /* Fill in mailbox registers */ | ||
822 | mbx_cmd = cmd->req.arg[0]; | ||
823 | writel(mbx_cmd, QLCNIC_MBX_HOST(ahw, 0)); | ||
824 | for (i = 1; i < cmd->req.num; i++) | ||
825 | writel(cmd->req.arg[i], QLCNIC_MBX_HOST(ahw, i)); | ||
826 | |||
827 | /* Signal FW about the impending command */ | ||
828 | QLCWRX(ahw, QLCNIC_HOST_MBX_CTRL, QLCNIC_SET_OWNER); | ||
829 | poll: | ||
830 | rsp = qlcnic_83xx_mbx_poll(adapter); | ||
831 | if (rsp != QLCNIC_RCODE_TIMEOUT) { | ||
832 | /* Get the FW response data */ | ||
833 | fw_data = readl(QLCNIC_MBX_FW(ahw, 0)); | ||
834 | if (fw_data & QLCNIC_MBX_ASYNC_EVENT) { | ||
835 | qlcnic_83xx_process_aen(adapter); | ||
836 | mbx_val = QLCRDX(ahw, QLCNIC_HOST_MBX_CTRL); | ||
837 | if (mbx_val) | ||
838 | goto poll; | ||
839 | } | ||
840 | mbx_err_code = QLCNIC_MBX_STATUS(fw_data); | ||
841 | rsp_num = QLCNIC_MBX_NUM_REGS(fw_data); | ||
842 | opcode = QLCNIC_MBX_RSP(fw_data); | ||
843 | qlcnic_83xx_get_mbx_data(adapter, cmd); | ||
844 | |||
845 | switch (mbx_err_code) { | ||
846 | case QLCNIC_MBX_RSP_OK: | ||
847 | case QLCNIC_MBX_PORT_RSP_OK: | ||
848 | rsp = QLCNIC_RCODE_SUCCESS; | ||
849 | break; | ||
850 | default: | ||
851 | if (opcode == QLCNIC_CMD_CONFIG_MAC_VLAN) { | ||
852 | rsp = qlcnic_83xx_mac_rcode(adapter); | ||
853 | if (!rsp) | ||
854 | goto out; | ||
855 | } | ||
856 | dev_err(&adapter->pdev->dev, | ||
857 | "MBX command 0x%x failed with err:0x%x\n", | ||
858 | opcode, mbx_err_code); | ||
859 | rsp = mbx_err_code; | ||
860 | qlcnic_dump_mbx(adapter, cmd); | ||
861 | break; | ||
862 | } | ||
863 | goto out; | ||
864 | } | ||
865 | |||
866 | dev_err(&adapter->pdev->dev, "MBX command 0x%x timed out\n", | ||
867 | QLCNIC_MBX_RSP(mbx_cmd)); | ||
868 | rsp = QLCNIC_RCODE_TIMEOUT; | ||
869 | out: | ||
870 | /* clear fw mbx control register */ | ||
871 | QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER); | ||
872 | spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags); | ||
873 | return rsp; | ||
874 | } | ||
875 | |||
876 | int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx, | ||
877 | struct qlcnic_adapter *adapter, u32 type) | ||
878 | { | ||
879 | int i, size; | ||
880 | u32 temp; | ||
881 | const struct qlcnic_mailbox_metadata *mbx_tbl; | ||
882 | |||
883 | mbx_tbl = qlcnic_83xx_mbx_tbl; | ||
884 | size = ARRAY_SIZE(qlcnic_83xx_mbx_tbl); | ||
885 | for (i = 0; i < size; i++) { | ||
886 | if (type == mbx_tbl[i].cmd) { | ||
887 | mbx->req.num = mbx_tbl[i].in_args; | ||
888 | mbx->rsp.num = mbx_tbl[i].out_args; | ||
889 | mbx->req.arg = kcalloc(mbx->req.num, sizeof(u32), | ||
890 | GFP_ATOMIC); | ||
891 | if (!mbx->req.arg) | ||
892 | return -ENOMEM; | ||
893 | mbx->rsp.arg = kcalloc(mbx->rsp.num, sizeof(u32), | ||
894 | GFP_ATOMIC); | ||
895 | if (!mbx->rsp.arg) { | ||
896 | kfree(mbx->req.arg); | ||
897 | mbx->req.arg = NULL; | ||
898 | return -ENOMEM; | ||
899 | } | ||
900 | memset(mbx->req.arg, 0, sizeof(u32) * mbx->req.num); | ||
901 | memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num); | ||
902 | temp = adapter->ahw->fw_hal_version << 29; | ||
903 | mbx->req.arg[0] = (type | (mbx->req.num << 16) | temp); | ||
904 | break; | ||
905 | } | ||
906 | } | ||
907 | return 0; | ||
908 | } | ||
909 | |||
910 | void qlcnic_83xx_idc_aen_work(struct work_struct *work) | ||
911 | { | ||
912 | struct qlcnic_adapter *adapter; | ||
913 | struct qlcnic_cmd_args cmd; | ||
914 | int i, err = 0; | ||
915 | |||
916 | adapter = container_of(work, struct qlcnic_adapter, idc_aen_work.work); | ||
917 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_IDC_ACK); | ||
918 | |||
919 | for (i = 1; i < QLC_83XX_MBX_AEN_CNT; i++) | ||
920 | cmd.req.arg[i] = adapter->ahw->mbox_aen[i]; | ||
921 | |||
922 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
923 | if (err) | ||
924 | dev_info(&adapter->pdev->dev, | ||
925 | "%s: Mailbox IDC ACK failed.\n", __func__); | ||
926 | qlcnic_free_mbx_args(&cmd); | ||
927 | } | ||
928 | |||
929 | static void qlcnic_83xx_handle_idc_comp_aen(struct qlcnic_adapter *adapter, | ||
930 | u32 data[]) | ||
931 | { | ||
932 | dev_dbg(&adapter->pdev->dev, "Completion AEN:0x%x.\n", | ||
933 | QLCNIC_MBX_RSP(data[0])); | ||
934 | clear_bit(QLC_83XX_IDC_COMP_AEN, &adapter->ahw->idc.status); | ||
935 | return; | ||
936 | } | ||
937 | |||
938 | void qlcnic_83xx_process_aen(struct qlcnic_adapter *adapter) | ||
939 | { | ||
940 | u32 event[QLC_83XX_MBX_AEN_CNT]; | ||
941 | int i; | ||
942 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
943 | |||
944 | for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++) | ||
945 | event[i] = readl(QLCNIC_MBX_FW(ahw, i)); | ||
946 | |||
947 | switch (QLCNIC_MBX_RSP(event[0])) { | ||
948 | |||
949 | case QLCNIC_MBX_LINK_EVENT: | ||
950 | qlcnic_83xx_handle_link_aen(adapter, event); | ||
951 | break; | ||
952 | case QLCNIC_MBX_COMP_EVENT: | ||
953 | qlcnic_83xx_handle_idc_comp_aen(adapter, event); | ||
954 | break; | ||
955 | case QLCNIC_MBX_REQUEST_EVENT: | ||
956 | for (i = 0; i < QLC_83XX_MBX_AEN_CNT; i++) | ||
957 | adapter->ahw->mbox_aen[i] = QLCNIC_MBX_RSP(event[i]); | ||
958 | queue_delayed_work(adapter->qlcnic_wq, | ||
959 | &adapter->idc_aen_work, 0); | ||
960 | break; | ||
961 | case QLCNIC_MBX_TIME_EXTEND_EVENT: | ||
962 | break; | ||
963 | case QLCNIC_MBX_SFP_INSERT_EVENT: | ||
964 | dev_info(&adapter->pdev->dev, "SFP+ Insert AEN:0x%x.\n", | ||
965 | QLCNIC_MBX_RSP(event[0])); | ||
966 | break; | ||
967 | case QLCNIC_MBX_SFP_REMOVE_EVENT: | ||
968 | dev_info(&adapter->pdev->dev, "SFP Removed AEN:0x%x.\n", | ||
969 | QLCNIC_MBX_RSP(event[0])); | ||
970 | break; | ||
971 | default: | ||
972 | dev_dbg(&adapter->pdev->dev, "Unsupported AEN:0x%x.\n", | ||
973 | QLCNIC_MBX_RSP(event[0])); | ||
974 | break; | ||
975 | } | ||
976 | |||
977 | QLCWRX(ahw, QLCNIC_FW_MBX_CTRL, QLCNIC_CLR_OWNER); | ||
978 | } | ||
979 | |||
980 | static int qlcnic_83xx_add_rings(struct qlcnic_adapter *adapter) | ||
981 | { | ||
982 | int index, i, err, sds_mbx_size; | ||
983 | u32 *buf, intrpt_id, intr_mask; | ||
984 | u16 context_id; | ||
985 | u8 num_sds; | ||
986 | struct qlcnic_cmd_args cmd; | ||
987 | struct qlcnic_host_sds_ring *sds; | ||
988 | struct qlcnic_sds_mbx sds_mbx; | ||
989 | struct qlcnic_add_rings_mbx_out *mbx_out; | ||
990 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
991 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
992 | |||
993 | sds_mbx_size = sizeof(struct qlcnic_sds_mbx); | ||
994 | context_id = recv_ctx->context_id; | ||
995 | num_sds = (adapter->max_sds_rings - QLCNIC_MAX_RING_SETS); | ||
996 | ahw->hw_ops->alloc_mbx_args(&cmd, adapter, | ||
997 | QLCNIC_CMD_ADD_RCV_RINGS); | ||
998 | cmd.req.arg[1] = 0 | (num_sds << 8) | (context_id << 16); | ||
999 | |||
1000 | /* set up status rings, mbx 2-81 */ | ||
1001 | index = 2; | ||
1002 | for (i = 8; i < adapter->max_sds_rings; i++) { | ||
1003 | memset(&sds_mbx, 0, sds_mbx_size); | ||
1004 | sds = &recv_ctx->sds_rings[i]; | ||
1005 | sds->consumer = 0; | ||
1006 | memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds)); | ||
1007 | sds_mbx.phy_addr = sds->phys_addr; | ||
1008 | sds_mbx.sds_ring_size = sds->num_desc; | ||
1009 | |||
1010 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
1011 | intrpt_id = ahw->intr_tbl[i].id; | ||
1012 | else | ||
1013 | intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID); | ||
1014 | |||
1015 | if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) | ||
1016 | sds_mbx.intrpt_id = intrpt_id; | ||
1017 | else | ||
1018 | sds_mbx.intrpt_id = 0xffff; | ||
1019 | sds_mbx.intrpt_val = 0; | ||
1020 | buf = &cmd.req.arg[index]; | ||
1021 | memcpy(buf, &sds_mbx, sds_mbx_size); | ||
1022 | index += sds_mbx_size / sizeof(u32); | ||
1023 | } | ||
1024 | |||
1025 | /* send the mailbox command */ | ||
1026 | err = ahw->hw_ops->mbx_cmd(adapter, &cmd); | ||
1027 | if (err) { | ||
1028 | dev_err(&adapter->pdev->dev, | ||
1029 | "Failed to add rings %d\n", err); | ||
1030 | goto out; | ||
1031 | } | ||
1032 | |||
1033 | mbx_out = (struct qlcnic_add_rings_mbx_out *)&cmd.rsp.arg[1]; | ||
1034 | index = 0; | ||
1035 | /* status descriptor ring */ | ||
1036 | for (i = 8; i < adapter->max_sds_rings; i++) { | ||
1037 | sds = &recv_ctx->sds_rings[i]; | ||
1038 | sds->crb_sts_consumer = ahw->pci_base0 + | ||
1039 | mbx_out->host_csmr[index]; | ||
1040 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
1041 | intr_mask = ahw->intr_tbl[i].src; | ||
1042 | else | ||
1043 | intr_mask = QLCRDX(ahw, QLCNIC_DEF_INT_MASK); | ||
1044 | |||
1045 | sds->crb_intr_mask = ahw->pci_base0 + intr_mask; | ||
1046 | index++; | ||
1047 | } | ||
1048 | out: | ||
1049 | qlcnic_free_mbx_args(&cmd); | ||
1050 | return err; | ||
1051 | } | ||
1052 | |||
1053 | int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *adapter) | ||
1054 | { | ||
1055 | int i, err, index, sds_mbx_size, rds_mbx_size; | ||
1056 | u8 num_sds, num_rds; | ||
1057 | u32 *buf, intrpt_id, intr_mask, cap = 0; | ||
1058 | struct qlcnic_host_sds_ring *sds; | ||
1059 | struct qlcnic_host_rds_ring *rds; | ||
1060 | struct qlcnic_sds_mbx sds_mbx; | ||
1061 | struct qlcnic_rds_mbx rds_mbx; | ||
1062 | struct qlcnic_cmd_args cmd; | ||
1063 | struct qlcnic_rcv_mbx_out *mbx_out; | ||
1064 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
1065 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
1066 | num_rds = adapter->max_rds_rings; | ||
1067 | |||
1068 | if (adapter->max_sds_rings <= QLCNIC_MAX_RING_SETS) | ||
1069 | num_sds = adapter->max_sds_rings; | ||
1070 | else | ||
1071 | num_sds = QLCNIC_MAX_RING_SETS; | ||
1072 | |||
1073 | sds_mbx_size = sizeof(struct qlcnic_sds_mbx); | ||
1074 | rds_mbx_size = sizeof(struct qlcnic_rds_mbx); | ||
1075 | cap = QLCNIC_CAP0_LEGACY_CONTEXT; | ||
1076 | |||
1077 | if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) | ||
1078 | cap |= QLC_83XX_FW_CAP_LRO_MSS; | ||
1079 | |||
1080 | /* set mailbox hdr and capabilities */ | ||
1081 | qlcnic_alloc_mbx_args(&cmd, adapter, | ||
1082 | QLCNIC_CMD_CREATE_RX_CTX); | ||
1083 | cmd.req.arg[1] = cap; | ||
1084 | cmd.req.arg[5] = 1 | (num_rds << 5) | (num_sds << 8) | | ||
1085 | (QLC_83XX_HOST_RDS_MODE_UNIQUE << 16); | ||
1086 | /* set up status rings, mbx 8-57/87 */ | ||
1087 | index = QLC_83XX_HOST_SDS_MBX_IDX; | ||
1088 | for (i = 0; i < num_sds; i++) { | ||
1089 | memset(&sds_mbx, 0, sds_mbx_size); | ||
1090 | sds = &recv_ctx->sds_rings[i]; | ||
1091 | sds->consumer = 0; | ||
1092 | memset(sds->desc_head, 0, STATUS_DESC_RINGSIZE(sds)); | ||
1093 | sds_mbx.phy_addr = sds->phys_addr; | ||
1094 | sds_mbx.sds_ring_size = sds->num_desc; | ||
1095 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
1096 | intrpt_id = ahw->intr_tbl[i].id; | ||
1097 | else | ||
1098 | intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID); | ||
1099 | if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) | ||
1100 | sds_mbx.intrpt_id = intrpt_id; | ||
1101 | else | ||
1102 | sds_mbx.intrpt_id = 0xffff; | ||
1103 | sds_mbx.intrpt_val = 0; | ||
1104 | buf = &cmd.req.arg[index]; | ||
1105 | memcpy(buf, &sds_mbx, sds_mbx_size); | ||
1106 | index += sds_mbx_size / sizeof(u32); | ||
1107 | } | ||
1108 | /* set up receive rings, mbx 88-111/135 */ | ||
1109 | index = QLCNIC_HOST_RDS_MBX_IDX; | ||
1110 | rds = &recv_ctx->rds_rings[0]; | ||
1111 | rds->producer = 0; | ||
1112 | memset(&rds_mbx, 0, rds_mbx_size); | ||
1113 | rds_mbx.phy_addr_reg = rds->phys_addr; | ||
1114 | rds_mbx.reg_ring_sz = rds->dma_size; | ||
1115 | rds_mbx.reg_ring_len = rds->num_desc; | ||
1116 | /* Jumbo ring */ | ||
1117 | rds = &recv_ctx->rds_rings[1]; | ||
1118 | rds->producer = 0; | ||
1119 | rds_mbx.phy_addr_jmb = rds->phys_addr; | ||
1120 | rds_mbx.jmb_ring_sz = rds->dma_size; | ||
1121 | rds_mbx.jmb_ring_len = rds->num_desc; | ||
1122 | buf = &cmd.req.arg[index]; | ||
1123 | memcpy(buf, &rds_mbx, rds_mbx_size); | ||
1124 | |||
1125 | /* send the mailbox command */ | ||
1126 | err = ahw->hw_ops->mbx_cmd(adapter, &cmd); | ||
1127 | if (err) { | ||
1128 | dev_err(&adapter->pdev->dev, | ||
1129 | "Failed to create Rx ctx in firmware%d\n", err); | ||
1130 | goto out; | ||
1131 | } | ||
1132 | mbx_out = (struct qlcnic_rcv_mbx_out *)&cmd.rsp.arg[1]; | ||
1133 | recv_ctx->context_id = mbx_out->ctx_id; | ||
1134 | recv_ctx->state = mbx_out->state; | ||
1135 | recv_ctx->virt_port = mbx_out->vport_id; | ||
1136 | dev_info(&adapter->pdev->dev, "Rx Context[%d] Created, state:0x%x\n", | ||
1137 | recv_ctx->context_id, recv_ctx->state); | ||
1138 | /* Receive descriptor ring */ | ||
1139 | /* Standard ring */ | ||
1140 | rds = &recv_ctx->rds_rings[0]; | ||
1141 | rds->crb_rcv_producer = ahw->pci_base0 + | ||
1142 | mbx_out->host_prod[0].reg_buf; | ||
1143 | /* Jumbo ring */ | ||
1144 | rds = &recv_ctx->rds_rings[1]; | ||
1145 | rds->crb_rcv_producer = ahw->pci_base0 + | ||
1146 | mbx_out->host_prod[0].jmb_buf; | ||
1147 | /* status descriptor ring */ | ||
1148 | for (i = 0; i < num_sds; i++) { | ||
1149 | sds = &recv_ctx->sds_rings[i]; | ||
1150 | sds->crb_sts_consumer = ahw->pci_base0 + | ||
1151 | mbx_out->host_csmr[i]; | ||
1152 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
1153 | intr_mask = ahw->intr_tbl[i].src; | ||
1154 | else | ||
1155 | intr_mask = QLCRDX(ahw, QLCNIC_DEF_INT_MASK); | ||
1156 | sds->crb_intr_mask = ahw->pci_base0 + intr_mask; | ||
1157 | } | ||
1158 | |||
1159 | if (adapter->max_sds_rings > QLCNIC_MAX_RING_SETS) | ||
1160 | err = qlcnic_83xx_add_rings(adapter); | ||
1161 | out: | ||
1162 | qlcnic_free_mbx_args(&cmd); | ||
1163 | return err; | ||
1164 | } | ||
1165 | |||
1166 | int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *adapter, | ||
1167 | struct qlcnic_host_tx_ring *tx, int ring) | ||
1168 | { | ||
1169 | int err; | ||
1170 | u16 msix_id; | ||
1171 | u32 *buf, intr_mask; | ||
1172 | struct qlcnic_cmd_args cmd; | ||
1173 | struct qlcnic_tx_mbx mbx; | ||
1174 | struct qlcnic_tx_mbx_out *mbx_out; | ||
1175 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
1176 | |||
1177 | /* Reset host resources */ | ||
1178 | tx->producer = 0; | ||
1179 | tx->sw_consumer = 0; | ||
1180 | *(tx->hw_consumer) = 0; | ||
1181 | |||
1182 | memset(&mbx, 0, sizeof(struct qlcnic_tx_mbx)); | ||
1183 | |||
1184 | /* setup mailbox inbox registerss */ | ||
1185 | mbx.phys_addr = tx->phys_addr; | ||
1186 | mbx.cnsmr_index = tx->hw_cons_phys_addr; | ||
1187 | mbx.size = tx->num_desc; | ||
1188 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
1189 | msix_id = ahw->intr_tbl[adapter->max_sds_rings + ring].id; | ||
1190 | else | ||
1191 | msix_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID); | ||
1192 | if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) | ||
1193 | mbx.intr_id = msix_id; | ||
1194 | else | ||
1195 | mbx.intr_id = 0xffff; | ||
1196 | mbx.src = 0; | ||
1197 | |||
1198 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX); | ||
1199 | cmd.req.arg[1] = QLCNIC_CAP0_LEGACY_CONTEXT; | ||
1200 | cmd.req.arg[5] = QLCNIC_MAX_TX_QUEUES; | ||
1201 | buf = &cmd.req.arg[6]; | ||
1202 | memcpy(buf, &mbx, sizeof(struct qlcnic_tx_mbx)); | ||
1203 | /* send the mailbox command*/ | ||
1204 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1205 | if (err) { | ||
1206 | dev_err(&adapter->pdev->dev, | ||
1207 | "Failed to create Tx ctx in firmware 0x%x\n", err); | ||
1208 | goto out; | ||
1209 | } | ||
1210 | mbx_out = (struct qlcnic_tx_mbx_out *)&cmd.rsp.arg[2]; | ||
1211 | tx->crb_cmd_producer = ahw->pci_base0 + mbx_out->host_prod; | ||
1212 | tx->ctx_id = mbx_out->ctx_id; | ||
1213 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { | ||
1214 | intr_mask = ahw->intr_tbl[adapter->max_sds_rings + ring].src; | ||
1215 | tx->crb_intr_mask = ahw->pci_base0 + intr_mask; | ||
1216 | } | ||
1217 | dev_info(&adapter->pdev->dev, "Tx Context[0x%x] Created, state:0x%x\n", | ||
1218 | tx->ctx_id, mbx_out->state); | ||
1219 | out: | ||
1220 | qlcnic_free_mbx_args(&cmd); | ||
1221 | return err; | ||
1222 | } | ||
1223 | |||
1224 | static int qlcnic_83xx_diag_alloc_res(struct net_device *netdev, int test) | ||
1225 | { | ||
1226 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
1227 | struct qlcnic_host_sds_ring *sds_ring; | ||
1228 | struct qlcnic_host_rds_ring *rds_ring; | ||
1229 | u8 ring; | ||
1230 | int ret; | ||
1231 | |||
1232 | netif_device_detach(netdev); | ||
1233 | |||
1234 | if (netif_running(netdev)) | ||
1235 | __qlcnic_down(adapter, netdev); | ||
1236 | |||
1237 | qlcnic_detach(adapter); | ||
1238 | |||
1239 | adapter->max_sds_rings = 1; | ||
1240 | adapter->ahw->diag_test = test; | ||
1241 | adapter->ahw->linkup = 0; | ||
1242 | |||
1243 | ret = qlcnic_attach(adapter); | ||
1244 | if (ret) { | ||
1245 | netif_device_attach(netdev); | ||
1246 | return ret; | ||
1247 | } | ||
1248 | |||
1249 | ret = qlcnic_fw_create_ctx(adapter); | ||
1250 | if (ret) { | ||
1251 | qlcnic_detach(adapter); | ||
1252 | netif_device_attach(netdev); | ||
1253 | return ret; | ||
1254 | } | ||
1255 | |||
1256 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | ||
1257 | rds_ring = &adapter->recv_ctx->rds_rings[ring]; | ||
1258 | qlcnic_post_rx_buffers(adapter, rds_ring, ring); | ||
1259 | } | ||
1260 | |||
1261 | if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) { | ||
1262 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | ||
1263 | sds_ring = &adapter->recv_ctx->sds_rings[ring]; | ||
1264 | qlcnic_83xx_enable_intr(adapter, sds_ring); | ||
1265 | } | ||
1266 | } | ||
1267 | |||
1268 | if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) { | ||
1269 | /* disable and free mailbox interrupt */ | ||
1270 | qlcnic_83xx_free_mbx_intr(adapter); | ||
1271 | adapter->ahw->loopback_state = 0; | ||
1272 | adapter->ahw->hw_ops->setup_link_event(adapter, 1); | ||
1273 | } | ||
1274 | |||
1275 | set_bit(__QLCNIC_DEV_UP, &adapter->state); | ||
1276 | return 0; | ||
1277 | } | ||
1278 | |||
1279 | static void qlcnic_83xx_diag_free_res(struct net_device *netdev, | ||
1280 | int max_sds_rings) | ||
1281 | { | ||
1282 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
1283 | struct qlcnic_host_sds_ring *sds_ring; | ||
1284 | int ring, err; | ||
1285 | |||
1286 | clear_bit(__QLCNIC_DEV_UP, &adapter->state); | ||
1287 | if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) { | ||
1288 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | ||
1289 | sds_ring = &adapter->recv_ctx->sds_rings[ring]; | ||
1290 | qlcnic_83xx_disable_intr(adapter, sds_ring); | ||
1291 | } | ||
1292 | } | ||
1293 | |||
1294 | qlcnic_fw_destroy_ctx(adapter); | ||
1295 | qlcnic_detach(adapter); | ||
1296 | |||
1297 | if (adapter->ahw->diag_test == QLCNIC_LOOPBACK_TEST) { | ||
1298 | err = qlcnic_83xx_setup_mbx_intr(adapter); | ||
1299 | if (err) { | ||
1300 | dev_err(&adapter->pdev->dev, | ||
1301 | "%s: failed to setup mbx interrupt\n", | ||
1302 | __func__); | ||
1303 | goto out; | ||
1304 | } | ||
1305 | } | ||
1306 | adapter->ahw->diag_test = 0; | ||
1307 | adapter->max_sds_rings = max_sds_rings; | ||
1308 | |||
1309 | if (qlcnic_attach(adapter)) | ||
1310 | goto out; | ||
1311 | |||
1312 | if (netif_running(netdev)) | ||
1313 | __qlcnic_up(adapter, netdev); | ||
1314 | out: | ||
1315 | netif_device_attach(netdev); | ||
1316 | } | ||
1317 | |||
1318 | int qlcnic_83xx_config_led(struct qlcnic_adapter *adapter, u32 state, | ||
1319 | u32 beacon) | ||
1320 | { | ||
1321 | struct qlcnic_cmd_args cmd; | ||
1322 | u32 mbx_in; | ||
1323 | int i, status = 0; | ||
1324 | |||
1325 | if (state) { | ||
1326 | /* Get LED configuration */ | ||
1327 | qlcnic_alloc_mbx_args(&cmd, adapter, | ||
1328 | QLCNIC_CMD_GET_LED_CONFIG); | ||
1329 | status = qlcnic_issue_cmd(adapter, &cmd); | ||
1330 | if (status) { | ||
1331 | dev_err(&adapter->pdev->dev, | ||
1332 | "Get led config failed.\n"); | ||
1333 | goto mbx_err; | ||
1334 | } else { | ||
1335 | for (i = 0; i < 4; i++) | ||
1336 | adapter->ahw->mbox_reg[i] = cmd.rsp.arg[i+1]; | ||
1337 | } | ||
1338 | qlcnic_free_mbx_args(&cmd); | ||
1339 | /* Set LED Configuration */ | ||
1340 | mbx_in = (LSW(QLC_83XX_LED_CONFIG) << 16) | | ||
1341 | LSW(QLC_83XX_LED_CONFIG); | ||
1342 | qlcnic_alloc_mbx_args(&cmd, adapter, | ||
1343 | QLCNIC_CMD_SET_LED_CONFIG); | ||
1344 | cmd.req.arg[1] = mbx_in; | ||
1345 | cmd.req.arg[2] = mbx_in; | ||
1346 | cmd.req.arg[3] = mbx_in; | ||
1347 | if (beacon) | ||
1348 | cmd.req.arg[4] = QLC_83XX_ENABLE_BEACON; | ||
1349 | status = qlcnic_issue_cmd(adapter, &cmd); | ||
1350 | if (status) { | ||
1351 | dev_err(&adapter->pdev->dev, | ||
1352 | "Set led config failed.\n"); | ||
1353 | } | ||
1354 | mbx_err: | ||
1355 | qlcnic_free_mbx_args(&cmd); | ||
1356 | return status; | ||
1357 | |||
1358 | } else { | ||
1359 | /* Restoring default LED configuration */ | ||
1360 | qlcnic_alloc_mbx_args(&cmd, adapter, | ||
1361 | QLCNIC_CMD_SET_LED_CONFIG); | ||
1362 | cmd.req.arg[1] = adapter->ahw->mbox_reg[0]; | ||
1363 | cmd.req.arg[2] = adapter->ahw->mbox_reg[1]; | ||
1364 | cmd.req.arg[3] = adapter->ahw->mbox_reg[2]; | ||
1365 | if (beacon) | ||
1366 | cmd.req.arg[4] = adapter->ahw->mbox_reg[3]; | ||
1367 | status = qlcnic_issue_cmd(adapter, &cmd); | ||
1368 | if (status) | ||
1369 | dev_err(&adapter->pdev->dev, | ||
1370 | "Restoring led config failed.\n"); | ||
1371 | qlcnic_free_mbx_args(&cmd); | ||
1372 | return status; | ||
1373 | } | ||
1374 | } | ||
1375 | |||
1376 | void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *adapter, | ||
1377 | int enable) | ||
1378 | { | ||
1379 | struct qlcnic_cmd_args cmd; | ||
1380 | int status; | ||
1381 | |||
1382 | if (enable) { | ||
1383 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INIT_NIC_FUNC); | ||
1384 | cmd.req.arg[1] = BIT_0 | BIT_31; | ||
1385 | } else { | ||
1386 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_STOP_NIC_FUNC); | ||
1387 | cmd.req.arg[1] = BIT_0 | BIT_31; | ||
1388 | } | ||
1389 | status = qlcnic_issue_cmd(adapter, &cmd); | ||
1390 | if (status) | ||
1391 | dev_err(&adapter->pdev->dev, | ||
1392 | "Failed to %s in NIC IDC function event.\n", | ||
1393 | (enable ? "register" : "unregister")); | ||
1394 | |||
1395 | qlcnic_free_mbx_args(&cmd); | ||
1396 | } | ||
1397 | |||
1398 | int qlcnic_83xx_set_port_config(struct qlcnic_adapter *adapter) | ||
1399 | { | ||
1400 | struct qlcnic_cmd_args cmd; | ||
1401 | int err; | ||
1402 | |||
1403 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_PORT_CONFIG); | ||
1404 | cmd.req.arg[1] = adapter->ahw->port_config; | ||
1405 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1406 | if (err) | ||
1407 | dev_info(&adapter->pdev->dev, "Set Port Config failed.\n"); | ||
1408 | qlcnic_free_mbx_args(&cmd); | ||
1409 | return err; | ||
1410 | } | ||
1411 | |||
1412 | int qlcnic_83xx_get_port_config(struct qlcnic_adapter *adapter) | ||
1413 | { | ||
1414 | struct qlcnic_cmd_args cmd; | ||
1415 | int err; | ||
1416 | |||
1417 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PORT_CONFIG); | ||
1418 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1419 | if (err) | ||
1420 | dev_info(&adapter->pdev->dev, "Get Port config failed\n"); | ||
1421 | else | ||
1422 | adapter->ahw->port_config = cmd.rsp.arg[1]; | ||
1423 | qlcnic_free_mbx_args(&cmd); | ||
1424 | return err; | ||
1425 | } | ||
1426 | |||
1427 | int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *adapter, int enable) | ||
1428 | { | ||
1429 | int err; | ||
1430 | u32 temp; | ||
1431 | struct qlcnic_cmd_args cmd; | ||
1432 | |||
1433 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_EVENT); | ||
1434 | temp = adapter->recv_ctx->context_id << 16; | ||
1435 | cmd.req.arg[1] = (enable ? 1 : 0) | BIT_8 | temp; | ||
1436 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1437 | if (err) | ||
1438 | dev_info(&adapter->pdev->dev, | ||
1439 | "Setup linkevent mailbox failed\n"); | ||
1440 | qlcnic_free_mbx_args(&cmd); | ||
1441 | return err; | ||
1442 | } | ||
1443 | |||
1444 | int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) | ||
1445 | { | ||
1446 | int err; | ||
1447 | u32 temp; | ||
1448 | struct qlcnic_cmd_args cmd; | ||
1449 | |||
1450 | if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED) | ||
1451 | return -EIO; | ||
1452 | |||
1453 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_MAC_RX_MODE); | ||
1454 | temp = adapter->recv_ctx->context_id << 16; | ||
1455 | cmd.req.arg[1] = (mode ? 1 : 0) | temp; | ||
1456 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1457 | if (err) | ||
1458 | dev_info(&adapter->pdev->dev, | ||
1459 | "Promiscous mode config failed\n"); | ||
1460 | qlcnic_free_mbx_args(&cmd); | ||
1461 | |||
1462 | return err; | ||
1463 | } | ||
1464 | |||
1465 | int qlcnic_83xx_loopback_test(struct net_device *netdev, u8 mode) | ||
1466 | { | ||
1467 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
1468 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
1469 | int ret = 0, loop = 0, max_sds_rings = adapter->max_sds_rings; | ||
1470 | |||
1471 | QLCDB(adapter, DRV, "%s loopback test in progress\n", | ||
1472 | mode == QLCNIC_ILB_MODE ? "internal" : "external"); | ||
1473 | if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { | ||
1474 | dev_warn(&adapter->pdev->dev, | ||
1475 | "Loopback test not supported for non privilege function\n"); | ||
1476 | return ret; | ||
1477 | } | ||
1478 | |||
1479 | if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) | ||
1480 | return -EBUSY; | ||
1481 | |||
1482 | ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_LOOPBACK_TEST); | ||
1483 | if (ret) | ||
1484 | goto fail_diag_alloc; | ||
1485 | |||
1486 | ret = qlcnic_83xx_set_lb_mode(adapter, mode); | ||
1487 | if (ret) | ||
1488 | goto free_diag_res; | ||
1489 | |||
1490 | /* Poll for link up event before running traffic */ | ||
1491 | do { | ||
1492 | msleep(500); | ||
1493 | qlcnic_83xx_process_aen(adapter); | ||
1494 | if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) { | ||
1495 | dev_info(&adapter->pdev->dev, | ||
1496 | "Firmware didn't sent link up event to loopback request\n"); | ||
1497 | ret = -QLCNIC_FW_NOT_RESPOND; | ||
1498 | qlcnic_83xx_clear_lb_mode(adapter, mode); | ||
1499 | goto free_diag_res; | ||
1500 | } | ||
1501 | } while ((adapter->ahw->linkup && ahw->has_link_events) != 1); | ||
1502 | |||
1503 | ret = qlcnic_do_lb_test(adapter, mode); | ||
1504 | |||
1505 | qlcnic_83xx_clear_lb_mode(adapter, mode); | ||
1506 | |||
1507 | free_diag_res: | ||
1508 | qlcnic_83xx_diag_free_res(netdev, max_sds_rings); | ||
1509 | |||
1510 | fail_diag_alloc: | ||
1511 | adapter->max_sds_rings = max_sds_rings; | ||
1512 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
1513 | return ret; | ||
1514 | } | ||
1515 | |||
1516 | int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode) | ||
1517 | { | ||
1518 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
1519 | int status = 0, loop = 0; | ||
1520 | u32 config; | ||
1521 | |||
1522 | status = qlcnic_83xx_get_port_config(adapter); | ||
1523 | if (status) | ||
1524 | return status; | ||
1525 | |||
1526 | config = ahw->port_config; | ||
1527 | set_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); | ||
1528 | |||
1529 | if (mode == QLCNIC_ILB_MODE) | ||
1530 | ahw->port_config |= QLC_83XX_CFG_LOOPBACK_HSS; | ||
1531 | if (mode == QLCNIC_ELB_MODE) | ||
1532 | ahw->port_config |= QLC_83XX_CFG_LOOPBACK_EXT; | ||
1533 | |||
1534 | status = qlcnic_83xx_set_port_config(adapter); | ||
1535 | if (status) { | ||
1536 | dev_err(&adapter->pdev->dev, | ||
1537 | "Failed to Set Loopback Mode = 0x%x.\n", | ||
1538 | ahw->port_config); | ||
1539 | ahw->port_config = config; | ||
1540 | clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); | ||
1541 | return status; | ||
1542 | } | ||
1543 | |||
1544 | /* Wait for Link and IDC Completion AEN */ | ||
1545 | do { | ||
1546 | msleep(300); | ||
1547 | qlcnic_83xx_process_aen(adapter); | ||
1548 | if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) { | ||
1549 | dev_err(&adapter->pdev->dev, | ||
1550 | "FW did not generate IDC completion AEN\n"); | ||
1551 | clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); | ||
1552 | qlcnic_83xx_clear_lb_mode(adapter, mode); | ||
1553 | return -EIO; | ||
1554 | } | ||
1555 | } while (test_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status)); | ||
1556 | |||
1557 | qlcnic_sre_macaddr_change(adapter, adapter->mac_addr, 0, | ||
1558 | QLCNIC_MAC_ADD); | ||
1559 | return status; | ||
1560 | } | ||
1561 | |||
1562 | int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode) | ||
1563 | { | ||
1564 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
1565 | int status = 0, loop = 0; | ||
1566 | u32 config = ahw->port_config; | ||
1567 | |||
1568 | set_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); | ||
1569 | if (mode == QLCNIC_ILB_MODE) | ||
1570 | ahw->port_config &= ~QLC_83XX_CFG_LOOPBACK_HSS; | ||
1571 | if (mode == QLCNIC_ELB_MODE) | ||
1572 | ahw->port_config &= ~QLC_83XX_CFG_LOOPBACK_EXT; | ||
1573 | |||
1574 | status = qlcnic_83xx_set_port_config(adapter); | ||
1575 | if (status) { | ||
1576 | dev_err(&adapter->pdev->dev, | ||
1577 | "Failed to Clear Loopback Mode = 0x%x.\n", | ||
1578 | ahw->port_config); | ||
1579 | ahw->port_config = config; | ||
1580 | clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); | ||
1581 | return status; | ||
1582 | } | ||
1583 | |||
1584 | /* Wait for Link and IDC Completion AEN */ | ||
1585 | do { | ||
1586 | msleep(300); | ||
1587 | qlcnic_83xx_process_aen(adapter); | ||
1588 | if (loop++ > QLCNIC_ILB_MAX_RCV_LOOP) { | ||
1589 | dev_err(&adapter->pdev->dev, | ||
1590 | "Firmware didn't sent IDC completion AEN\n"); | ||
1591 | clear_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status); | ||
1592 | return -EIO; | ||
1593 | } | ||
1594 | } while (test_bit(QLC_83XX_IDC_COMP_AEN, &ahw->idc.status)); | ||
1595 | |||
1596 | qlcnic_sre_macaddr_change(adapter, adapter->mac_addr, 0, | ||
1597 | QLCNIC_MAC_DEL); | ||
1598 | return status; | ||
1599 | } | ||
1600 | |||
1601 | void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, | ||
1602 | int mode) | ||
1603 | { | ||
1604 | int err; | ||
1605 | u32 temp, temp_ip; | ||
1606 | struct qlcnic_cmd_args cmd; | ||
1607 | |||
1608 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_IP_ADDR); | ||
1609 | if (mode == QLCNIC_IP_UP) { | ||
1610 | temp = adapter->recv_ctx->context_id << 16; | ||
1611 | cmd.req.arg[1] = 1 | temp; | ||
1612 | } else { | ||
1613 | temp = adapter->recv_ctx->context_id << 16; | ||
1614 | cmd.req.arg[1] = 2 | temp; | ||
1615 | } | ||
1616 | |||
1617 | /* | ||
1618 | * Adapter needs IP address in network byte order. | ||
1619 | * But hardware mailbox registers go through writel(), hence IP address | ||
1620 | * gets swapped on big endian architecture. | ||
1621 | * To negate swapping of writel() on big endian architecture | ||
1622 | * use swab32(value). | ||
1623 | */ | ||
1624 | |||
1625 | temp_ip = swab32(ntohl(ip)); | ||
1626 | memcpy(&cmd.req.arg[2], &temp_ip, sizeof(u32)); | ||
1627 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1628 | if (err != QLCNIC_RCODE_SUCCESS) | ||
1629 | dev_err(&adapter->netdev->dev, | ||
1630 | "could not notify %s IP 0x%x request\n", | ||
1631 | (mode == QLCNIC_IP_UP) ? "Add" : "Remove", ip); | ||
1632 | qlcnic_free_mbx_args(&cmd); | ||
1633 | } | ||
1634 | |||
1635 | int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *adapter, int mode) | ||
1636 | { | ||
1637 | int err; | ||
1638 | u32 temp, arg1; | ||
1639 | struct qlcnic_cmd_args cmd; | ||
1640 | int lro_bit_mask; | ||
1641 | |||
1642 | lro_bit_mask = (mode ? (BIT_0 | BIT_1 | BIT_2 | BIT_3) : 0); | ||
1643 | |||
1644 | if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED) | ||
1645 | return 0; | ||
1646 | |||
1647 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_HW_LRO); | ||
1648 | temp = adapter->recv_ctx->context_id << 16; | ||
1649 | arg1 = lro_bit_mask | temp; | ||
1650 | cmd.req.arg[1] = arg1; | ||
1651 | |||
1652 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1653 | if (err) | ||
1654 | dev_info(&adapter->pdev->dev, "LRO config failed\n"); | ||
1655 | qlcnic_free_mbx_args(&cmd); | ||
1656 | |||
1657 | return err; | ||
1658 | } | ||
1659 | |||
1660 | int qlcnic_83xx_config_rss(struct qlcnic_adapter *adapter, int enable) | ||
1661 | { | ||
1662 | int err; | ||
1663 | u32 word; | ||
1664 | struct qlcnic_cmd_args cmd; | ||
1665 | const u64 key[] = { 0xbeac01fa6a42b73bULL, 0x8030f20c77cb2da3ULL, | ||
1666 | 0xae7b30b4d0ca2bcbULL, 0x43a38fb04167253dULL, | ||
1667 | 0x255b0ec26d5a56daULL }; | ||
1668 | |||
1669 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_RSS); | ||
1670 | |||
1671 | /* | ||
1672 | * RSS request: | ||
1673 | * bits 3-0: Rsvd | ||
1674 | * 5-4: hash_type_ipv4 | ||
1675 | * 7-6: hash_type_ipv6 | ||
1676 | * 8: enable | ||
1677 | * 9: use indirection table | ||
1678 | * 16-31: indirection table mask | ||
1679 | */ | ||
1680 | word = ((u32)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) | | ||
1681 | ((u32)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) | | ||
1682 | ((u32)(enable & 0x1) << 8) | | ||
1683 | ((0x7ULL) << 16); | ||
1684 | cmd.req.arg[1] = (adapter->recv_ctx->context_id); | ||
1685 | cmd.req.arg[2] = word; | ||
1686 | memcpy(&cmd.req.arg[4], key, sizeof(key)); | ||
1687 | |||
1688 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1689 | |||
1690 | if (err) | ||
1691 | dev_info(&adapter->pdev->dev, "RSS config failed\n"); | ||
1692 | qlcnic_free_mbx_args(&cmd); | ||
1693 | |||
1694 | return err; | ||
1695 | |||
1696 | } | ||
1697 | |||
1698 | int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, | ||
1699 | __le16 vlan_id, u8 op) | ||
1700 | { | ||
1701 | int err; | ||
1702 | u32 *buf; | ||
1703 | struct qlcnic_cmd_args cmd; | ||
1704 | struct qlcnic_macvlan_mbx mv; | ||
1705 | |||
1706 | if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED) | ||
1707 | return -EIO; | ||
1708 | |||
1709 | err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_MAC_VLAN); | ||
1710 | if (err) | ||
1711 | return err; | ||
1712 | cmd.req.arg[1] = op | (1 << 8) | | ||
1713 | (adapter->recv_ctx->context_id << 16); | ||
1714 | |||
1715 | mv.vlan = le16_to_cpu(vlan_id); | ||
1716 | memcpy(&mv.mac, addr, ETH_ALEN); | ||
1717 | buf = &cmd.req.arg[2]; | ||
1718 | memcpy(buf, &mv, sizeof(struct qlcnic_macvlan_mbx)); | ||
1719 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1720 | if (err) | ||
1721 | dev_err(&adapter->pdev->dev, | ||
1722 | "MAC-VLAN %s to CAM failed, err=%d.\n", | ||
1723 | ((op == 1) ? "add " : "delete "), err); | ||
1724 | qlcnic_free_mbx_args(&cmd); | ||
1725 | return err; | ||
1726 | } | ||
1727 | |||
1728 | void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *adapter, u64 *addr, | ||
1729 | __le16 vlan_id) | ||
1730 | { | ||
1731 | u8 mac[ETH_ALEN]; | ||
1732 | memcpy(&mac, addr, ETH_ALEN); | ||
1733 | qlcnic_83xx_sre_macaddr_change(adapter, mac, vlan_id, QLCNIC_MAC_ADD); | ||
1734 | } | ||
1735 | |||
1736 | void qlcnic_83xx_configure_mac(struct qlcnic_adapter *adapter, u8 *mac, | ||
1737 | u8 type, struct qlcnic_cmd_args *cmd) | ||
1738 | { | ||
1739 | switch (type) { | ||
1740 | case QLCNIC_SET_STATION_MAC: | ||
1741 | case QLCNIC_SET_FAC_DEF_MAC: | ||
1742 | memcpy(&cmd->req.arg[2], mac, sizeof(u32)); | ||
1743 | memcpy(&cmd->req.arg[3], &mac[4], sizeof(u16)); | ||
1744 | break; | ||
1745 | } | ||
1746 | cmd->req.arg[1] = type; | ||
1747 | } | ||
1748 | |||
1749 | int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac) | ||
1750 | { | ||
1751 | int err, i; | ||
1752 | struct qlcnic_cmd_args cmd; | ||
1753 | u32 mac_low, mac_high; | ||
1754 | |||
1755 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS); | ||
1756 | qlcnic_83xx_configure_mac(adapter, mac, QLCNIC_GET_CURRENT_MAC, &cmd); | ||
1757 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1758 | |||
1759 | if (err == QLCNIC_RCODE_SUCCESS) { | ||
1760 | mac_low = cmd.rsp.arg[1]; | ||
1761 | mac_high = cmd.rsp.arg[2]; | ||
1762 | |||
1763 | for (i = 0; i < 2; i++) | ||
1764 | mac[i] = (u8) (mac_high >> ((1 - i) * 8)); | ||
1765 | for (i = 2; i < 6; i++) | ||
1766 | mac[i] = (u8) (mac_low >> ((5 - i) * 8)); | ||
1767 | } else { | ||
1768 | dev_err(&adapter->pdev->dev, "Failed to get mac address%d\n", | ||
1769 | err); | ||
1770 | err = -EIO; | ||
1771 | } | ||
1772 | qlcnic_free_mbx_args(&cmd); | ||
1773 | return err; | ||
1774 | } | ||
1775 | |||
1776 | void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *adapter) | ||
1777 | { | ||
1778 | int err; | ||
1779 | u32 temp; | ||
1780 | struct qlcnic_cmd_args cmd; | ||
1781 | struct qlcnic_nic_intr_coalesce *coal = &adapter->ahw->coal; | ||
1782 | |||
1783 | if (adapter->recv_ctx->state == QLCNIC_HOST_CTX_STATE_FREED) | ||
1784 | return; | ||
1785 | |||
1786 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTR_COAL); | ||
1787 | cmd.req.arg[1] = 1 | (adapter->recv_ctx->context_id << 16); | ||
1788 | cmd.req.arg[3] = coal->flag; | ||
1789 | temp = coal->rx_time_us << 16; | ||
1790 | cmd.req.arg[2] = coal->rx_packets | temp; | ||
1791 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1792 | if (err != QLCNIC_RCODE_SUCCESS) | ||
1793 | dev_info(&adapter->pdev->dev, | ||
1794 | "Failed to send interrupt coalescence parameters\n"); | ||
1795 | qlcnic_free_mbx_args(&cmd); | ||
1796 | } | ||
1797 | |||
1798 | static void qlcnic_83xx_handle_link_aen(struct qlcnic_adapter *adapter, | ||
1799 | u32 data[]) | ||
1800 | { | ||
1801 | u8 link_status, duplex; | ||
1802 | /* link speed */ | ||
1803 | link_status = LSB(data[3]) & 1; | ||
1804 | adapter->ahw->link_speed = MSW(data[2]); | ||
1805 | adapter->ahw->link_autoneg = MSB(MSW(data[3])); | ||
1806 | adapter->ahw->module_type = MSB(LSW(data[3])); | ||
1807 | duplex = LSB(MSW(data[3])); | ||
1808 | if (duplex) | ||
1809 | adapter->ahw->link_duplex = DUPLEX_FULL; | ||
1810 | else | ||
1811 | adapter->ahw->link_duplex = DUPLEX_HALF; | ||
1812 | adapter->ahw->has_link_events = 1; | ||
1813 | qlcnic_advert_link_change(adapter, link_status); | ||
1814 | } | ||
1815 | |||
1816 | irqreturn_t qlcnic_83xx_handle_aen(int irq, void *data) | ||
1817 | { | ||
1818 | struct qlcnic_adapter *adapter = data; | ||
1819 | unsigned long flags; | ||
1820 | u32 mask, resp, event; | ||
1821 | |||
1822 | spin_lock_irqsave(&adapter->ahw->mbx_lock, flags); | ||
1823 | resp = QLCRDX(adapter->ahw, QLCNIC_FW_MBX_CTRL); | ||
1824 | if (!(resp & QLCNIC_SET_OWNER)) | ||
1825 | goto out; | ||
1826 | |||
1827 | event = readl(QLCNIC_MBX_FW(adapter->ahw, 0)); | ||
1828 | if (event & QLCNIC_MBX_ASYNC_EVENT) | ||
1829 | qlcnic_83xx_process_aen(adapter); | ||
1830 | out: | ||
1831 | mask = QLCRDX(adapter->ahw, QLCNIC_DEF_INT_MASK); | ||
1832 | writel(0, adapter->ahw->pci_base0 + mask); | ||
1833 | spin_unlock_irqrestore(&adapter->ahw->mbx_lock, flags); | ||
1834 | |||
1835 | return IRQ_HANDLED; | ||
1836 | } | ||
1837 | |||
1838 | int qlcnic_enable_eswitch(struct qlcnic_adapter *adapter, u8 port, u8 enable) | ||
1839 | { | ||
1840 | int err = -EIO; | ||
1841 | struct qlcnic_cmd_args cmd; | ||
1842 | |||
1843 | if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) { | ||
1844 | dev_err(&adapter->pdev->dev, | ||
1845 | "%s: Error, invoked by non management func\n", | ||
1846 | __func__); | ||
1847 | return err; | ||
1848 | } | ||
1849 | |||
1850 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_TOGGLE_ESWITCH); | ||
1851 | cmd.req.arg[1] = (port & 0xf) | BIT_4; | ||
1852 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1853 | |||
1854 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
1855 | dev_err(&adapter->pdev->dev, "Failed to enable eswitch%d\n", | ||
1856 | err); | ||
1857 | err = -EIO; | ||
1858 | } | ||
1859 | qlcnic_free_mbx_args(&cmd); | ||
1860 | |||
1861 | return err; | ||
1862 | |||
1863 | } | ||
1864 | |||
1865 | int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *adapter, | ||
1866 | struct qlcnic_info *nic) | ||
1867 | { | ||
1868 | int i, err = -EIO; | ||
1869 | struct qlcnic_cmd_args cmd; | ||
1870 | |||
1871 | if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) { | ||
1872 | dev_err(&adapter->pdev->dev, | ||
1873 | "%s: Error, invoked by non management func\n", | ||
1874 | __func__); | ||
1875 | return err; | ||
1876 | } | ||
1877 | |||
1878 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO); | ||
1879 | cmd.req.arg[1] = (nic->pci_func << 16); | ||
1880 | cmd.req.arg[2] = 0x1 << 16; | ||
1881 | cmd.req.arg[3] = nic->phys_port | (nic->switch_mode << 16); | ||
1882 | cmd.req.arg[4] = nic->capabilities; | ||
1883 | cmd.req.arg[5] = (nic->max_mac_filters & 0xFF) | ((nic->max_mtu) << 16); | ||
1884 | cmd.req.arg[6] = (nic->max_tx_ques) | ((nic->max_rx_ques) << 16); | ||
1885 | cmd.req.arg[7] = (nic->min_tx_bw) | ((nic->max_tx_bw) << 16); | ||
1886 | for (i = 8; i < 32; i++) | ||
1887 | cmd.req.arg[i] = 0; | ||
1888 | |||
1889 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1890 | |||
1891 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
1892 | dev_err(&adapter->pdev->dev, "Failed to set nic info%d\n", | ||
1893 | err); | ||
1894 | err = -EIO; | ||
1895 | } | ||
1896 | |||
1897 | qlcnic_free_mbx_args(&cmd); | ||
1898 | |||
1899 | return err; | ||
1900 | } | ||
1901 | |||
1902 | int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *adapter, | ||
1903 | struct qlcnic_info *npar_info, u8 func_id) | ||
1904 | { | ||
1905 | int err; | ||
1906 | u32 temp; | ||
1907 | u8 op = 0; | ||
1908 | struct qlcnic_cmd_args cmd; | ||
1909 | |||
1910 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO); | ||
1911 | if (func_id != adapter->ahw->pci_func) { | ||
1912 | temp = func_id << 16; | ||
1913 | cmd.req.arg[1] = op | BIT_31 | temp; | ||
1914 | } else { | ||
1915 | cmd.req.arg[1] = adapter->ahw->pci_func << 16; | ||
1916 | } | ||
1917 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1918 | if (err) { | ||
1919 | dev_info(&adapter->pdev->dev, | ||
1920 | "Failed to get nic info %d\n", err); | ||
1921 | goto out; | ||
1922 | } | ||
1923 | |||
1924 | npar_info->op_type = cmd.rsp.arg[1]; | ||
1925 | npar_info->pci_func = cmd.rsp.arg[2] & 0xFFFF; | ||
1926 | npar_info->op_mode = (cmd.rsp.arg[2] & 0xFFFF0000) >> 16; | ||
1927 | npar_info->phys_port = cmd.rsp.arg[3] & 0xFFFF; | ||
1928 | npar_info->switch_mode = (cmd.rsp.arg[3] & 0xFFFF0000) >> 16; | ||
1929 | npar_info->capabilities = cmd.rsp.arg[4]; | ||
1930 | npar_info->max_mac_filters = cmd.rsp.arg[5] & 0xFF; | ||
1931 | npar_info->max_mtu = (cmd.rsp.arg[5] & 0xFFFF0000) >> 16; | ||
1932 | npar_info->max_tx_ques = cmd.rsp.arg[6] & 0xFFFF; | ||
1933 | npar_info->max_rx_ques = (cmd.rsp.arg[6] & 0xFFFF0000) >> 16; | ||
1934 | npar_info->min_tx_bw = cmd.rsp.arg[7] & 0xFFFF; | ||
1935 | npar_info->max_tx_bw = (cmd.rsp.arg[7] & 0xFFFF0000) >> 16; | ||
1936 | if (cmd.rsp.arg[8] & 0x1) | ||
1937 | npar_info->max_bw_reg_offset = (cmd.rsp.arg[8] & 0x7FFE) >> 1; | ||
1938 | if (cmd.rsp.arg[8] & 0x10000) { | ||
1939 | temp = (cmd.rsp.arg[8] & 0x7FFE0000) >> 17; | ||
1940 | npar_info->max_linkspeed_reg_offset = temp; | ||
1941 | } | ||
1942 | |||
1943 | out: | ||
1944 | qlcnic_free_mbx_args(&cmd); | ||
1945 | return err; | ||
1946 | } | ||
1947 | |||
1948 | int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *adapter, | ||
1949 | struct qlcnic_pci_info *pci_info) | ||
1950 | { | ||
1951 | int i, err = 0, j = 0; | ||
1952 | u32 temp; | ||
1953 | struct qlcnic_cmd_args cmd; | ||
1954 | |||
1955 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO); | ||
1956 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
1957 | |||
1958 | adapter->ahw->act_pci_func = 0; | ||
1959 | if (err == QLCNIC_RCODE_SUCCESS) { | ||
1960 | pci_info->func_count = cmd.rsp.arg[1] & 0xFF; | ||
1961 | dev_info(&adapter->pdev->dev, | ||
1962 | "%s: total functions = %d\n", | ||
1963 | __func__, pci_info->func_count); | ||
1964 | for (i = 2, j = 0; j < QLCNIC_MAX_PCI_FUNC; j++, pci_info++) { | ||
1965 | pci_info->id = cmd.rsp.arg[i] & 0xFFFF; | ||
1966 | pci_info->active = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16; | ||
1967 | i++; | ||
1968 | pci_info->type = cmd.rsp.arg[i] & 0xFFFF; | ||
1969 | if (pci_info->type == QLCNIC_TYPE_NIC) | ||
1970 | adapter->ahw->act_pci_func++; | ||
1971 | temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16; | ||
1972 | pci_info->default_port = temp; | ||
1973 | i++; | ||
1974 | pci_info->tx_min_bw = cmd.rsp.arg[i] & 0xFFFF; | ||
1975 | temp = (cmd.rsp.arg[i] & 0xFFFF0000) >> 16; | ||
1976 | pci_info->tx_max_bw = temp; | ||
1977 | i = i + 2; | ||
1978 | memcpy(pci_info->mac, &cmd.rsp.arg[i], ETH_ALEN - 2); | ||
1979 | i++; | ||
1980 | memcpy(pci_info->mac + sizeof(u32), &cmd.rsp.arg[i], 2); | ||
1981 | i = i + 3; | ||
1982 | |||
1983 | dev_info(&adapter->pdev->dev, "%s:\n" | ||
1984 | "\tid = %d active = %d type = %d\n" | ||
1985 | "\tport = %d min bw = %d max bw = %d\n" | ||
1986 | "\tmac_addr = %pM\n", __func__, | ||
1987 | pci_info->id, pci_info->active, pci_info->type, | ||
1988 | pci_info->default_port, pci_info->tx_min_bw, | ||
1989 | pci_info->tx_max_bw, pci_info->mac); | ||
1990 | } | ||
1991 | } else { | ||
1992 | dev_err(&adapter->pdev->dev, "Failed to get PCI Info%d\n", | ||
1993 | err); | ||
1994 | err = -EIO; | ||
1995 | } | ||
1996 | |||
1997 | qlcnic_free_mbx_args(&cmd); | ||
1998 | |||
1999 | return err; | ||
2000 | } | ||
2001 | |||
2002 | int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *adapter, bool op_type) | ||
2003 | { | ||
2004 | int i, index, err; | ||
2005 | bool type; | ||
2006 | u8 max_ints; | ||
2007 | u32 val, temp; | ||
2008 | struct qlcnic_cmd_args cmd; | ||
2009 | |||
2010 | max_ints = adapter->ahw->num_msix - 1; | ||
2011 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_INTRPT); | ||
2012 | cmd.req.arg[1] = max_ints; | ||
2013 | for (i = 0, index = 2; i < max_ints; i++) { | ||
2014 | type = op_type ? QLCNIC_INTRPT_ADD : QLCNIC_INTRPT_DEL; | ||
2015 | val = type | (adapter->ahw->intr_tbl[i].type << 4); | ||
2016 | if (adapter->ahw->intr_tbl[i].type == QLCNIC_INTRPT_MSIX) | ||
2017 | val |= (adapter->ahw->intr_tbl[i].id << 16); | ||
2018 | cmd.req.arg[index++] = val; | ||
2019 | } | ||
2020 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
2021 | if (err) { | ||
2022 | dev_err(&adapter->pdev->dev, | ||
2023 | "Failed to configure interrupts 0x%x\n", err); | ||
2024 | goto out; | ||
2025 | } | ||
2026 | |||
2027 | max_ints = cmd.rsp.arg[1]; | ||
2028 | for (i = 0, index = 2; i < max_ints; i++, index += 2) { | ||
2029 | val = cmd.rsp.arg[index]; | ||
2030 | if (LSB(val)) { | ||
2031 | dev_info(&adapter->pdev->dev, | ||
2032 | "Can't configure interrupt %d\n", | ||
2033 | adapter->ahw->intr_tbl[i].id); | ||
2034 | continue; | ||
2035 | } | ||
2036 | if (op_type) { | ||
2037 | adapter->ahw->intr_tbl[i].id = MSW(val); | ||
2038 | adapter->ahw->intr_tbl[i].enabled = 1; | ||
2039 | temp = cmd.rsp.arg[index + 1]; | ||
2040 | adapter->ahw->intr_tbl[i].src = temp; | ||
2041 | } else { | ||
2042 | adapter->ahw->intr_tbl[i].id = i; | ||
2043 | adapter->ahw->intr_tbl[i].enabled = 0; | ||
2044 | adapter->ahw->intr_tbl[i].src = 0; | ||
2045 | } | ||
2046 | } | ||
2047 | out: | ||
2048 | qlcnic_free_mbx_args(&cmd); | ||
2049 | return err; | ||
2050 | } | ||
2051 | |||
2052 | int qlcnic_83xx_lock_flash(struct qlcnic_adapter *adapter) | ||
2053 | { | ||
2054 | int id, timeout = 0; | ||
2055 | u32 status = 0; | ||
2056 | |||
2057 | while (status == 0) { | ||
2058 | status = QLC_SHARED_REG_RD32(adapter, QLCNIC_FLASH_LOCK); | ||
2059 | if (status) | ||
2060 | break; | ||
2061 | |||
2062 | if (++timeout >= QLC_83XX_FLASH_LOCK_TIMEOUT) { | ||
2063 | id = QLC_SHARED_REG_RD32(adapter, | ||
2064 | QLCNIC_FLASH_LOCK_OWNER); | ||
2065 | dev_err(&adapter->pdev->dev, | ||
2066 | "%s: failed, lock held by %d\n", __func__, id); | ||
2067 | return -EIO; | ||
2068 | } | ||
2069 | usleep_range(1000, 2000); | ||
2070 | } | ||
2071 | |||
2072 | QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER, adapter->portnum); | ||
2073 | return 0; | ||
2074 | } | ||
2075 | |||
2076 | void qlcnic_83xx_unlock_flash(struct qlcnic_adapter *adapter) | ||
2077 | { | ||
2078 | QLC_SHARED_REG_RD32(adapter, QLCNIC_FLASH_UNLOCK); | ||
2079 | QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER, 0xFF); | ||
2080 | } | ||
2081 | |||
2082 | int qlcnic_83xx_lockless_flash_read32(struct qlcnic_adapter *adapter, | ||
2083 | u32 flash_addr, u8 *p_data, | ||
2084 | int count) | ||
2085 | { | ||
2086 | int i, ret; | ||
2087 | u32 word, range, flash_offset, addr = flash_addr; | ||
2088 | ulong indirect_add, direct_window; | ||
2089 | |||
2090 | flash_offset = addr & (QLCNIC_FLASH_SECTOR_SIZE - 1); | ||
2091 | if (addr & 0x3) { | ||
2092 | dev_err(&adapter->pdev->dev, "Illegal addr = 0x%x\n", addr); | ||
2093 | return -EIO; | ||
2094 | } | ||
2095 | |||
2096 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_DIRECT_WINDOW, | ||
2097 | (addr)); | ||
2098 | |||
2099 | range = flash_offset + (count * sizeof(u32)); | ||
2100 | /* Check if data is spread across multiple sectors */ | ||
2101 | if (range > (QLCNIC_FLASH_SECTOR_SIZE - 1)) { | ||
2102 | |||
2103 | /* Multi sector read */ | ||
2104 | for (i = 0; i < count; i++) { | ||
2105 | indirect_add = QLC_83XX_FLASH_DIRECT_DATA(addr); | ||
2106 | ret = qlcnic_83xx_rd_reg_indirect(adapter, | ||
2107 | indirect_add); | ||
2108 | if (ret == -EIO) | ||
2109 | return -EIO; | ||
2110 | |||
2111 | word = ret; | ||
2112 | *(u32 *)p_data = word; | ||
2113 | p_data = p_data + 4; | ||
2114 | addr = addr + 4; | ||
2115 | flash_offset = flash_offset + 4; | ||
2116 | |||
2117 | if (flash_offset > (QLCNIC_FLASH_SECTOR_SIZE - 1)) { | ||
2118 | direct_window = QLC_83XX_FLASH_DIRECT_WINDOW; | ||
2119 | /* This write is needed once for each sector */ | ||
2120 | qlcnic_83xx_wrt_reg_indirect(adapter, | ||
2121 | direct_window, | ||
2122 | (addr)); | ||
2123 | flash_offset = 0; | ||
2124 | } | ||
2125 | } | ||
2126 | } else { | ||
2127 | /* Single sector read */ | ||
2128 | for (i = 0; i < count; i++) { | ||
2129 | indirect_add = QLC_83XX_FLASH_DIRECT_DATA(addr); | ||
2130 | ret = qlcnic_83xx_rd_reg_indirect(adapter, | ||
2131 | indirect_add); | ||
2132 | if (ret == -EIO) | ||
2133 | return -EIO; | ||
2134 | |||
2135 | word = ret; | ||
2136 | *(u32 *)p_data = word; | ||
2137 | p_data = p_data + 4; | ||
2138 | addr = addr + 4; | ||
2139 | } | ||
2140 | } | ||
2141 | |||
2142 | return 0; | ||
2143 | } | ||
2144 | |||
2145 | static int qlcnic_83xx_poll_flash_status_reg(struct qlcnic_adapter *adapter) | ||
2146 | { | ||
2147 | u32 status; | ||
2148 | int retries = QLC_83XX_FLASH_READ_RETRY_COUNT; | ||
2149 | |||
2150 | do { | ||
2151 | status = qlcnic_83xx_rd_reg_indirect(adapter, | ||
2152 | QLC_83XX_FLASH_STATUS); | ||
2153 | if ((status & QLC_83XX_FLASH_STATUS_READY) == | ||
2154 | QLC_83XX_FLASH_STATUS_READY) | ||
2155 | break; | ||
2156 | |||
2157 | msleep(QLC_83XX_FLASH_STATUS_REG_POLL_DELAY); | ||
2158 | } while (--retries); | ||
2159 | |||
2160 | if (!retries) | ||
2161 | return -EIO; | ||
2162 | |||
2163 | return 0; | ||
2164 | } | ||
2165 | |||
2166 | static int qlcnic_83xx_enable_flash_write_op(struct qlcnic_adapter *adapter) | ||
2167 | { | ||
2168 | int ret; | ||
2169 | u32 cmd; | ||
2170 | cmd = adapter->ahw->fdt.write_statusreg_cmd; | ||
2171 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR, | ||
2172 | (QLC_83XX_FLASH_FDT_WRITE_DEF_SIG | cmd)); | ||
2173 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, | ||
2174 | adapter->ahw->fdt.write_enable_bits); | ||
2175 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL, | ||
2176 | QLC_83XX_FLASH_SECOND_ERASE_MS_VAL); | ||
2177 | ret = qlcnic_83xx_poll_flash_status_reg(adapter); | ||
2178 | if (ret) | ||
2179 | return -EIO; | ||
2180 | |||
2181 | return 0; | ||
2182 | } | ||
2183 | |||
2184 | static int qlcnic_83xx_disable_flash_write_op(struct qlcnic_adapter *adapter) | ||
2185 | { | ||
2186 | int ret; | ||
2187 | |||
2188 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR, | ||
2189 | (QLC_83XX_FLASH_FDT_WRITE_DEF_SIG | | ||
2190 | adapter->ahw->fdt.write_statusreg_cmd)); | ||
2191 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, | ||
2192 | adapter->ahw->fdt.write_disable_bits); | ||
2193 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL, | ||
2194 | QLC_83XX_FLASH_SECOND_ERASE_MS_VAL); | ||
2195 | ret = qlcnic_83xx_poll_flash_status_reg(adapter); | ||
2196 | if (ret) | ||
2197 | return -EIO; | ||
2198 | |||
2199 | return 0; | ||
2200 | } | ||
2201 | |||
2202 | int qlcnic_83xx_read_flash_mfg_id(struct qlcnic_adapter *adapter) | ||
2203 | { | ||
2204 | int ret, mfg_id; | ||
2205 | |||
2206 | if (qlcnic_83xx_lock_flash(adapter)) | ||
2207 | return -EIO; | ||
2208 | |||
2209 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR, | ||
2210 | QLC_83XX_FLASH_FDT_READ_MFG_ID_VAL); | ||
2211 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL, | ||
2212 | QLC_83XX_FLASH_READ_CTRL); | ||
2213 | ret = qlcnic_83xx_poll_flash_status_reg(adapter); | ||
2214 | if (ret) { | ||
2215 | qlcnic_83xx_unlock_flash(adapter); | ||
2216 | return -EIO; | ||
2217 | } | ||
2218 | |||
2219 | mfg_id = qlcnic_83xx_rd_reg_indirect(adapter, QLC_83XX_FLASH_RDDATA); | ||
2220 | if (mfg_id == -EIO) | ||
2221 | return -EIO; | ||
2222 | |||
2223 | adapter->flash_mfg_id = (mfg_id & 0xFF); | ||
2224 | qlcnic_83xx_unlock_flash(adapter); | ||
2225 | |||
2226 | return 0; | ||
2227 | } | ||
2228 | |||
2229 | int qlcnic_83xx_read_flash_descriptor_table(struct qlcnic_adapter *adapter) | ||
2230 | { | ||
2231 | int count, fdt_size, ret = 0; | ||
2232 | |||
2233 | fdt_size = sizeof(struct qlcnic_fdt); | ||
2234 | count = fdt_size / sizeof(u32); | ||
2235 | |||
2236 | if (qlcnic_83xx_lock_flash(adapter)) | ||
2237 | return -EIO; | ||
2238 | |||
2239 | memset(&adapter->ahw->fdt, 0, fdt_size); | ||
2240 | ret = qlcnic_83xx_lockless_flash_read32(adapter, QLCNIC_FDT_LOCATION, | ||
2241 | (u8 *)&adapter->ahw->fdt, | ||
2242 | count); | ||
2243 | |||
2244 | qlcnic_83xx_unlock_flash(adapter); | ||
2245 | return ret; | ||
2246 | } | ||
2247 | |||
2248 | int qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *adapter, | ||
2249 | u32 sector_start_addr) | ||
2250 | { | ||
2251 | u32 reversed_addr, addr1, addr2, cmd; | ||
2252 | int ret = -EIO; | ||
2253 | |||
2254 | if (qlcnic_83xx_lock_flash(adapter) != 0) | ||
2255 | return -EIO; | ||
2256 | |||
2257 | if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) { | ||
2258 | ret = qlcnic_83xx_enable_flash_write_op(adapter); | ||
2259 | if (ret) { | ||
2260 | qlcnic_83xx_unlock_flash(adapter); | ||
2261 | dev_err(&adapter->pdev->dev, | ||
2262 | "%s failed at %d\n", | ||
2263 | __func__, __LINE__); | ||
2264 | return ret; | ||
2265 | } | ||
2266 | } | ||
2267 | |||
2268 | ret = qlcnic_83xx_poll_flash_status_reg(adapter); | ||
2269 | if (ret) { | ||
2270 | qlcnic_83xx_unlock_flash(adapter); | ||
2271 | dev_err(&adapter->pdev->dev, | ||
2272 | "%s: failed at %d\n", __func__, __LINE__); | ||
2273 | return -EIO; | ||
2274 | } | ||
2275 | |||
2276 | addr1 = (sector_start_addr & 0xFF) << 16; | ||
2277 | addr2 = (sector_start_addr & 0xFF0000) >> 16; | ||
2278 | reversed_addr = addr1 | addr2; | ||
2279 | |||
2280 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, | ||
2281 | reversed_addr); | ||
2282 | cmd = QLC_83XX_FLASH_FDT_ERASE_DEF_SIG | adapter->ahw->fdt.erase_cmd; | ||
2283 | if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) | ||
2284 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR, cmd); | ||
2285 | else | ||
2286 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR, | ||
2287 | QLC_83XX_FLASH_OEM_ERASE_SIG); | ||
2288 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL, | ||
2289 | QLC_83XX_FLASH_LAST_ERASE_MS_VAL); | ||
2290 | |||
2291 | ret = qlcnic_83xx_poll_flash_status_reg(adapter); | ||
2292 | if (ret) { | ||
2293 | qlcnic_83xx_unlock_flash(adapter); | ||
2294 | dev_err(&adapter->pdev->dev, | ||
2295 | "%s: failed at %d\n", __func__, __LINE__); | ||
2296 | return -EIO; | ||
2297 | } | ||
2298 | |||
2299 | if (adapter->ahw->fdt.mfg_id == adapter->flash_mfg_id) { | ||
2300 | ret = qlcnic_83xx_disable_flash_write_op(adapter); | ||
2301 | if (ret) { | ||
2302 | qlcnic_83xx_unlock_flash(adapter); | ||
2303 | dev_err(&adapter->pdev->dev, | ||
2304 | "%s: failed at %d\n", __func__, __LINE__); | ||
2305 | return ret; | ||
2306 | } | ||
2307 | } | ||
2308 | |||
2309 | qlcnic_83xx_unlock_flash(adapter); | ||
2310 | |||
2311 | return 0; | ||
2312 | } | ||
2313 | |||
2314 | int qlcnic_83xx_flash_write32(struct qlcnic_adapter *adapter, u32 addr, | ||
2315 | u32 *p_data) | ||
2316 | { | ||
2317 | int ret = -EIO; | ||
2318 | u32 addr1 = 0x00800000 | (addr >> 2); | ||
2319 | |||
2320 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR, addr1); | ||
2321 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, *p_data); | ||
2322 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL, | ||
2323 | QLC_83XX_FLASH_LAST_ERASE_MS_VAL); | ||
2324 | ret = qlcnic_83xx_poll_flash_status_reg(adapter); | ||
2325 | if (ret) { | ||
2326 | dev_err(&adapter->pdev->dev, | ||
2327 | "%s: failed at %d\n", __func__, __LINE__); | ||
2328 | return -EIO; | ||
2329 | } | ||
2330 | |||
2331 | return 0; | ||
2332 | } | ||
2333 | |||
2334 | int qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *adapter, u32 addr, | ||
2335 | u32 *p_data, int count) | ||
2336 | { | ||
2337 | u32 temp; | ||
2338 | int ret = -EIO; | ||
2339 | |||
2340 | if ((count < QLC_83XX_FLASH_BULK_WRITE_MIN) || | ||
2341 | (count > QLC_83XX_FLASH_BULK_WRITE_MAX)) { | ||
2342 | dev_err(&adapter->pdev->dev, | ||
2343 | "%s: Invalid word count\n", __func__); | ||
2344 | return -EIO; | ||
2345 | } | ||
2346 | |||
2347 | temp = qlcnic_83xx_rd_reg_indirect(adapter, | ||
2348 | QLC_83XX_FLASH_SPI_CONTROL); | ||
2349 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_SPI_CONTROL, | ||
2350 | (temp | QLC_83XX_FLASH_SPI_CTRL)); | ||
2351 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR, | ||
2352 | QLC_83XX_FLASH_ADDR_TEMP_VAL); | ||
2353 | |||
2354 | /* First DWORD write */ | ||
2355 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, *p_data++); | ||
2356 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL, | ||
2357 | QLC_83XX_FLASH_FIRST_MS_PATTERN); | ||
2358 | ret = qlcnic_83xx_poll_flash_status_reg(adapter); | ||
2359 | if (ret) { | ||
2360 | dev_err(&adapter->pdev->dev, | ||
2361 | "%s: failed at %d\n", __func__, __LINE__); | ||
2362 | return -EIO; | ||
2363 | } | ||
2364 | |||
2365 | count--; | ||
2366 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR, | ||
2367 | QLC_83XX_FLASH_ADDR_SECOND_TEMP_VAL); | ||
2368 | /* Second to N-1 DWORD writes */ | ||
2369 | while (count != 1) { | ||
2370 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, | ||
2371 | *p_data++); | ||
2372 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL, | ||
2373 | QLC_83XX_FLASH_SECOND_MS_PATTERN); | ||
2374 | ret = qlcnic_83xx_poll_flash_status_reg(adapter); | ||
2375 | if (ret) { | ||
2376 | dev_err(&adapter->pdev->dev, | ||
2377 | "%s: failed at %d\n", __func__, __LINE__); | ||
2378 | return -EIO; | ||
2379 | } | ||
2380 | count--; | ||
2381 | } | ||
2382 | |||
2383 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR, | ||
2384 | QLC_83XX_FLASH_ADDR_TEMP_VAL | | ||
2385 | (addr >> 2)); | ||
2386 | /* Last DWORD write */ | ||
2387 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_WRDATA, *p_data++); | ||
2388 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL, | ||
2389 | QLC_83XX_FLASH_LAST_MS_PATTERN); | ||
2390 | ret = qlcnic_83xx_poll_flash_status_reg(adapter); | ||
2391 | if (ret) { | ||
2392 | dev_err(&adapter->pdev->dev, | ||
2393 | "%s: failed at %d\n", __func__, __LINE__); | ||
2394 | return -EIO; | ||
2395 | } | ||
2396 | |||
2397 | ret = qlcnic_83xx_rd_reg_indirect(adapter, QLC_83XX_FLASH_SPI_STATUS); | ||
2398 | if ((ret & QLC_83XX_FLASH_SPI_CTRL) == QLC_83XX_FLASH_SPI_CTRL) { | ||
2399 | dev_err(&adapter->pdev->dev, "%s: failed at %d\n", | ||
2400 | __func__, __LINE__); | ||
2401 | /* Operation failed, clear error bit */ | ||
2402 | temp = qlcnic_83xx_rd_reg_indirect(adapter, | ||
2403 | QLC_83XX_FLASH_SPI_CONTROL); | ||
2404 | qlcnic_83xx_wrt_reg_indirect(adapter, | ||
2405 | QLC_83XX_FLASH_SPI_CONTROL, | ||
2406 | (temp | QLC_83XX_FLASH_SPI_CTRL)); | ||
2407 | } | ||
2408 | |||
2409 | return 0; | ||
2410 | } | ||
2411 | |||
2412 | static void qlcnic_83xx_recover_driver_lock(struct qlcnic_adapter *adapter) | ||
2413 | { | ||
2414 | u32 val, id; | ||
2415 | |||
2416 | val = QLCRDX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK); | ||
2417 | |||
2418 | /* Check if recovery need to be performed by the calling function */ | ||
2419 | if ((val & QLC_83XX_DRV_LOCK_RECOVERY_STATUS_MASK) == 0) { | ||
2420 | val = val & ~0x3F; | ||
2421 | val = val | ((adapter->portnum << 2) | | ||
2422 | QLC_83XX_NEED_DRV_LOCK_RECOVERY); | ||
2423 | QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val); | ||
2424 | dev_info(&adapter->pdev->dev, | ||
2425 | "%s: lock recovery initiated\n", __func__); | ||
2426 | msleep(QLC_83XX_DRV_LOCK_RECOVERY_DELAY); | ||
2427 | val = QLCRDX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK); | ||
2428 | id = ((val >> 2) & 0xF); | ||
2429 | if (id == adapter->portnum) { | ||
2430 | val = val & ~QLC_83XX_DRV_LOCK_RECOVERY_STATUS_MASK; | ||
2431 | val = val | QLC_83XX_DRV_LOCK_RECOVERY_IN_PROGRESS; | ||
2432 | QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val); | ||
2433 | /* Force release the lock */ | ||
2434 | QLCRDX(adapter->ahw, QLC_83XX_DRV_UNLOCK); | ||
2435 | /* Clear recovery bits */ | ||
2436 | val = val & ~0x3F; | ||
2437 | QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, val); | ||
2438 | dev_info(&adapter->pdev->dev, | ||
2439 | "%s: lock recovery completed\n", __func__); | ||
2440 | } else { | ||
2441 | dev_info(&adapter->pdev->dev, | ||
2442 | "%s: func %d to resume lock recovery process\n", | ||
2443 | __func__, id); | ||
2444 | } | ||
2445 | } else { | ||
2446 | dev_info(&adapter->pdev->dev, | ||
2447 | "%s: lock recovery initiated by other functions\n", | ||
2448 | __func__); | ||
2449 | } | ||
2450 | } | ||
2451 | |||
2452 | int qlcnic_83xx_lock_driver(struct qlcnic_adapter *adapter) | ||
2453 | { | ||
2454 | u32 lock_alive_counter, val, id, i = 0, status = 0, temp = 0; | ||
2455 | int max_attempt = 0; | ||
2456 | |||
2457 | while (status == 0) { | ||
2458 | status = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK); | ||
2459 | if (status) | ||
2460 | break; | ||
2461 | |||
2462 | msleep(QLC_83XX_DRV_LOCK_WAIT_DELAY); | ||
2463 | i++; | ||
2464 | |||
2465 | if (i == 1) | ||
2466 | temp = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID); | ||
2467 | |||
2468 | if (i == QLC_83XX_DRV_LOCK_WAIT_COUNTER) { | ||
2469 | val = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID); | ||
2470 | if (val == temp) { | ||
2471 | id = val & 0xFF; | ||
2472 | dev_info(&adapter->pdev->dev, | ||
2473 | "%s: lock to be recovered from %d\n", | ||
2474 | __func__, id); | ||
2475 | qlcnic_83xx_recover_driver_lock(adapter); | ||
2476 | i = 0; | ||
2477 | max_attempt++; | ||
2478 | } else { | ||
2479 | dev_err(&adapter->pdev->dev, | ||
2480 | "%s: failed to get lock\n", __func__); | ||
2481 | return -EIO; | ||
2482 | } | ||
2483 | } | ||
2484 | |||
2485 | /* Force exit from while loop after few attempts */ | ||
2486 | if (max_attempt == QLC_83XX_MAX_DRV_LOCK_RECOVERY_ATTEMPT) { | ||
2487 | dev_err(&adapter->pdev->dev, | ||
2488 | "%s: failed to get lock\n", __func__); | ||
2489 | return -EIO; | ||
2490 | } | ||
2491 | } | ||
2492 | |||
2493 | val = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID); | ||
2494 | lock_alive_counter = val >> 8; | ||
2495 | lock_alive_counter++; | ||
2496 | val = lock_alive_counter << 8 | adapter->portnum; | ||
2497 | QLCWRX(adapter->ahw, QLC_83XX_DRV_LOCK_ID, val); | ||
2498 | |||
2499 | return 0; | ||
2500 | } | ||
2501 | |||
2502 | void qlcnic_83xx_unlock_driver(struct qlcnic_adapter *adapter) | ||
2503 | { | ||
2504 | u32 val, lock_alive_counter, id; | ||
2505 | |||
2506 | val = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID); | ||
2507 | id = val & 0xFF; | ||
2508 | lock_alive_counter = val >> 8; | ||
2509 | |||
2510 | if (id != adapter->portnum) | ||
2511 | dev_err(&adapter->pdev->dev, | ||
2512 | "%s:Warning func %d is unlocking lock owned by %d\n", | ||
2513 | __func__, adapter->portnum, id); | ||
2514 | |||
2515 | val = (lock_alive_counter << 8) | 0xFF; | ||
2516 | QLCWRX(adapter->ahw, QLC_83XX_DRV_LOCK_ID, val); | ||
2517 | QLCRDX(adapter->ahw, QLC_83XX_DRV_UNLOCK); | ||
2518 | } | ||
2519 | |||
2520 | int qlcnic_83xx_ms_mem_write128(struct qlcnic_adapter *adapter, u64 addr, | ||
2521 | u32 *data, u32 count) | ||
2522 | { | ||
2523 | int i, j, ret = 0; | ||
2524 | u32 temp; | ||
2525 | |||
2526 | /* Check alignment */ | ||
2527 | if (addr & 0xF) | ||
2528 | return -EIO; | ||
2529 | |||
2530 | mutex_lock(&adapter->ahw->mem_lock); | ||
2531 | qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_ADDR_HI, 0); | ||
2532 | |||
2533 | for (i = 0; i < count; i++, addr += 16) { | ||
2534 | if (!((ADDR_IN_RANGE(addr, QLCNIC_ADDR_QDR_NET, | ||
2535 | QLCNIC_ADDR_QDR_NET_MAX)) || | ||
2536 | (ADDR_IN_RANGE(addr, QLCNIC_ADDR_DDR_NET, | ||
2537 | QLCNIC_ADDR_DDR_NET_MAX)))) { | ||
2538 | mutex_unlock(&adapter->ahw->mem_lock); | ||
2539 | return -EIO; | ||
2540 | } | ||
2541 | |||
2542 | qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_ADDR_LO, addr); | ||
2543 | qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_WRTDATA_LO, | ||
2544 | *data++); | ||
2545 | qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_WRTDATA_HI, | ||
2546 | *data++); | ||
2547 | qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_WRTDATA_ULO, | ||
2548 | *data++); | ||
2549 | qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_WRTDATA_UHI, | ||
2550 | *data++); | ||
2551 | qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_CTRL, | ||
2552 | QLCNIC_TA_WRITE_ENABLE); | ||
2553 | qlcnic_83xx_wrt_reg_indirect(adapter, QLCNIC_MS_CTRL, | ||
2554 | QLCNIC_TA_WRITE_START); | ||
2555 | |||
2556 | for (j = 0; j < MAX_CTL_CHECK; j++) { | ||
2557 | temp = qlcnic_83xx_rd_reg_indirect(adapter, | ||
2558 | QLCNIC_MS_CTRL); | ||
2559 | if ((temp & TA_CTL_BUSY) == 0) | ||
2560 | break; | ||
2561 | } | ||
2562 | |||
2563 | /* Status check failure */ | ||
2564 | if (j >= MAX_CTL_CHECK) { | ||
2565 | printk_ratelimited(KERN_WARNING | ||
2566 | "MS memory write failed\n"); | ||
2567 | mutex_unlock(&adapter->ahw->mem_lock); | ||
2568 | return -EIO; | ||
2569 | } | ||
2570 | } | ||
2571 | |||
2572 | mutex_unlock(&adapter->ahw->mem_lock); | ||
2573 | |||
2574 | return ret; | ||
2575 | } | ||
2576 | |||
2577 | int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr, | ||
2578 | u8 *p_data, int count) | ||
2579 | { | ||
2580 | int i, ret; | ||
2581 | u32 word, addr = flash_addr; | ||
2582 | ulong indirect_addr; | ||
2583 | |||
2584 | if (qlcnic_83xx_lock_flash(adapter) != 0) | ||
2585 | return -EIO; | ||
2586 | |||
2587 | if (addr & 0x3) { | ||
2588 | dev_err(&adapter->pdev->dev, "Illegal addr = 0x%x\n", addr); | ||
2589 | qlcnic_83xx_unlock_flash(adapter); | ||
2590 | return -EIO; | ||
2591 | } | ||
2592 | |||
2593 | for (i = 0; i < count; i++) { | ||
2594 | if (qlcnic_83xx_wrt_reg_indirect(adapter, | ||
2595 | QLC_83XX_FLASH_DIRECT_WINDOW, | ||
2596 | (addr))) { | ||
2597 | qlcnic_83xx_unlock_flash(adapter); | ||
2598 | return -EIO; | ||
2599 | } | ||
2600 | |||
2601 | indirect_addr = QLC_83XX_FLASH_DIRECT_DATA(addr); | ||
2602 | ret = qlcnic_83xx_rd_reg_indirect(adapter, | ||
2603 | indirect_addr); | ||
2604 | if (ret == -EIO) | ||
2605 | return -EIO; | ||
2606 | word = ret; | ||
2607 | *(u32 *)p_data = word; | ||
2608 | p_data = p_data + 4; | ||
2609 | addr = addr + 4; | ||
2610 | } | ||
2611 | |||
2612 | qlcnic_83xx_unlock_flash(adapter); | ||
2613 | |||
2614 | return 0; | ||
2615 | } | ||
2616 | |||
2617 | int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter) | ||
2618 | { | ||
2619 | int err; | ||
2620 | u32 config = 0, state; | ||
2621 | struct qlcnic_cmd_args cmd; | ||
2622 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2623 | |||
2624 | state = readl(ahw->pci_base0 + QLC_83XX_LINK_STATE(ahw->pci_func)); | ||
2625 | if (!QLC_83xx_FUNC_VAL(state, ahw->pci_func)) { | ||
2626 | dev_info(&adapter->pdev->dev, "link state down\n"); | ||
2627 | return config; | ||
2628 | } | ||
2629 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_STATUS); | ||
2630 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
2631 | if (err) { | ||
2632 | dev_info(&adapter->pdev->dev, | ||
2633 | "Get Link Status Command failed: 0x%x\n", err); | ||
2634 | goto out; | ||
2635 | } else { | ||
2636 | config = cmd.rsp.arg[1]; | ||
2637 | switch (QLC_83XX_CURRENT_LINK_SPEED(config)) { | ||
2638 | case QLC_83XX_10M_LINK: | ||
2639 | ahw->link_speed = SPEED_10; | ||
2640 | break; | ||
2641 | case QLC_83XX_100M_LINK: | ||
2642 | ahw->link_speed = SPEED_100; | ||
2643 | break; | ||
2644 | case QLC_83XX_1G_LINK: | ||
2645 | ahw->link_speed = SPEED_1000; | ||
2646 | break; | ||
2647 | case QLC_83XX_10G_LINK: | ||
2648 | ahw->link_speed = SPEED_10000; | ||
2649 | break; | ||
2650 | default: | ||
2651 | ahw->link_speed = 0; | ||
2652 | break; | ||
2653 | } | ||
2654 | config = cmd.rsp.arg[3]; | ||
2655 | if (config & 1) | ||
2656 | err = 1; | ||
2657 | } | ||
2658 | out: | ||
2659 | qlcnic_free_mbx_args(&cmd); | ||
2660 | return config; | ||
2661 | } | ||
2662 | |||
2663 | int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter) | ||
2664 | { | ||
2665 | u32 config = 0; | ||
2666 | int status = 0; | ||
2667 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2668 | |||
2669 | /* Get port configuration info */ | ||
2670 | status = qlcnic_83xx_get_port_info(adapter); | ||
2671 | /* Get Link Status related info */ | ||
2672 | config = qlcnic_83xx_test_link(adapter); | ||
2673 | ahw->module_type = QLC_83XX_SFP_MODULE_TYPE(config); | ||
2674 | /* hard code until there is a way to get it from flash */ | ||
2675 | ahw->board_type = QLCNIC_BRDTYPE_83XX_10G; | ||
2676 | return status; | ||
2677 | } | ||
2678 | |||
2679 | int qlcnic_83xx_set_settings(struct qlcnic_adapter *adapter, | ||
2680 | struct ethtool_cmd *ecmd) | ||
2681 | { | ||
2682 | int status = 0; | ||
2683 | u32 config = adapter->ahw->port_config; | ||
2684 | |||
2685 | if (ecmd->autoneg) | ||
2686 | adapter->ahw->port_config |= BIT_15; | ||
2687 | |||
2688 | switch (ethtool_cmd_speed(ecmd)) { | ||
2689 | case SPEED_10: | ||
2690 | adapter->ahw->port_config |= BIT_8; | ||
2691 | break; | ||
2692 | case SPEED_100: | ||
2693 | adapter->ahw->port_config |= BIT_9; | ||
2694 | break; | ||
2695 | case SPEED_1000: | ||
2696 | adapter->ahw->port_config |= BIT_10; | ||
2697 | break; | ||
2698 | case SPEED_10000: | ||
2699 | adapter->ahw->port_config |= BIT_11; | ||
2700 | break; | ||
2701 | default: | ||
2702 | return -EINVAL; | ||
2703 | } | ||
2704 | |||
2705 | status = qlcnic_83xx_set_port_config(adapter); | ||
2706 | if (status) { | ||
2707 | dev_info(&adapter->pdev->dev, | ||
2708 | "Faild to Set Link Speed and autoneg.\n"); | ||
2709 | adapter->ahw->port_config = config; | ||
2710 | } | ||
2711 | return status; | ||
2712 | } | ||
2713 | |||
2714 | static inline u64 *qlcnic_83xx_copy_stats(struct qlcnic_cmd_args *cmd, | ||
2715 | u64 *data, int index) | ||
2716 | { | ||
2717 | u32 low, hi; | ||
2718 | u64 val; | ||
2719 | |||
2720 | low = cmd->rsp.arg[index]; | ||
2721 | hi = cmd->rsp.arg[index + 1]; | ||
2722 | val = (((u64) low) | (((u64) hi) << 32)); | ||
2723 | *data++ = val; | ||
2724 | return data; | ||
2725 | } | ||
2726 | |||
2727 | static u64 *qlcnic_83xx_fill_stats(struct qlcnic_adapter *adapter, | ||
2728 | struct qlcnic_cmd_args *cmd, u64 *data, | ||
2729 | int type, int *ret) | ||
2730 | { | ||
2731 | int err, k, total_regs; | ||
2732 | |||
2733 | *ret = 0; | ||
2734 | err = qlcnic_issue_cmd(adapter, cmd); | ||
2735 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
2736 | dev_info(&adapter->pdev->dev, | ||
2737 | "Error in get statistics mailbox command\n"); | ||
2738 | *ret = -EIO; | ||
2739 | return data; | ||
2740 | } | ||
2741 | total_regs = cmd->rsp.num; | ||
2742 | switch (type) { | ||
2743 | case QLC_83XX_STAT_MAC: | ||
2744 | /* fill in MAC tx counters */ | ||
2745 | for (k = 2; k < 28; k += 2) | ||
2746 | data = qlcnic_83xx_copy_stats(cmd, data, k); | ||
2747 | /* skip 24 bytes of reserved area */ | ||
2748 | /* fill in MAC rx counters */ | ||
2749 | for (k += 6; k < 60; k += 2) | ||
2750 | data = qlcnic_83xx_copy_stats(cmd, data, k); | ||
2751 | /* skip 24 bytes of reserved area */ | ||
2752 | /* fill in MAC rx frame stats */ | ||
2753 | for (k += 6; k < 80; k += 2) | ||
2754 | data = qlcnic_83xx_copy_stats(cmd, data, k); | ||
2755 | break; | ||
2756 | case QLC_83XX_STAT_RX: | ||
2757 | for (k = 2; k < 8; k += 2) | ||
2758 | data = qlcnic_83xx_copy_stats(cmd, data, k); | ||
2759 | /* skip 8 bytes of reserved data */ | ||
2760 | for (k += 2; k < 24; k += 2) | ||
2761 | data = qlcnic_83xx_copy_stats(cmd, data, k); | ||
2762 | /* skip 8 bytes containing RE1FBQ error data */ | ||
2763 | for (k += 2; k < total_regs; k += 2) | ||
2764 | data = qlcnic_83xx_copy_stats(cmd, data, k); | ||
2765 | break; | ||
2766 | case QLC_83XX_STAT_TX: | ||
2767 | for (k = 2; k < 10; k += 2) | ||
2768 | data = qlcnic_83xx_copy_stats(cmd, data, k); | ||
2769 | /* skip 8 bytes of reserved data */ | ||
2770 | for (k += 2; k < total_regs; k += 2) | ||
2771 | data = qlcnic_83xx_copy_stats(cmd, data, k); | ||
2772 | break; | ||
2773 | default: | ||
2774 | dev_warn(&adapter->pdev->dev, "Unknown get statistics mode\n"); | ||
2775 | *ret = -EIO; | ||
2776 | } | ||
2777 | return data; | ||
2778 | } | ||
2779 | |||
2780 | void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data) | ||
2781 | { | ||
2782 | struct qlcnic_cmd_args cmd; | ||
2783 | int ret = 0; | ||
2784 | |||
2785 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_STATISTICS); | ||
2786 | /* Get Tx stats */ | ||
2787 | cmd.req.arg[1] = BIT_1 | (adapter->tx_ring->ctx_id << 16); | ||
2788 | cmd.rsp.num = QLC_83XX_TX_STAT_REGS; | ||
2789 | data = qlcnic_83xx_fill_stats(adapter, &cmd, data, | ||
2790 | QLC_83XX_STAT_TX, &ret); | ||
2791 | if (ret) { | ||
2792 | dev_info(&adapter->pdev->dev, "Error getting MAC stats\n"); | ||
2793 | goto out; | ||
2794 | } | ||
2795 | /* Get MAC stats */ | ||
2796 | cmd.req.arg[1] = BIT_2 | (adapter->portnum << 16); | ||
2797 | cmd.rsp.num = QLC_83XX_MAC_STAT_REGS; | ||
2798 | memset(cmd.rsp.arg, 0, sizeof(u32) * cmd.rsp.num); | ||
2799 | data = qlcnic_83xx_fill_stats(adapter, &cmd, data, | ||
2800 | QLC_83XX_STAT_MAC, &ret); | ||
2801 | if (ret) { | ||
2802 | dev_info(&adapter->pdev->dev, | ||
2803 | "Error getting Rx stats\n"); | ||
2804 | goto out; | ||
2805 | } | ||
2806 | /* Get Rx stats */ | ||
2807 | cmd.req.arg[1] = adapter->recv_ctx->context_id << 16; | ||
2808 | cmd.rsp.num = QLC_83XX_RX_STAT_REGS; | ||
2809 | memset(cmd.rsp.arg, 0, sizeof(u32) * cmd.rsp.num); | ||
2810 | data = qlcnic_83xx_fill_stats(adapter, &cmd, data, | ||
2811 | QLC_83XX_STAT_RX, &ret); | ||
2812 | if (ret) | ||
2813 | dev_info(&adapter->pdev->dev, | ||
2814 | "Error getting Tx stats\n"); | ||
2815 | out: | ||
2816 | qlcnic_free_mbx_args(&cmd); | ||
2817 | } | ||
2818 | |||
2819 | int qlcnic_83xx_reg_test(struct qlcnic_adapter *adapter) | ||
2820 | { | ||
2821 | u32 major, minor, sub; | ||
2822 | |||
2823 | major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR); | ||
2824 | minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR); | ||
2825 | sub = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB); | ||
2826 | |||
2827 | if (adapter->fw_version != QLCNIC_VERSION_CODE(major, minor, sub)) { | ||
2828 | dev_info(&adapter->pdev->dev, "%s: Reg test failed\n", | ||
2829 | __func__); | ||
2830 | return 1; | ||
2831 | } | ||
2832 | return 0; | ||
2833 | } | ||
2834 | |||
2835 | int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *adapter) | ||
2836 | { | ||
2837 | return (ARRAY_SIZE(qlcnic_83xx_ext_reg_tbl) * | ||
2838 | sizeof(adapter->ahw->ext_reg_tbl)) + | ||
2839 | (ARRAY_SIZE(qlcnic_83xx_reg_tbl) + | ||
2840 | sizeof(adapter->ahw->reg_tbl)); | ||
2841 | } | ||
2842 | |||
2843 | int qlcnic_83xx_get_registers(struct qlcnic_adapter *adapter, u32 *regs_buff) | ||
2844 | { | ||
2845 | int i, j = 0; | ||
2846 | |||
2847 | for (i = QLCNIC_DEV_INFO_SIZE + 1; | ||
2848 | j < ARRAY_SIZE(qlcnic_83xx_reg_tbl); i++, j++) | ||
2849 | regs_buff[i] = QLC_SHARED_REG_RD32(adapter, j); | ||
2850 | |||
2851 | for (j = 0; j < ARRAY_SIZE(qlcnic_83xx_ext_reg_tbl); j++) | ||
2852 | regs_buff[i++] = QLCRDX(adapter->ahw, j); | ||
2853 | return i; | ||
2854 | } | ||
2855 | |||
2856 | int qlcnic_83xx_interrupt_test(struct net_device *netdev) | ||
2857 | { | ||
2858 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
2859 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2860 | struct qlcnic_cmd_args cmd; | ||
2861 | u32 data; | ||
2862 | u16 intrpt_id, id; | ||
2863 | u8 val; | ||
2864 | int ret, max_sds_rings = adapter->max_sds_rings; | ||
2865 | |||
2866 | if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) | ||
2867 | return -EIO; | ||
2868 | |||
2869 | ret = qlcnic_83xx_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST); | ||
2870 | if (ret) | ||
2871 | goto fail_diag_irq; | ||
2872 | |||
2873 | ahw->diag_cnt = 0; | ||
2874 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST); | ||
2875 | |||
2876 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
2877 | intrpt_id = ahw->intr_tbl[0].id; | ||
2878 | else | ||
2879 | intrpt_id = QLCRDX(ahw, QLCNIC_DEF_INT_ID); | ||
2880 | |||
2881 | cmd.req.arg[1] = 1; | ||
2882 | cmd.req.arg[2] = intrpt_id; | ||
2883 | cmd.req.arg[3] = BIT_0; | ||
2884 | |||
2885 | ret = qlcnic_issue_cmd(adapter, &cmd); | ||
2886 | data = cmd.rsp.arg[2]; | ||
2887 | id = LSW(data); | ||
2888 | val = LSB(MSW(data)); | ||
2889 | if (id != intrpt_id) | ||
2890 | dev_info(&adapter->pdev->dev, | ||
2891 | "Interrupt generated: 0x%x, requested:0x%x\n", | ||
2892 | id, intrpt_id); | ||
2893 | if (val) | ||
2894 | dev_err(&adapter->pdev->dev, | ||
2895 | "Interrupt test error: 0x%x\n", val); | ||
2896 | if (ret) | ||
2897 | goto done; | ||
2898 | |||
2899 | msleep(20); | ||
2900 | ret = !ahw->diag_cnt; | ||
2901 | |||
2902 | done: | ||
2903 | qlcnic_free_mbx_args(&cmd); | ||
2904 | qlcnic_83xx_diag_free_res(netdev, max_sds_rings); | ||
2905 | |||
2906 | fail_diag_irq: | ||
2907 | adapter->max_sds_rings = max_sds_rings; | ||
2908 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
2909 | return ret; | ||
2910 | } | ||
2911 | |||
2912 | void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *adapter, | ||
2913 | struct ethtool_pauseparam *pause) | ||
2914 | { | ||
2915 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2916 | int status = 0; | ||
2917 | u32 config; | ||
2918 | |||
2919 | status = qlcnic_83xx_get_port_config(adapter); | ||
2920 | if (status) { | ||
2921 | dev_err(&adapter->pdev->dev, | ||
2922 | "%s: Get Pause Config failed\n", __func__); | ||
2923 | return; | ||
2924 | } | ||
2925 | config = ahw->port_config; | ||
2926 | if (config & QLC_83XX_CFG_STD_PAUSE) { | ||
2927 | if (config & QLC_83XX_CFG_STD_TX_PAUSE) | ||
2928 | pause->tx_pause = 1; | ||
2929 | if (config & QLC_83XX_CFG_STD_RX_PAUSE) | ||
2930 | pause->rx_pause = 1; | ||
2931 | } | ||
2932 | |||
2933 | if (QLC_83XX_AUTONEG(config)) | ||
2934 | pause->autoneg = 1; | ||
2935 | } | ||
2936 | |||
2937 | int qlcnic_83xx_set_pauseparam(struct qlcnic_adapter *adapter, | ||
2938 | struct ethtool_pauseparam *pause) | ||
2939 | { | ||
2940 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2941 | int status = 0; | ||
2942 | u32 config; | ||
2943 | |||
2944 | status = qlcnic_83xx_get_port_config(adapter); | ||
2945 | if (status) { | ||
2946 | dev_err(&adapter->pdev->dev, | ||
2947 | "%s: Get Pause Config failed.\n", __func__); | ||
2948 | return status; | ||
2949 | } | ||
2950 | config = ahw->port_config; | ||
2951 | |||
2952 | if (ahw->port_type == QLCNIC_GBE) { | ||
2953 | if (pause->autoneg) | ||
2954 | ahw->port_config |= QLC_83XX_ENABLE_AUTONEG; | ||
2955 | if (!pause->autoneg) | ||
2956 | ahw->port_config &= ~QLC_83XX_ENABLE_AUTONEG; | ||
2957 | } else if ((ahw->port_type == QLCNIC_XGBE) && (pause->autoneg)) { | ||
2958 | return -EOPNOTSUPP; | ||
2959 | } | ||
2960 | |||
2961 | if (!(config & QLC_83XX_CFG_STD_PAUSE)) | ||
2962 | ahw->port_config |= QLC_83XX_CFG_STD_PAUSE; | ||
2963 | |||
2964 | if (pause->rx_pause && pause->tx_pause) { | ||
2965 | ahw->port_config |= QLC_83XX_CFG_STD_TX_RX_PAUSE; | ||
2966 | } else if (pause->rx_pause && !pause->tx_pause) { | ||
2967 | ahw->port_config &= ~QLC_83XX_CFG_STD_TX_PAUSE; | ||
2968 | ahw->port_config |= QLC_83XX_CFG_STD_RX_PAUSE; | ||
2969 | } else if (pause->tx_pause && !pause->rx_pause) { | ||
2970 | ahw->port_config &= ~QLC_83XX_CFG_STD_RX_PAUSE; | ||
2971 | ahw->port_config |= QLC_83XX_CFG_STD_TX_PAUSE; | ||
2972 | } else if (!pause->rx_pause && !pause->tx_pause) { | ||
2973 | ahw->port_config &= ~QLC_83XX_CFG_STD_TX_RX_PAUSE; | ||
2974 | } | ||
2975 | status = qlcnic_83xx_set_port_config(adapter); | ||
2976 | if (status) { | ||
2977 | dev_err(&adapter->pdev->dev, | ||
2978 | "%s: Set Pause Config failed.\n", __func__); | ||
2979 | ahw->port_config = config; | ||
2980 | } | ||
2981 | return status; | ||
2982 | } | ||
2983 | |||
2984 | static int qlcnic_83xx_read_flash_status_reg(struct qlcnic_adapter *adapter) | ||
2985 | { | ||
2986 | int ret; | ||
2987 | |||
2988 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_ADDR, | ||
2989 | QLC_83XX_FLASH_OEM_READ_SIG); | ||
2990 | qlcnic_83xx_wrt_reg_indirect(adapter, QLC_83XX_FLASH_CONTROL, | ||
2991 | QLC_83XX_FLASH_READ_CTRL); | ||
2992 | ret = qlcnic_83xx_poll_flash_status_reg(adapter); | ||
2993 | if (ret) | ||
2994 | return -EIO; | ||
2995 | |||
2996 | ret = qlcnic_83xx_rd_reg_indirect(adapter, QLC_83XX_FLASH_RDDATA); | ||
2997 | return ret & 0xFF; | ||
2998 | } | ||
2999 | |||
3000 | int qlcnic_83xx_flash_test(struct qlcnic_adapter *adapter) | ||
3001 | { | ||
3002 | int status; | ||
3003 | |||
3004 | status = qlcnic_83xx_read_flash_status_reg(adapter); | ||
3005 | if (status == -EIO) { | ||
3006 | dev_info(&adapter->pdev->dev, "%s: EEPROM test failed.\n", | ||
3007 | __func__); | ||
3008 | return 1; | ||
3009 | } | ||
3010 | return 0; | ||
3011 | } | ||
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..61f81f6c84a9 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h | |||
@@ -0,0 +1,438 @@ | |||
1 | /* | ||
2 | * QLogic qlcnic NIC Driver | ||
3 | * Copyright (c) 2009-2013 QLogic Corporation | ||
4 | * | ||
5 | * See LICENSE.qlcnic for copyright and licensing details. | ||
6 | */ | ||
7 | |||
8 | #ifndef __QLCNIC_83XX_HW_H | ||
9 | #define __QLCNIC_83XX_HW_H | ||
10 | |||
11 | #include <linux/types.h> | ||
12 | #include <linux/etherdevice.h> | ||
13 | #include "qlcnic_hw.h" | ||
14 | |||
15 | /* Directly mapped registers */ | ||
16 | #define QLC_83XX_CRB_WIN_BASE 0x3800 | ||
17 | #define QLC_83XX_CRB_WIN_FUNC(f) (QLC_83XX_CRB_WIN_BASE+((f)*4)) | ||
18 | #define QLC_83XX_SEM_LOCK_BASE 0x3840 | ||
19 | #define QLC_83XX_SEM_UNLOCK_BASE 0x3844 | ||
20 | #define QLC_83XX_SEM_LOCK_FUNC(f) (QLC_83XX_SEM_LOCK_BASE+((f)*8)) | ||
21 | #define QLC_83XX_SEM_UNLOCK_FUNC(f) (QLC_83XX_SEM_UNLOCK_BASE+((f)*8)) | ||
22 | #define QLC_83XX_LINK_STATE(f) (0x3698+((f) > 7 ? 4 : 0)) | ||
23 | #define QLC_83XX_LINK_SPEED(f) (0x36E0+(((f) >> 2) * 4)) | ||
24 | #define QLC_83XX_LINK_SPEED_FACTOR 10 | ||
25 | #define QLC_83xx_FUNC_VAL(v, f) ((v) & (1 << (f * 4))) | ||
26 | #define QLC_83XX_INTX_PTR 0x38C0 | ||
27 | #define QLC_83XX_INTX_TRGR 0x38C4 | ||
28 | #define QLC_83XX_INTX_MASK 0x38C8 | ||
29 | |||
30 | #define QLC_83XX_DRV_LOCK_WAIT_COUNTER 100 | ||
31 | #define QLC_83XX_DRV_LOCK_WAIT_DELAY 20 | ||
32 | #define QLC_83XX_NEED_DRV_LOCK_RECOVERY 1 | ||
33 | #define QLC_83XX_DRV_LOCK_RECOVERY_IN_PROGRESS 2 | ||
34 | #define QLC_83XX_MAX_DRV_LOCK_RECOVERY_ATTEMPT 3 | ||
35 | #define QLC_83XX_DRV_LOCK_RECOVERY_DELAY 200 | ||
36 | #define QLC_83XX_DRV_LOCK_RECOVERY_STATUS_MASK 0x3 | ||
37 | |||
38 | #define QLC_83XX_NO_NIC_RESOURCE 0x5 | ||
39 | #define QLC_83XX_MAC_PRESENT 0xC | ||
40 | #define QLC_83XX_MAC_ABSENT 0xD | ||
41 | |||
42 | |||
43 | #define QLC_83XX_FLASH_SECTOR_SIZE (64 * 1024) | ||
44 | |||
45 | /* PEG status definitions */ | ||
46 | #define QLC_83XX_CMDPEG_COMPLETE 0xff01 | ||
47 | #define QLC_83XX_VALID_INTX_BIT30(val) ((val) & BIT_30) | ||
48 | #define QLC_83XX_VALID_INTX_BIT31(val) ((val) & BIT_31) | ||
49 | #define QLC_83XX_INTX_FUNC(val) ((val) & 0xFF) | ||
50 | #define QLC_83XX_LEGACY_INTX_MAX_RETRY 100 | ||
51 | #define QLC_83XX_LEGACY_INTX_DELAY 4 | ||
52 | #define QLC_83XX_REG_DESC 1 | ||
53 | #define QLC_83XX_LRO_DESC 2 | ||
54 | #define QLC_83XX_CTRL_DESC 3 | ||
55 | #define QLC_83XX_FW_CAPABILITY_TSO BIT_6 | ||
56 | #define QLC_83XX_FW_CAP_LRO_MSS BIT_17 | ||
57 | #define QLC_83XX_HOST_RDS_MODE_UNIQUE 0 | ||
58 | #define QLC_83XX_HOST_SDS_MBX_IDX 8 | ||
59 | |||
60 | #define QLCNIC_HOST_RDS_MBX_IDX 88 | ||
61 | #define QLCNIC_MAX_RING_SETS 8 | ||
62 | |||
63 | /* Pause control registers */ | ||
64 | #define QLC_83XX_SRE_SHIM_REG 0x0D200284 | ||
65 | #define QLC_83XX_PORT0_THRESHOLD 0x0B2003A4 | ||
66 | #define QLC_83XX_PORT1_THRESHOLD 0x0B2013A4 | ||
67 | #define QLC_83XX_PORT0_TC_MC_REG 0x0B200388 | ||
68 | #define QLC_83XX_PORT1_TC_MC_REG 0x0B201388 | ||
69 | #define QLC_83XX_PORT0_TC_STATS 0x0B20039C | ||
70 | #define QLC_83XX_PORT1_TC_STATS 0x0B20139C | ||
71 | #define QLC_83XX_PORT2_IFB_THRESHOLD 0x0B200704 | ||
72 | #define QLC_83XX_PORT3_IFB_THRESHOLD 0x0B201704 | ||
73 | |||
74 | /* Peg PC status registers */ | ||
75 | #define QLC_83XX_CRB_PEG_NET_0 0x3400003c | ||
76 | #define QLC_83XX_CRB_PEG_NET_1 0x3410003c | ||
77 | #define QLC_83XX_CRB_PEG_NET_2 0x3420003c | ||
78 | #define QLC_83XX_CRB_PEG_NET_3 0x3430003c | ||
79 | #define QLC_83XX_CRB_PEG_NET_4 0x34b0003c | ||
80 | |||
81 | /* Firmware image definitions */ | ||
82 | #define QLC_83XX_BOOTLOADER_FLASH_ADDR 0x10000 | ||
83 | #define QLC_83XX_FW_FILE_NAME "83xx_fw.bin" | ||
84 | #define QLC_83XX_BOOT_FROM_FLASH 0 | ||
85 | #define QLC_83XX_BOOT_FROM_FILE 0x12345678 | ||
86 | |||
87 | #define QLC_83XX_MAX_RESET_SEQ_ENTRIES 16 | ||
88 | |||
89 | struct qlcnic_intrpt_config { | ||
90 | u8 type; | ||
91 | u8 enabled; | ||
92 | u16 id; | ||
93 | u32 src; | ||
94 | }; | ||
95 | |||
96 | struct qlcnic_macvlan_mbx { | ||
97 | u8 mac[ETH_ALEN]; | ||
98 | u16 vlan; | ||
99 | }; | ||
100 | |||
101 | struct qlc_83xx_fw_info { | ||
102 | const struct firmware *fw; | ||
103 | u16 major_fw_version; | ||
104 | u8 minor_fw_version; | ||
105 | u8 sub_fw_version; | ||
106 | u8 fw_build_num; | ||
107 | u8 load_from_file; | ||
108 | }; | ||
109 | |||
110 | struct qlc_83xx_reset { | ||
111 | struct qlc_83xx_reset_hdr *hdr; | ||
112 | int seq_index; | ||
113 | int seq_error; | ||
114 | int array_index; | ||
115 | u32 array[QLC_83XX_MAX_RESET_SEQ_ENTRIES]; | ||
116 | u8 *buff; | ||
117 | u8 *stop_offset; | ||
118 | u8 *start_offset; | ||
119 | u8 *init_offset; | ||
120 | u8 seq_end; | ||
121 | u8 template_end; | ||
122 | }; | ||
123 | |||
124 | #define QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY 0x1 | ||
125 | #define QLC_83XX_IDC_GRACEFULL_RESET 0x2 | ||
126 | #define QLC_83XX_IDC_TIMESTAMP 0 | ||
127 | #define QLC_83XX_IDC_DURATION 1 | ||
128 | #define QLC_83XX_IDC_INIT_TIMEOUT_SECS 30 | ||
129 | #define QLC_83XX_IDC_RESET_ACK_TIMEOUT_SECS 10 | ||
130 | #define QLC_83XX_IDC_RESET_TIMEOUT_SECS 10 | ||
131 | #define QLC_83XX_IDC_QUIESCE_ACK_TIMEOUT_SECS 20 | ||
132 | #define QLC_83XX_IDC_FW_POLL_DELAY (1 * HZ) | ||
133 | #define QLC_83XX_IDC_FW_FAIL_THRESH 2 | ||
134 | #define QLC_83XX_IDC_MAX_FUNC_PER_PARTITION_INFO 8 | ||
135 | #define QLC_83XX_IDC_MAX_CNA_FUNCTIONS 16 | ||
136 | #define QLC_83XX_IDC_MAJOR_VERSION 1 | ||
137 | #define QLC_83XX_IDC_MINOR_VERSION 0 | ||
138 | #define QLC_83XX_IDC_FLASH_PARAM_ADDR 0x3e8020 | ||
139 | |||
140 | struct qlcnic_adapter; | ||
141 | struct qlc_83xx_idc { | ||
142 | int (*state_entry) (struct qlcnic_adapter *); | ||
143 | u64 sec_counter; | ||
144 | u64 delay; | ||
145 | unsigned long status; | ||
146 | int err_code; | ||
147 | int collect_dump; | ||
148 | u8 curr_state; | ||
149 | u8 prev_state; | ||
150 | u8 vnic_state; | ||
151 | u8 vnic_wait_limit; | ||
152 | u8 quiesce_req; | ||
153 | char **name; | ||
154 | }; | ||
155 | |||
156 | #define QLCNIC_MBX_RSP(reg) LSW(reg) | ||
157 | #define QLCNIC_MBX_NUM_REGS(reg) (MSW(reg) & 0x1FF) | ||
158 | #define QLCNIC_MBX_STATUS(reg) (((reg) >> 25) & 0x7F) | ||
159 | #define QLCNIC_MBX_HOST(ahw, i) ((ahw)->pci_base0 + ((i) * 4)) | ||
160 | #define QLCNIC_MBX_FW(ahw, i) ((ahw)->pci_base0 + 0x800 + ((i) * 4)) | ||
161 | |||
162 | /* Mailbox process AEN count */ | ||
163 | #define QLC_83XX_IDC_COMP_AEN 3 | ||
164 | #define QLC_83XX_MBX_AEN_CNT 5 | ||
165 | #define QLC_83XX_MODULE_LOADED 1 | ||
166 | #define QLC_83XX_MBX_READY 2 | ||
167 | #define QLC_83XX_MBX_AEN_ACK 3 | ||
168 | #define QLC_83XX_SFP_PRESENT(data) ((data) & 3) | ||
169 | #define QLC_83XX_SFP_ERR(data) (((data) >> 2) & 3) | ||
170 | #define QLC_83XX_SFP_MODULE_TYPE(data) (((data) >> 4) & 0x1F) | ||
171 | #define QLC_83XX_SFP_CU_LENGTH(data) (LSB((data) >> 16)) | ||
172 | #define QLC_83XX_SFP_TX_FAULT(data) ((data) & BIT_10) | ||
173 | #define QLC_83XX_SFP_10G_CAPABLE(data) ((data) & BIT_11) | ||
174 | #define QLC_83XX_LINK_STATS(data) ((data) & BIT_0) | ||
175 | #define QLC_83XX_CURRENT_LINK_SPEED(data) (((data) >> 3) & 7) | ||
176 | #define QLC_83XX_LINK_PAUSE(data) (((data) >> 6) & 3) | ||
177 | #define QLC_83XX_LINK_LB(data) (((data) >> 8) & 7) | ||
178 | #define QLC_83XX_LINK_FEC(data) ((data) & BIT_12) | ||
179 | #define QLC_83XX_LINK_EEE(data) ((data) & BIT_13) | ||
180 | #define QLC_83XX_DCBX(data) (((data) >> 28) & 7) | ||
181 | #define QLC_83XX_AUTONEG(data) ((data) & BIT_15) | ||
182 | #define QLC_83XX_CFG_STD_PAUSE (1 << 5) | ||
183 | #define QLC_83XX_CFG_STD_TX_PAUSE (1 << 20) | ||
184 | #define QLC_83XX_CFG_STD_RX_PAUSE (2 << 20) | ||
185 | #define QLC_83XX_CFG_STD_TX_RX_PAUSE (3 << 20) | ||
186 | #define QLC_83XX_ENABLE_AUTONEG (1 << 15) | ||
187 | #define QLC_83XX_CFG_LOOPBACK_HSS (2 << 1) | ||
188 | #define QLC_83XX_CFG_LOOPBACK_PHY (3 << 1) | ||
189 | #define QLC_83XX_CFG_LOOPBACK_EXT (4 << 1) | ||
190 | |||
191 | /* LED configuration settings */ | ||
192 | #define QLC_83XX_ENABLE_BEACON 0xe | ||
193 | #define QLC_83XX_LED_RATE 0xff | ||
194 | #define QLC_83XX_LED_ACT (1 << 10) | ||
195 | #define QLC_83XX_LED_MOD (0 << 13) | ||
196 | #define QLC_83XX_LED_CONFIG (QLC_83XX_LED_RATE | QLC_83XX_LED_ACT | \ | ||
197 | QLC_83XX_LED_MOD) | ||
198 | |||
199 | #define QLC_83XX_10M_LINK 1 | ||
200 | #define QLC_83XX_100M_LINK 2 | ||
201 | #define QLC_83XX_1G_LINK 3 | ||
202 | #define QLC_83XX_10G_LINK 4 | ||
203 | #define QLC_83XX_STAT_TX 3 | ||
204 | #define QLC_83XX_STAT_RX 2 | ||
205 | #define QLC_83XX_STAT_MAC 1 | ||
206 | #define QLC_83XX_TX_STAT_REGS 14 | ||
207 | #define QLC_83XX_RX_STAT_REGS 40 | ||
208 | #define QLC_83XX_MAC_STAT_REGS 80 | ||
209 | |||
210 | #define QLC_83XX_GET_FUNC_PRIVILEGE(VAL, FN) (0x3 & ((VAL) >> (FN * 2))) | ||
211 | #define QLC_83XX_SET_FUNC_OPMODE(VAL, FN) ((VAL) << (FN * 2)) | ||
212 | #define QLC_83XX_DEFAULT_OPMODE 0x55555555 | ||
213 | #define QLC_83XX_PRIVLEGED_FUNC 0x1 | ||
214 | #define QLC_83XX_VIRTUAL_FUNC 0x2 | ||
215 | |||
216 | #define QLC_83XX_LB_MAX_FILTERS 2048 | ||
217 | #define QLC_83XX_LB_BUCKET_SIZE 256 | ||
218 | #define QLC_83XX_MINIMUM_VECTOR 3 | ||
219 | |||
220 | #define QLC_83XX_GET_FUNC_MODE_FROM_NPAR_INFO(val) (val & 0x80000000) | ||
221 | #define QLC_83XX_GET_LRO_CAPABILITY(val) (val & 0x20) | ||
222 | #define QLC_83XX_GET_LSO_CAPABILITY(val) (val & 0x40) | ||
223 | #define QLC_83XX_GET_LSO_CAPABILITY(val) (val & 0x40) | ||
224 | #define QLC_83XX_GET_HW_LRO_CAPABILITY(val) (val & 0x400) | ||
225 | #define QLC_83XX_GET_VLAN_ALIGN_CAPABILITY(val) (val & 0x4000) | ||
226 | #define QLC_83XX_GET_FW_LRO_MSS_CAPABILITY(val) (val & 0x20000) | ||
227 | #define QLC_83XX_VIRTUAL_NIC_MODE 0xFF | ||
228 | #define QLC_83XX_DEFAULT_MODE 0x0 | ||
229 | #define QLCNIC_BRDTYPE_83XX_10G 0x0083 | ||
230 | |||
231 | #define QLC_83XX_FLASH_SPI_STATUS 0x2808E010 | ||
232 | #define QLC_83XX_FLASH_SPI_CONTROL 0x2808E014 | ||
233 | #define QLC_83XX_FLASH_STATUS 0x42100004 | ||
234 | #define QLC_83XX_FLASH_CONTROL 0x42110004 | ||
235 | #define QLC_83XX_FLASH_ADDR 0x42110008 | ||
236 | #define QLC_83XX_FLASH_WRDATA 0x4211000C | ||
237 | #define QLC_83XX_FLASH_RDDATA 0x42110018 | ||
238 | #define QLC_83XX_FLASH_DIRECT_WINDOW 0x42110030 | ||
239 | #define QLC_83XX_FLASH_DIRECT_DATA(DATA) (0x42150000 | (0x0000FFFF&DATA)) | ||
240 | #define QLC_83XX_FLASH_SECTOR_ERASE_CMD 0xdeadbeef | ||
241 | #define QLC_83XX_FLASH_WRITE_CMD 0xdacdacda | ||
242 | #define QLC_83XX_FLASH_BULK_WRITE_CMD 0xcadcadca | ||
243 | #define QLC_83XX_FLASH_READ_RETRY_COUNT 5000 | ||
244 | #define QLC_83XX_FLASH_STATUS_READY 0x6 | ||
245 | #define QLC_83XX_FLASH_BULK_WRITE_MIN 2 | ||
246 | #define QLC_83XX_FLASH_BULK_WRITE_MAX 64 | ||
247 | #define QLC_83XX_FLASH_STATUS_REG_POLL_DELAY 1 | ||
248 | #define QLC_83XX_ERASE_MODE 1 | ||
249 | #define QLC_83XX_WRITE_MODE 2 | ||
250 | #define QLC_83XX_BULK_WRITE_MODE 3 | ||
251 | #define QLC_83XX_FLASH_FDT_WRITE_DEF_SIG 0xFD0100 | ||
252 | #define QLC_83XX_FLASH_FDT_ERASE_DEF_SIG 0xFD0300 | ||
253 | #define QLC_83XX_FLASH_FDT_READ_MFG_ID_VAL 0xFD009F | ||
254 | #define QLC_83XX_FLASH_OEM_ERASE_SIG 0xFD03D8 | ||
255 | #define QLC_83XX_FLASH_OEM_WRITE_SIG 0xFD0101 | ||
256 | #define QLC_83XX_FLASH_OEM_READ_SIG 0xFD0005 | ||
257 | #define QLC_83XX_FLASH_ADDR_TEMP_VAL 0x00800000 | ||
258 | #define QLC_83XX_FLASH_ADDR_SECOND_TEMP_VAL 0x00800001 | ||
259 | #define QLC_83XX_FLASH_WRDATA_DEF 0x0 | ||
260 | #define QLC_83XX_FLASH_READ_CTRL 0x3F | ||
261 | #define QLC_83XX_FLASH_SPI_CTRL 0x4 | ||
262 | #define QLC_83XX_FLASH_FIRST_ERASE_MS_VAL 0x2 | ||
263 | #define QLC_83XX_FLASH_SECOND_ERASE_MS_VAL 0x5 | ||
264 | #define QLC_83XX_FLASH_LAST_ERASE_MS_VAL 0x3D | ||
265 | #define QLC_83XX_FLASH_FIRST_MS_PATTERN 0x43 | ||
266 | #define QLC_83XX_FLASH_SECOND_MS_PATTERN 0x7F | ||
267 | #define QLC_83XX_FLASH_LAST_MS_PATTERN 0x7D | ||
268 | #define QLC_83xx_FLASH_MAX_WAIT_USEC 100 | ||
269 | #define QLC_83XX_FLASH_LOCK_TIMEOUT 10000 | ||
270 | |||
271 | /* Additional registers in 83xx */ | ||
272 | enum qlc_83xx_ext_regs { | ||
273 | QLCNIC_GLOBAL_RESET = 0, | ||
274 | QLCNIC_WILDCARD, | ||
275 | QLCNIC_INFORMANT, | ||
276 | QLCNIC_HOST_MBX_CTRL, | ||
277 | QLCNIC_FW_MBX_CTRL, | ||
278 | QLCNIC_BOOTLOADER_ADDR, | ||
279 | QLCNIC_BOOTLOADER_SIZE, | ||
280 | QLCNIC_FW_IMAGE_ADDR, | ||
281 | QLCNIC_MBX_INTR_ENBL, | ||
282 | QLCNIC_DEF_INT_MASK, | ||
283 | QLCNIC_DEF_INT_ID, | ||
284 | QLC_83XX_IDC_MAJ_VERSION, | ||
285 | QLC_83XX_IDC_DEV_STATE, | ||
286 | QLC_83XX_IDC_DRV_PRESENCE, | ||
287 | QLC_83XX_IDC_DRV_ACK, | ||
288 | QLC_83XX_IDC_CTRL, | ||
289 | QLC_83XX_IDC_DRV_AUDIT, | ||
290 | QLC_83XX_IDC_MIN_VERSION, | ||
291 | QLC_83XX_RECOVER_DRV_LOCK, | ||
292 | QLC_83XX_IDC_PF_0, | ||
293 | QLC_83XX_IDC_PF_1, | ||
294 | QLC_83XX_IDC_PF_2, | ||
295 | QLC_83XX_IDC_PF_3, | ||
296 | QLC_83XX_IDC_PF_4, | ||
297 | QLC_83XX_IDC_PF_5, | ||
298 | QLC_83XX_IDC_PF_6, | ||
299 | QLC_83XX_IDC_PF_7, | ||
300 | QLC_83XX_IDC_PF_8, | ||
301 | QLC_83XX_IDC_PF_9, | ||
302 | QLC_83XX_IDC_PF_10, | ||
303 | QLC_83XX_IDC_PF_11, | ||
304 | QLC_83XX_IDC_PF_12, | ||
305 | QLC_83XX_IDC_PF_13, | ||
306 | QLC_83XX_IDC_PF_14, | ||
307 | QLC_83XX_IDC_PF_15, | ||
308 | QLC_83XX_IDC_DEV_PARTITION_INFO_1, | ||
309 | QLC_83XX_IDC_DEV_PARTITION_INFO_2, | ||
310 | QLC_83XX_DRV_OP_MODE, | ||
311 | QLC_83XX_VNIC_STATE, | ||
312 | QLC_83XX_DRV_LOCK, | ||
313 | QLC_83XX_DRV_UNLOCK, | ||
314 | QLC_83XX_DRV_LOCK_ID, | ||
315 | QLC_83XX_ASIC_TEMP, | ||
316 | }; | ||
317 | |||
318 | /* 83xx funcitons */ | ||
319 | int qlcnic_83xx_get_fw_version(struct qlcnic_adapter *); | ||
320 | int qlcnic_83xx_mbx_op(struct qlcnic_adapter *, struct qlcnic_cmd_args *); | ||
321 | int qlcnic_83xx_setup_intr(struct qlcnic_adapter *, u8); | ||
322 | void qlcnic_83xx_get_func_no(struct qlcnic_adapter *); | ||
323 | int qlcnic_83xx_cam_lock(struct qlcnic_adapter *); | ||
324 | void qlcnic_83xx_cam_unlock(struct qlcnic_adapter *); | ||
325 | int qlcnic_send_ctrl_op(struct qlcnic_adapter *, struct qlcnic_cmd_args *, u32); | ||
326 | void qlcnic_83xx_add_sysfs(struct qlcnic_adapter *); | ||
327 | void qlcnic_83xx_remove_sysfs(struct qlcnic_adapter *); | ||
328 | void qlcnic_83xx_write_crb(struct qlcnic_adapter *, char *, loff_t, size_t); | ||
329 | void qlcnic_83xx_read_crb(struct qlcnic_adapter *, char *, loff_t, size_t); | ||
330 | int qlcnic_83xx_rd_reg_indirect(struct qlcnic_adapter *, ulong); | ||
331 | int qlcnic_83xx_wrt_reg_indirect(struct qlcnic_adapter *, ulong, u32); | ||
332 | void qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter *, int, u64 []); | ||
333 | int qlcnic_83xx_nic_set_promisc(struct qlcnic_adapter *, u32); | ||
334 | int qlcnic_83xx_set_lb_mode(struct qlcnic_adapter *, u8); | ||
335 | int qlcnic_83xx_clear_lb_mode(struct qlcnic_adapter *, u8); | ||
336 | int qlcnic_83xx_config_hw_lro(struct qlcnic_adapter *, int); | ||
337 | int qlcnic_83xx_config_rss(struct qlcnic_adapter *, int); | ||
338 | int qlcnic_83xx_config_intr_coalesce(struct qlcnic_adapter *); | ||
339 | void qlcnic_83xx_change_l2_filter(struct qlcnic_adapter *, u64 *, __le16); | ||
340 | int qlcnic_83xx_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info *); | ||
341 | int qlcnic_83xx_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *); | ||
342 | void qlcnic_83xx_register_nic_idc_func(struct qlcnic_adapter *, int); | ||
343 | |||
344 | int qlcnic_83xx_napi_add(struct qlcnic_adapter *, struct net_device *); | ||
345 | void qlcnic_83xx_napi_del(struct qlcnic_adapter *); | ||
346 | void qlcnic_83xx_napi_enable(struct qlcnic_adapter *); | ||
347 | void qlcnic_83xx_napi_disable(struct qlcnic_adapter *); | ||
348 | int qlcnic_83xx_config_led(struct qlcnic_adapter *, u32, u32); | ||
349 | void qlcnic_ind_wr(struct qlcnic_adapter *, u32, u32); | ||
350 | int qlcnic_ind_rd(struct qlcnic_adapter *, u32); | ||
351 | int qlcnic_83xx_create_rx_ctx(struct qlcnic_adapter *); | ||
352 | int qlcnic_83xx_create_tx_ctx(struct qlcnic_adapter *, | ||
353 | struct qlcnic_host_tx_ring *, int); | ||
354 | int qlcnic_83xx_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8); | ||
355 | int qlcnic_83xx_setup_link_event(struct qlcnic_adapter *, int); | ||
356 | void qlcnic_83xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *); | ||
357 | int qlcnic_83xx_config_intrpt(struct qlcnic_adapter *, bool); | ||
358 | int qlcnic_83xx_sre_macaddr_change(struct qlcnic_adapter *, u8 *, __le16, u8); | ||
359 | int qlcnic_83xx_get_mac_address(struct qlcnic_adapter *, u8 *); | ||
360 | void qlcnic_83xx_configure_mac(struct qlcnic_adapter *, u8 *, u8, | ||
361 | struct qlcnic_cmd_args *); | ||
362 | int qlcnic_83xx_alloc_mbx_args(struct qlcnic_cmd_args *, | ||
363 | struct qlcnic_adapter *, u32); | ||
364 | void qlcnic_free_mbx_args(struct qlcnic_cmd_args *); | ||
365 | void qlcnic_set_npar_data(struct qlcnic_adapter *, const struct qlcnic_info *, | ||
366 | struct qlcnic_info *); | ||
367 | void qlcnic_83xx_config_intr_coal(struct qlcnic_adapter *); | ||
368 | irqreturn_t qlcnic_83xx_handle_aen(int, void *); | ||
369 | int qlcnic_83xx_get_port_info(struct qlcnic_adapter *); | ||
370 | void qlcnic_83xx_enable_mbx_intrpt(struct qlcnic_adapter *); | ||
371 | irqreturn_t qlcnic_83xx_clear_legacy_intr(struct qlcnic_adapter *); | ||
372 | irqreturn_t qlcnic_83xx_intr(int, void *); | ||
373 | irqreturn_t qlcnic_83xx_tmp_intr(int, void *); | ||
374 | void qlcnic_83xx_enable_intr(struct qlcnic_adapter *, | ||
375 | struct qlcnic_host_sds_ring *); | ||
376 | void qlcnic_83xx_disable_intr(struct qlcnic_adapter *, | ||
377 | struct qlcnic_host_sds_ring *); | ||
378 | void qlcnic_83xx_check_vf(struct qlcnic_adapter *, | ||
379 | const struct pci_device_id *); | ||
380 | void qlcnic_83xx_process_aen(struct qlcnic_adapter *); | ||
381 | int qlcnic_83xx_get_port_config(struct qlcnic_adapter *); | ||
382 | int qlcnic_83xx_set_port_config(struct qlcnic_adapter *); | ||
383 | int qlcnic_enable_eswitch(struct qlcnic_adapter *, u8, u8); | ||
384 | int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *); | ||
385 | int qlcnic_83xx_config_default_opmode(struct qlcnic_adapter *); | ||
386 | int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *); | ||
387 | void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *); | ||
388 | void qlcnic_83xx_register_map(struct qlcnic_hardware_context *); | ||
389 | void qlcnic_83xx_idc_aen_work(struct work_struct *); | ||
390 | void qlcnic_83xx_config_ipaddr(struct qlcnic_adapter *, __be32, int); | ||
391 | |||
392 | int qlcnic_83xx_erase_flash_sector(struct qlcnic_adapter *, u32); | ||
393 | int qlcnic_83xx_flash_bulk_write(struct qlcnic_adapter *, u32, u32 *, int); | ||
394 | int qlcnic_83xx_flash_write32(struct qlcnic_adapter *, u32, u32 *); | ||
395 | int qlcnic_83xx_lock_flash(struct qlcnic_adapter *); | ||
396 | void qlcnic_83xx_unlock_flash(struct qlcnic_adapter *); | ||
397 | int qlcnic_83xx_save_flash_status(struct qlcnic_adapter *); | ||
398 | int qlcnic_83xx_restore_flash_status(struct qlcnic_adapter *, int); | ||
399 | int qlcnic_83xx_read_flash_mfg_id(struct qlcnic_adapter *); | ||
400 | int qlcnic_83xx_read_flash_descriptor_table(struct qlcnic_adapter *); | ||
401 | int qlcnic_83xx_flash_read32(struct qlcnic_adapter *, u32, u8 *, int); | ||
402 | int qlcnic_83xx_lockless_flash_read32(struct qlcnic_adapter *, | ||
403 | u32, u8 *, int); | ||
404 | int qlcnic_83xx_init(struct qlcnic_adapter *); | ||
405 | int qlcnic_83xx_idc_ready_state_entry(struct qlcnic_adapter *); | ||
406 | int qlcnic_83xx_check_hw_status(struct qlcnic_adapter *p_dev); | ||
407 | void qlcnic_83xx_idc_poll_dev_state(struct work_struct *); | ||
408 | int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *); | ||
409 | void qlcnic_83xx_idc_exit(struct qlcnic_adapter *); | ||
410 | void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *, u32); | ||
411 | int qlcnic_83xx_lock_driver(struct qlcnic_adapter *); | ||
412 | void qlcnic_83xx_unlock_driver(struct qlcnic_adapter *); | ||
413 | int qlcnic_83xx_set_default_offload_settings(struct qlcnic_adapter *); | ||
414 | int qlcnic_83xx_ms_mem_write128(struct qlcnic_adapter *, u64, u32 *, u32); | ||
415 | int qlcnic_83xx_idc_vnic_pf_entry(struct qlcnic_adapter *); | ||
416 | int qlcnic_83xx_enable_vnic_mode(struct qlcnic_adapter *, int); | ||
417 | int qlcnic_83xx_disable_vnic_mode(struct qlcnic_adapter *, int); | ||
418 | int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *); | ||
419 | int qlcnic_83xx_get_vnic_vport_info(struct qlcnic_adapter *, | ||
420 | struct qlcnic_info *, u8); | ||
421 | int qlcnic_83xx_get_vnic_pf_info(struct qlcnic_adapter *, struct qlcnic_info *); | ||
422 | |||
423 | void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *); | ||
424 | void qlcnic_83xx_get_stats(struct qlcnic_adapter *adapter, u64 *data); | ||
425 | int qlcnic_83xx_get_settings(struct qlcnic_adapter *); | ||
426 | int qlcnic_83xx_set_settings(struct qlcnic_adapter *, struct ethtool_cmd *); | ||
427 | void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *, | ||
428 | struct ethtool_pauseparam *); | ||
429 | int qlcnic_83xx_set_pauseparam(struct qlcnic_adapter *, | ||
430 | struct ethtool_pauseparam *); | ||
431 | int qlcnic_83xx_test_link(struct qlcnic_adapter *); | ||
432 | int qlcnic_83xx_reg_test(struct qlcnic_adapter *); | ||
433 | int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *); | ||
434 | int qlcnic_83xx_get_registers(struct qlcnic_adapter *, u32 *); | ||
435 | int qlcnic_83xx_loopback_test(struct net_device *, u8); | ||
436 | int qlcnic_83xx_interrupt_test(struct net_device *); | ||
437 | int qlcnic_83xx_flash_test(struct qlcnic_adapter *); | ||
438 | #endif | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c new file mode 100644 index 000000000000..5c033f268ca5 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | |||
@@ -0,0 +1,2047 @@ | |||
1 | /* | ||
2 | * QLogic qlcnic NIC Driver | ||
3 | * Copyright (c) 2009-2013 QLogic Corporation | ||
4 | * | ||
5 | * See LICENSE.qlcnic for copyright and licensing details. | ||
6 | */ | ||
7 | |||
8 | #include "qlcnic.h" | ||
9 | #include "qlcnic_hw.h" | ||
10 | |||
11 | /* Reset template definitions */ | ||
12 | #define QLC_83XX_RESTART_TEMPLATE_SIZE 0x2000 | ||
13 | #define QLC_83XX_RESET_TEMPLATE_ADDR 0x4F0000 | ||
14 | #define QLC_83XX_RESET_SEQ_VERSION 0x0101 | ||
15 | |||
16 | #define QLC_83XX_OPCODE_NOP 0x0000 | ||
17 | #define QLC_83XX_OPCODE_WRITE_LIST 0x0001 | ||
18 | #define QLC_83XX_OPCODE_READ_WRITE_LIST 0x0002 | ||
19 | #define QLC_83XX_OPCODE_POLL_LIST 0x0004 | ||
20 | #define QLC_83XX_OPCODE_POLL_WRITE_LIST 0x0008 | ||
21 | #define QLC_83XX_OPCODE_READ_MODIFY_WRITE 0x0010 | ||
22 | #define QLC_83XX_OPCODE_SEQ_PAUSE 0x0020 | ||
23 | #define QLC_83XX_OPCODE_SEQ_END 0x0040 | ||
24 | #define QLC_83XX_OPCODE_TMPL_END 0x0080 | ||
25 | #define QLC_83XX_OPCODE_POLL_READ_LIST 0x0100 | ||
26 | |||
27 | static int qlcnic_83xx_init_default_driver(struct qlcnic_adapter *adapter); | ||
28 | static int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter); | ||
29 | static int qlcnic_83xx_check_heartbeat(struct qlcnic_adapter *p_dev); | ||
30 | static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter); | ||
31 | |||
32 | /* Template header */ | ||
33 | struct qlc_83xx_reset_hdr { | ||
34 | u16 version; | ||
35 | u16 signature; | ||
36 | u16 size; | ||
37 | u16 entries; | ||
38 | u16 hdr_size; | ||
39 | u16 checksum; | ||
40 | u16 init_offset; | ||
41 | u16 start_offset; | ||
42 | } __packed; | ||
43 | |||
44 | /* Command entry header. */ | ||
45 | struct qlc_83xx_entry_hdr { | ||
46 | u16 cmd; | ||
47 | u16 size; | ||
48 | u16 count; | ||
49 | u16 delay; | ||
50 | } __packed; | ||
51 | |||
52 | /* Generic poll command */ | ||
53 | struct qlc_83xx_poll { | ||
54 | u32 mask; | ||
55 | u32 status; | ||
56 | } __packed; | ||
57 | |||
58 | /* Read modify write command */ | ||
59 | struct qlc_83xx_rmw { | ||
60 | u32 mask; | ||
61 | u32 xor_value; | ||
62 | u32 or_value; | ||
63 | u8 shl; | ||
64 | u8 shr; | ||
65 | u8 index_a; | ||
66 | u8 rsvd; | ||
67 | } __packed; | ||
68 | |||
69 | /* Generic command with 2 DWORD */ | ||
70 | struct qlc_83xx_entry { | ||
71 | u32 arg1; | ||
72 | u32 arg2; | ||
73 | } __packed; | ||
74 | |||
75 | /* Generic command with 4 DWORD */ | ||
76 | struct qlc_83xx_quad_entry { | ||
77 | u32 dr_addr; | ||
78 | u32 dr_value; | ||
79 | u32 ar_addr; | ||
80 | u32 ar_value; | ||
81 | } __packed; | ||
82 | static const char *const qlc_83xx_idc_states[] = { | ||
83 | "Unknown", | ||
84 | "Cold", | ||
85 | "Init", | ||
86 | "Ready", | ||
87 | "Need Reset", | ||
88 | "Need Quiesce", | ||
89 | "Failed", | ||
90 | "Quiesce" | ||
91 | }; | ||
92 | |||
93 | /* Device States */ | ||
94 | enum qlcnic_83xx_states { | ||
95 | QLC_83XX_IDC_DEV_UNKNOWN, | ||
96 | QLC_83XX_IDC_DEV_COLD, | ||
97 | QLC_83XX_IDC_DEV_INIT, | ||
98 | QLC_83XX_IDC_DEV_READY, | ||
99 | QLC_83XX_IDC_DEV_NEED_RESET, | ||
100 | QLC_83XX_IDC_DEV_NEED_QUISCENT, | ||
101 | QLC_83XX_IDC_DEV_FAILED, | ||
102 | QLC_83XX_IDC_DEV_QUISCENT | ||
103 | }; | ||
104 | |||
105 | static int | ||
106 | qlcnic_83xx_idc_check_driver_presence_reg(struct qlcnic_adapter *adapter) | ||
107 | { | ||
108 | u32 val; | ||
109 | |||
110 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE); | ||
111 | if ((val & 0xFFFF)) | ||
112 | return 1; | ||
113 | else | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static void qlcnic_83xx_idc_log_state_history(struct qlcnic_adapter *adapter) | ||
118 | { | ||
119 | u32 cur, prev; | ||
120 | cur = adapter->ahw->idc.curr_state; | ||
121 | prev = adapter->ahw->idc.prev_state; | ||
122 | |||
123 | dev_info(&adapter->pdev->dev, | ||
124 | "current state = %s, prev state = %s\n", | ||
125 | adapter->ahw->idc.name[cur], | ||
126 | adapter->ahw->idc.name[prev]); | ||
127 | } | ||
128 | |||
129 | static int qlcnic_83xx_idc_update_audit_reg(struct qlcnic_adapter *adapter, | ||
130 | u8 mode, int lock) | ||
131 | { | ||
132 | u32 val; | ||
133 | int seconds; | ||
134 | |||
135 | if (lock) { | ||
136 | if (qlcnic_83xx_lock_driver(adapter)) | ||
137 | return -EBUSY; | ||
138 | } | ||
139 | |||
140 | val = adapter->portnum & 0xf; | ||
141 | val |= mode << 7; | ||
142 | if (mode) | ||
143 | seconds = jiffies / HZ - adapter->ahw->idc.sec_counter; | ||
144 | else | ||
145 | seconds = jiffies / HZ; | ||
146 | |||
147 | val |= seconds << 8; | ||
148 | QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_AUDIT, val); | ||
149 | adapter->ahw->idc.sec_counter = jiffies / HZ; | ||
150 | |||
151 | if (lock) | ||
152 | qlcnic_83xx_unlock_driver(adapter); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static void qlcnic_83xx_idc_update_minor_version(struct qlcnic_adapter *adapter) | ||
158 | { | ||
159 | u32 val; | ||
160 | |||
161 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_MIN_VERSION); | ||
162 | val = val & ~(0x3 << (adapter->portnum * 2)); | ||
163 | val = val | (QLC_83XX_IDC_MINOR_VERSION << (adapter->portnum * 2)); | ||
164 | QLCWRX(adapter->ahw, QLC_83XX_IDC_MIN_VERSION, val); | ||
165 | } | ||
166 | |||
167 | static int qlcnic_83xx_idc_update_major_version(struct qlcnic_adapter *adapter, | ||
168 | int lock) | ||
169 | { | ||
170 | u32 val; | ||
171 | |||
172 | if (lock) { | ||
173 | if (qlcnic_83xx_lock_driver(adapter)) | ||
174 | return -EBUSY; | ||
175 | } | ||
176 | |||
177 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_MAJ_VERSION); | ||
178 | val = val & ~0xFF; | ||
179 | val = val | QLC_83XX_IDC_MAJOR_VERSION; | ||
180 | QLCWRX(adapter->ahw, QLC_83XX_IDC_MAJ_VERSION, val); | ||
181 | |||
182 | if (lock) | ||
183 | qlcnic_83xx_unlock_driver(adapter); | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static int | ||
189 | qlcnic_83xx_idc_update_drv_presence_reg(struct qlcnic_adapter *adapter, | ||
190 | int status, int lock) | ||
191 | { | ||
192 | u32 val; | ||
193 | |||
194 | if (lock) { | ||
195 | if (qlcnic_83xx_lock_driver(adapter)) | ||
196 | return -EBUSY; | ||
197 | } | ||
198 | |||
199 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE); | ||
200 | |||
201 | if (status) | ||
202 | val = val | (1 << adapter->portnum); | ||
203 | else | ||
204 | val = val & ~(1 << adapter->portnum); | ||
205 | |||
206 | QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE, val); | ||
207 | qlcnic_83xx_idc_update_minor_version(adapter); | ||
208 | |||
209 | if (lock) | ||
210 | qlcnic_83xx_unlock_driver(adapter); | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static int qlcnic_83xx_idc_check_major_version(struct qlcnic_adapter *adapter) | ||
216 | { | ||
217 | u32 val; | ||
218 | u8 version; | ||
219 | |||
220 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_MAJ_VERSION); | ||
221 | version = val & 0xFF; | ||
222 | |||
223 | if (version != QLC_83XX_IDC_MAJOR_VERSION) { | ||
224 | dev_info(&adapter->pdev->dev, | ||
225 | "%s:mismatch. version 0x%x, expected version 0x%x\n", | ||
226 | __func__, version, QLC_83XX_IDC_MAJOR_VERSION); | ||
227 | return -EIO; | ||
228 | } | ||
229 | |||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static int qlcnic_83xx_idc_clear_registers(struct qlcnic_adapter *adapter, | ||
234 | int lock) | ||
235 | { | ||
236 | u32 val; | ||
237 | |||
238 | if (lock) { | ||
239 | if (qlcnic_83xx_lock_driver(adapter)) | ||
240 | return -EBUSY; | ||
241 | } | ||
242 | |||
243 | QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_ACK, 0); | ||
244 | /* Clear gracefull reset bit */ | ||
245 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); | ||
246 | val &= ~QLC_83XX_IDC_GRACEFULL_RESET; | ||
247 | QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val); | ||
248 | |||
249 | if (lock) | ||
250 | qlcnic_83xx_unlock_driver(adapter); | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static int qlcnic_83xx_idc_update_drv_ack_reg(struct qlcnic_adapter *adapter, | ||
256 | int flag, int lock) | ||
257 | { | ||
258 | u32 val; | ||
259 | |||
260 | if (lock) { | ||
261 | if (qlcnic_83xx_lock_driver(adapter)) | ||
262 | return -EBUSY; | ||
263 | } | ||
264 | |||
265 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_ACK); | ||
266 | if (flag) | ||
267 | val = val | (1 << adapter->portnum); | ||
268 | else | ||
269 | val = val & ~(1 << adapter->portnum); | ||
270 | QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_ACK, val); | ||
271 | |||
272 | if (lock) | ||
273 | qlcnic_83xx_unlock_driver(adapter); | ||
274 | |||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static int qlcnic_83xx_idc_check_timeout(struct qlcnic_adapter *adapter, | ||
279 | int time_limit) | ||
280 | { | ||
281 | u64 seconds; | ||
282 | |||
283 | seconds = jiffies / HZ - adapter->ahw->idc.sec_counter; | ||
284 | if (seconds <= time_limit) | ||
285 | return 0; | ||
286 | else | ||
287 | return -EBUSY; | ||
288 | } | ||
289 | |||
290 | /** | ||
291 | * qlcnic_83xx_idc_check_reset_ack_reg | ||
292 | * | ||
293 | * @adapter: adapter structure | ||
294 | * | ||
295 | * Check ACK wait limit and clear the functions which failed to ACK | ||
296 | * | ||
297 | * Return 0 if all functions have acknowledged the reset request. | ||
298 | **/ | ||
299 | static int qlcnic_83xx_idc_check_reset_ack_reg(struct qlcnic_adapter *adapter) | ||
300 | { | ||
301 | int timeout; | ||
302 | u32 ack, presence, val; | ||
303 | |||
304 | timeout = QLC_83XX_IDC_RESET_TIMEOUT_SECS; | ||
305 | ack = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_ACK); | ||
306 | presence = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE); | ||
307 | dev_info(&adapter->pdev->dev, | ||
308 | "%s: ack = 0x%x, presence = 0x%x\n", __func__, ack, presence); | ||
309 | if (!((ack & presence) == presence)) { | ||
310 | if (qlcnic_83xx_idc_check_timeout(adapter, timeout)) { | ||
311 | /* Clear functions which failed to ACK */ | ||
312 | dev_info(&adapter->pdev->dev, | ||
313 | "%s: ACK wait exceeds time limit\n", __func__); | ||
314 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE); | ||
315 | val = val & ~(ack ^ presence); | ||
316 | if (qlcnic_83xx_lock_driver(adapter)) | ||
317 | return -EBUSY; | ||
318 | QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE, val); | ||
319 | dev_info(&adapter->pdev->dev, | ||
320 | "%s: updated drv presence reg = 0x%x\n", | ||
321 | __func__, val); | ||
322 | qlcnic_83xx_unlock_driver(adapter); | ||
323 | return 0; | ||
324 | |||
325 | } else { | ||
326 | return 1; | ||
327 | } | ||
328 | } else { | ||
329 | dev_info(&adapter->pdev->dev, | ||
330 | "%s: Reset ACK received from all functions\n", | ||
331 | __func__); | ||
332 | return 0; | ||
333 | } | ||
334 | } | ||
335 | |||
336 | /** | ||
337 | * qlcnic_83xx_idc_tx_soft_reset | ||
338 | * | ||
339 | * @adapter: adapter structure | ||
340 | * | ||
341 | * Handle context deletion and recreation request from transmit routine | ||
342 | * | ||
343 | * Returns -EBUSY or Success (0) | ||
344 | * | ||
345 | **/ | ||
346 | static int qlcnic_83xx_idc_tx_soft_reset(struct qlcnic_adapter *adapter) | ||
347 | { | ||
348 | struct net_device *netdev = adapter->netdev; | ||
349 | |||
350 | if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) | ||
351 | return -EBUSY; | ||
352 | |||
353 | netif_device_detach(netdev); | ||
354 | qlcnic_down(adapter, netdev); | ||
355 | qlcnic_up(adapter, netdev); | ||
356 | netif_device_attach(netdev); | ||
357 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
358 | dev_err(&adapter->pdev->dev, "%s:\n", __func__); | ||
359 | |||
360 | adapter->netdev->trans_start = jiffies; | ||
361 | |||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | /** | ||
366 | * qlcnic_83xx_idc_detach_driver | ||
367 | * | ||
368 | * @adapter: adapter structure | ||
369 | * Detach net interface, stop TX and cleanup resources before the HW reset. | ||
370 | * Returns: None | ||
371 | * | ||
372 | **/ | ||
373 | static void qlcnic_83xx_idc_detach_driver(struct qlcnic_adapter *adapter) | ||
374 | { | ||
375 | int i; | ||
376 | struct net_device *netdev = adapter->netdev; | ||
377 | |||
378 | netif_device_detach(netdev); | ||
379 | /* Disable mailbox interrupt */ | ||
380 | QLCWRX(adapter->ahw, QLCNIC_MBX_INTR_ENBL, 0); | ||
381 | qlcnic_down(adapter, netdev); | ||
382 | for (i = 0; i < adapter->ahw->num_msix; i++) { | ||
383 | adapter->ahw->intr_tbl[i].id = i; | ||
384 | adapter->ahw->intr_tbl[i].enabled = 0; | ||
385 | adapter->ahw->intr_tbl[i].src = 0; | ||
386 | } | ||
387 | } | ||
388 | |||
389 | /** | ||
390 | * qlcnic_83xx_idc_attach_driver | ||
391 | * | ||
392 | * @adapter: adapter structure | ||
393 | * | ||
394 | * Re-attach and re-enable net interface | ||
395 | * Returns: None | ||
396 | * | ||
397 | **/ | ||
398 | static void qlcnic_83xx_idc_attach_driver(struct qlcnic_adapter *adapter) | ||
399 | { | ||
400 | struct net_device *netdev = adapter->netdev; | ||
401 | |||
402 | if (netif_running(netdev)) { | ||
403 | if (qlcnic_up(adapter, netdev)) | ||
404 | goto done; | ||
405 | qlcnic_restore_indev_addr(netdev, NETDEV_UP); | ||
406 | } | ||
407 | done: | ||
408 | netif_device_attach(netdev); | ||
409 | if (netif_running(netdev)) { | ||
410 | netif_carrier_on(netdev); | ||
411 | netif_wake_queue(netdev); | ||
412 | } | ||
413 | } | ||
414 | |||
415 | static int qlcnic_83xx_idc_enter_failed_state(struct qlcnic_adapter *adapter, | ||
416 | int lock) | ||
417 | { | ||
418 | if (lock) { | ||
419 | if (qlcnic_83xx_lock_driver(adapter)) | ||
420 | return -EBUSY; | ||
421 | } | ||
422 | |||
423 | qlcnic_83xx_idc_clear_registers(adapter, 0); | ||
424 | QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE, QLC_83XX_IDC_DEV_FAILED); | ||
425 | if (lock) | ||
426 | qlcnic_83xx_unlock_driver(adapter); | ||
427 | |||
428 | qlcnic_83xx_idc_log_state_history(adapter); | ||
429 | dev_info(&adapter->pdev->dev, "Device will enter failed state\n"); | ||
430 | |||
431 | return 0; | ||
432 | } | ||
433 | |||
434 | static int qlcnic_83xx_idc_enter_init_state(struct qlcnic_adapter *adapter, | ||
435 | int lock) | ||
436 | { | ||
437 | if (lock) { | ||
438 | if (qlcnic_83xx_lock_driver(adapter)) | ||
439 | return -EBUSY; | ||
440 | } | ||
441 | |||
442 | QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE, QLC_83XX_IDC_DEV_INIT); | ||
443 | |||
444 | if (lock) | ||
445 | qlcnic_83xx_unlock_driver(adapter); | ||
446 | |||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | static int qlcnic_83xx_idc_enter_need_quiesce(struct qlcnic_adapter *adapter, | ||
451 | int lock) | ||
452 | { | ||
453 | if (lock) { | ||
454 | if (qlcnic_83xx_lock_driver(adapter)) | ||
455 | return -EBUSY; | ||
456 | } | ||
457 | |||
458 | QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE, | ||
459 | QLC_83XX_IDC_DEV_NEED_QUISCENT); | ||
460 | |||
461 | if (lock) | ||
462 | qlcnic_83xx_unlock_driver(adapter); | ||
463 | |||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | static int | ||
468 | qlcnic_83xx_idc_enter_need_reset_state(struct qlcnic_adapter *adapter, int lock) | ||
469 | { | ||
470 | if (lock) { | ||
471 | if (qlcnic_83xx_lock_driver(adapter)) | ||
472 | return -EBUSY; | ||
473 | } | ||
474 | |||
475 | QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE, | ||
476 | QLC_83XX_IDC_DEV_NEED_RESET); | ||
477 | |||
478 | if (lock) | ||
479 | qlcnic_83xx_unlock_driver(adapter); | ||
480 | |||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | static int qlcnic_83xx_idc_enter_ready_state(struct qlcnic_adapter *adapter, | ||
485 | int lock) | ||
486 | { | ||
487 | if (lock) { | ||
488 | if (qlcnic_83xx_lock_driver(adapter)) | ||
489 | return -EBUSY; | ||
490 | } | ||
491 | |||
492 | QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE, QLC_83XX_IDC_DEV_READY); | ||
493 | if (lock) | ||
494 | qlcnic_83xx_unlock_driver(adapter); | ||
495 | |||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | /** | ||
500 | * qlcnic_83xx_idc_find_reset_owner_id | ||
501 | * | ||
502 | * @adapter: adapter structure | ||
503 | * | ||
504 | * NIC gets precedence over ISCSI and ISCSI has precedence over FCOE. | ||
505 | * Within the same class, function with lowest PCI ID assumes ownership | ||
506 | * | ||
507 | * Returns: reset owner id or failure indication (-EIO) | ||
508 | * | ||
509 | **/ | ||
510 | static int qlcnic_83xx_idc_find_reset_owner_id(struct qlcnic_adapter *adapter) | ||
511 | { | ||
512 | u32 reg, reg1, reg2, i, j, owner, class; | ||
513 | |||
514 | reg1 = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_PARTITION_INFO_1); | ||
515 | reg2 = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_PARTITION_INFO_2); | ||
516 | owner = QLCNIC_TYPE_NIC; | ||
517 | i = 0; | ||
518 | j = 0; | ||
519 | reg = reg1; | ||
520 | |||
521 | do { | ||
522 | class = (((reg & (0xF << j * 4)) >> j * 4) & 0x3); | ||
523 | if (class == owner) | ||
524 | break; | ||
525 | if (i == (QLC_83XX_IDC_MAX_FUNC_PER_PARTITION_INFO - 1)) { | ||
526 | reg = reg2; | ||
527 | j = 0; | ||
528 | } else { | ||
529 | j++; | ||
530 | } | ||
531 | |||
532 | if (i == (QLC_83XX_IDC_MAX_CNA_FUNCTIONS - 1)) { | ||
533 | if (owner == QLCNIC_TYPE_NIC) | ||
534 | owner = QLCNIC_TYPE_ISCSI; | ||
535 | else if (owner == QLCNIC_TYPE_ISCSI) | ||
536 | owner = QLCNIC_TYPE_FCOE; | ||
537 | else if (owner == QLCNIC_TYPE_FCOE) | ||
538 | return -EIO; | ||
539 | reg = reg1; | ||
540 | j = 0; | ||
541 | i = 0; | ||
542 | } | ||
543 | } while (i++ < QLC_83XX_IDC_MAX_CNA_FUNCTIONS); | ||
544 | |||
545 | return i; | ||
546 | } | ||
547 | |||
548 | static int qlcnic_83xx_idc_restart_hw(struct qlcnic_adapter *adapter, int lock) | ||
549 | { | ||
550 | int ret = 0; | ||
551 | |||
552 | ret = qlcnic_83xx_restart_hw(adapter); | ||
553 | |||
554 | if (ret) { | ||
555 | qlcnic_83xx_idc_enter_failed_state(adapter, lock); | ||
556 | } else { | ||
557 | qlcnic_83xx_idc_clear_registers(adapter, lock); | ||
558 | ret = qlcnic_83xx_idc_enter_ready_state(adapter, lock); | ||
559 | } | ||
560 | |||
561 | return ret; | ||
562 | } | ||
563 | |||
564 | static int qlcnic_83xx_idc_check_fan_failure(struct qlcnic_adapter *adapter) | ||
565 | { | ||
566 | u32 status; | ||
567 | |||
568 | status = QLC_SHARED_REG_RD32(adapter, QLCNIC_PEG_HALT_STATUS1); | ||
569 | |||
570 | if (status & QLCNIC_RCODE_FATAL_ERROR) { | ||
571 | dev_err(&adapter->pdev->dev, | ||
572 | "peg halt status1=0x%x\n", status); | ||
573 | if (QLCNIC_FWERROR_CODE(status) == QLCNIC_FWERROR_FAN_FAILURE) { | ||
574 | dev_err(&adapter->pdev->dev, | ||
575 | "On board active cooling fan failed. " | ||
576 | "Device has been halted.\n"); | ||
577 | dev_err(&adapter->pdev->dev, | ||
578 | "Replace the adapter.\n"); | ||
579 | return -EIO; | ||
580 | } | ||
581 | } | ||
582 | |||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | static int qlcnic_83xx_idc_reattach_driver(struct qlcnic_adapter *adapter) | ||
587 | { | ||
588 | /* register for NIC IDC AEN Events */ | ||
589 | qlcnic_83xx_register_nic_idc_func(adapter, 1); | ||
590 | |||
591 | qlcnic_83xx_enable_mbx_intrpt(adapter); | ||
592 | |||
593 | if (qlcnic_83xx_configure_opmode(adapter)) { | ||
594 | qlcnic_83xx_idc_enter_failed_state(adapter, 1); | ||
595 | return -EIO; | ||
596 | } | ||
597 | |||
598 | if (adapter->nic_ops->init_driver(adapter)) { | ||
599 | qlcnic_83xx_idc_enter_failed_state(adapter, 1); | ||
600 | return -EIO; | ||
601 | } | ||
602 | |||
603 | qlcnic_83xx_idc_attach_driver(adapter); | ||
604 | |||
605 | return 0; | ||
606 | } | ||
607 | |||
608 | static void qlcnic_83xx_idc_update_idc_params(struct qlcnic_adapter *adapter) | ||
609 | { | ||
610 | qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 1); | ||
611 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
612 | set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); | ||
613 | qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1); | ||
614 | set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status); | ||
615 | adapter->ahw->idc.quiesce_req = 0; | ||
616 | adapter->ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY; | ||
617 | adapter->ahw->idc.err_code = 0; | ||
618 | adapter->ahw->idc.collect_dump = 0; | ||
619 | } | ||
620 | |||
621 | /** | ||
622 | * qlcnic_83xx_idc_ready_state_entry | ||
623 | * | ||
624 | * @adapter: adapter structure | ||
625 | * | ||
626 | * Perform ready state initialization, this routine will get invoked only | ||
627 | * once from READY state. | ||
628 | * | ||
629 | * Returns: Error code or Success(0) | ||
630 | * | ||
631 | **/ | ||
632 | int qlcnic_83xx_idc_ready_state_entry(struct qlcnic_adapter *adapter) | ||
633 | { | ||
634 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
635 | |||
636 | if (ahw->idc.prev_state != QLC_83XX_IDC_DEV_READY) { | ||
637 | qlcnic_83xx_idc_update_idc_params(adapter); | ||
638 | /* Re-attach the device if required */ | ||
639 | if ((ahw->idc.prev_state == QLC_83XX_IDC_DEV_NEED_RESET) || | ||
640 | (ahw->idc.prev_state == QLC_83XX_IDC_DEV_INIT)) { | ||
641 | if (qlcnic_83xx_idc_reattach_driver(adapter)) | ||
642 | return -EIO; | ||
643 | } | ||
644 | } | ||
645 | |||
646 | return 0; | ||
647 | } | ||
648 | |||
649 | /** | ||
650 | * qlcnic_83xx_idc_vnic_pf_entry | ||
651 | * | ||
652 | * @adapter: adapter structure | ||
653 | * | ||
654 | * Ensure vNIC mode privileged function starts only after vNIC mode is | ||
655 | * enabled by management function. | ||
656 | * If vNIC mode is ready, start initialization. | ||
657 | * | ||
658 | * Returns: -EIO or 0 | ||
659 | * | ||
660 | **/ | ||
661 | int qlcnic_83xx_idc_vnic_pf_entry(struct qlcnic_adapter *adapter) | ||
662 | { | ||
663 | u32 state; | ||
664 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
665 | |||
666 | /* Privileged function waits till mgmt function enables VNIC mode */ | ||
667 | state = QLCRDX(adapter->ahw, QLC_83XX_VNIC_STATE); | ||
668 | if (state != QLCNIC_DEV_NPAR_OPER) { | ||
669 | if (!ahw->idc.vnic_wait_limit--) { | ||
670 | qlcnic_83xx_idc_enter_failed_state(adapter, 1); | ||
671 | return -EIO; | ||
672 | } | ||
673 | dev_info(&adapter->pdev->dev, "vNIC mode disabled\n"); | ||
674 | return -EIO; | ||
675 | |||
676 | } else { | ||
677 | /* Perform one time initialization from ready state */ | ||
678 | if (ahw->idc.vnic_state != QLCNIC_DEV_NPAR_OPER) { | ||
679 | qlcnic_83xx_idc_update_idc_params(adapter); | ||
680 | |||
681 | /* If the previous state is UNKNOWN, device will be | ||
682 | already attached properly by Init routine*/ | ||
683 | if (ahw->idc.prev_state != QLC_83XX_IDC_DEV_UNKNOWN) { | ||
684 | if (qlcnic_83xx_idc_reattach_driver(adapter)) | ||
685 | return -EIO; | ||
686 | } | ||
687 | adapter->ahw->idc.vnic_state = QLCNIC_DEV_NPAR_OPER; | ||
688 | dev_info(&adapter->pdev->dev, "vNIC mode enabled\n"); | ||
689 | } | ||
690 | } | ||
691 | |||
692 | return 0; | ||
693 | } | ||
694 | |||
695 | static int qlcnic_83xx_idc_unknown_state(struct qlcnic_adapter *adapter) | ||
696 | { | ||
697 | adapter->ahw->idc.err_code = -EIO; | ||
698 | dev_err(&adapter->pdev->dev, | ||
699 | "%s: Device in unknown state\n", __func__); | ||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | /** | ||
704 | * qlcnic_83xx_idc_cold_state | ||
705 | * | ||
706 | * @adapter: adapter structure | ||
707 | * | ||
708 | * If HW is up and running device will enter READY state. | ||
709 | * If firmware image from host needs to be loaded, device is | ||
710 | * forced to start with the file firmware image. | ||
711 | * | ||
712 | * Returns: Error code or Success(0) | ||
713 | * | ||
714 | **/ | ||
715 | static int qlcnic_83xx_idc_cold_state_handler(struct qlcnic_adapter *adapter) | ||
716 | { | ||
717 | qlcnic_83xx_idc_update_drv_presence_reg(adapter, 1, 0); | ||
718 | qlcnic_83xx_idc_update_audit_reg(adapter, 1, 0); | ||
719 | |||
720 | if (qlcnic_load_fw_file) { | ||
721 | qlcnic_83xx_idc_restart_hw(adapter, 0); | ||
722 | } else { | ||
723 | if (qlcnic_83xx_check_hw_status(adapter)) { | ||
724 | qlcnic_83xx_idc_enter_failed_state(adapter, 0); | ||
725 | return -EIO; | ||
726 | } else { | ||
727 | qlcnic_83xx_idc_enter_ready_state(adapter, 0); | ||
728 | } | ||
729 | } | ||
730 | return 0; | ||
731 | } | ||
732 | |||
733 | /** | ||
734 | * qlcnic_83xx_idc_init_state | ||
735 | * | ||
736 | * @adapter: adapter structure | ||
737 | * | ||
738 | * Reset owner will restart the device from this state. | ||
739 | * Device will enter failed state if it remains | ||
740 | * in this state for more than DEV_INIT time limit. | ||
741 | * | ||
742 | * Returns: Error code or Success(0) | ||
743 | * | ||
744 | **/ | ||
745 | static int qlcnic_83xx_idc_init_state(struct qlcnic_adapter *adapter) | ||
746 | { | ||
747 | int timeout, ret = 0; | ||
748 | u32 owner; | ||
749 | |||
750 | timeout = QLC_83XX_IDC_INIT_TIMEOUT_SECS; | ||
751 | if (adapter->ahw->idc.prev_state == QLC_83XX_IDC_DEV_NEED_RESET) { | ||
752 | owner = qlcnic_83xx_idc_find_reset_owner_id(adapter); | ||
753 | if (adapter->ahw->pci_func == owner) | ||
754 | ret = qlcnic_83xx_idc_restart_hw(adapter, 1); | ||
755 | } else { | ||
756 | ret = qlcnic_83xx_idc_check_timeout(adapter, timeout); | ||
757 | return ret; | ||
758 | } | ||
759 | |||
760 | return ret; | ||
761 | } | ||
762 | |||
763 | /** | ||
764 | * qlcnic_83xx_idc_ready_state | ||
765 | * | ||
766 | * @adapter: adapter structure | ||
767 | * | ||
768 | * Perform IDC protocol specicifed actions after monitoring device state and | ||
769 | * events. | ||
770 | * | ||
771 | * Returns: Error code or Success(0) | ||
772 | * | ||
773 | **/ | ||
774 | static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter) | ||
775 | { | ||
776 | u32 val; | ||
777 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
778 | int ret = 0; | ||
779 | |||
780 | /* Perform NIC configuration based ready state entry actions */ | ||
781 | if (ahw->idc.state_entry(adapter)) | ||
782 | return -EIO; | ||
783 | |||
784 | if (qlcnic_check_temp(adapter)) { | ||
785 | if (ahw->temp == QLCNIC_TEMP_PANIC) { | ||
786 | qlcnic_83xx_idc_check_fan_failure(adapter); | ||
787 | dev_err(&adapter->pdev->dev, | ||
788 | "Error: device temperature %d above limits\n", | ||
789 | adapter->ahw->temp); | ||
790 | clear_bit(QLC_83XX_MBX_READY, &ahw->idc.status); | ||
791 | set_bit(__QLCNIC_RESETTING, &adapter->state); | ||
792 | qlcnic_83xx_idc_detach_driver(adapter); | ||
793 | qlcnic_83xx_idc_enter_failed_state(adapter, 1); | ||
794 | return -EIO; | ||
795 | } | ||
796 | } | ||
797 | |||
798 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); | ||
799 | ret = qlcnic_83xx_check_heartbeat(adapter); | ||
800 | if (ret) { | ||
801 | adapter->flags |= QLCNIC_FW_HANG; | ||
802 | if (!(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) { | ||
803 | clear_bit(QLC_83XX_MBX_READY, &ahw->idc.status); | ||
804 | set_bit(__QLCNIC_RESETTING, &adapter->state); | ||
805 | qlcnic_83xx_idc_enter_need_reset_state(adapter, 1); | ||
806 | } | ||
807 | return -EIO; | ||
808 | } | ||
809 | |||
810 | if ((val & QLC_83XX_IDC_GRACEFULL_RESET) || ahw->idc.collect_dump) { | ||
811 | /* Move to need reset state and prepare for reset */ | ||
812 | qlcnic_83xx_idc_enter_need_reset_state(adapter, 1); | ||
813 | return ret; | ||
814 | } | ||
815 | |||
816 | /* Check for soft reset request */ | ||
817 | if (ahw->reset_context && | ||
818 | !(val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY)) { | ||
819 | qlcnic_83xx_idc_tx_soft_reset(adapter); | ||
820 | return ret; | ||
821 | } | ||
822 | |||
823 | /* Move to need quiesce state if requested */ | ||
824 | if (adapter->ahw->idc.quiesce_req) { | ||
825 | qlcnic_83xx_idc_enter_need_quiesce(adapter, 1); | ||
826 | qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1); | ||
827 | return ret; | ||
828 | } | ||
829 | |||
830 | return ret; | ||
831 | } | ||
832 | |||
833 | /** | ||
834 | * qlcnic_83xx_idc_need_reset_state | ||
835 | * | ||
836 | * @adapter: adapter structure | ||
837 | * | ||
838 | * Device will remain in this state until: | ||
839 | * Reset request ACK's are recieved from all the functions | ||
840 | * Wait time exceeds max time limit | ||
841 | * | ||
842 | * Returns: Error code or Success(0) | ||
843 | * | ||
844 | **/ | ||
845 | static int qlcnic_83xx_idc_need_reset_state(struct qlcnic_adapter *adapter) | ||
846 | { | ||
847 | int ret = 0; | ||
848 | |||
849 | if (adapter->ahw->idc.prev_state != QLC_83XX_IDC_DEV_NEED_RESET) { | ||
850 | qlcnic_83xx_idc_update_drv_ack_reg(adapter, 1, 1); | ||
851 | qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1); | ||
852 | set_bit(__QLCNIC_RESETTING, &adapter->state); | ||
853 | clear_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); | ||
854 | if (adapter->ahw->nic_mode == QLC_83XX_VIRTUAL_NIC_MODE) | ||
855 | qlcnic_83xx_disable_vnic_mode(adapter, 1); | ||
856 | qlcnic_83xx_idc_detach_driver(adapter); | ||
857 | } | ||
858 | |||
859 | /* Check ACK from other functions */ | ||
860 | ret = qlcnic_83xx_idc_check_reset_ack_reg(adapter); | ||
861 | if (ret) { | ||
862 | dev_info(&adapter->pdev->dev, | ||
863 | "%s: Waiting for reset ACK\n", __func__); | ||
864 | return 0; | ||
865 | } | ||
866 | |||
867 | /* Transit to INIT state and restart the HW */ | ||
868 | qlcnic_83xx_idc_enter_init_state(adapter, 1); | ||
869 | |||
870 | return ret; | ||
871 | } | ||
872 | |||
873 | static int qlcnic_83xx_idc_need_quiesce_state(struct qlcnic_adapter *adapter) | ||
874 | { | ||
875 | dev_err(&adapter->pdev->dev, "%s: TBD\n", __func__); | ||
876 | return 0; | ||
877 | } | ||
878 | |||
879 | static int qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter) | ||
880 | { | ||
881 | dev_err(&adapter->pdev->dev, "%s: please restart!!\n", __func__); | ||
882 | adapter->ahw->idc.err_code = -EIO; | ||
883 | |||
884 | return 0; | ||
885 | } | ||
886 | |||
887 | static int qlcnic_83xx_idc_quiesce_state(struct qlcnic_adapter *adapter) | ||
888 | { | ||
889 | dev_info(&adapter->pdev->dev, "%s: TBD\n", __func__); | ||
890 | return 0; | ||
891 | } | ||
892 | |||
893 | static int qlcnic_83xx_idc_check_state_validity(struct qlcnic_adapter *adapter, | ||
894 | u32 state) | ||
895 | { | ||
896 | u32 cur, prev, next; | ||
897 | |||
898 | cur = adapter->ahw->idc.curr_state; | ||
899 | prev = adapter->ahw->idc.prev_state; | ||
900 | next = state; | ||
901 | |||
902 | if ((next < QLC_83XX_IDC_DEV_COLD) || | ||
903 | (next > QLC_83XX_IDC_DEV_QUISCENT)) { | ||
904 | dev_err(&adapter->pdev->dev, | ||
905 | "%s: curr %d, prev %d, next state %d is invalid\n", | ||
906 | __func__, cur, prev, state); | ||
907 | return 1; | ||
908 | } | ||
909 | |||
910 | if ((cur == QLC_83XX_IDC_DEV_UNKNOWN) && | ||
911 | (prev == QLC_83XX_IDC_DEV_UNKNOWN)) { | ||
912 | if ((next != QLC_83XX_IDC_DEV_COLD) && | ||
913 | (next != QLC_83XX_IDC_DEV_READY)) { | ||
914 | dev_err(&adapter->pdev->dev, | ||
915 | "%s: failed, cur %d prev %d next %d\n", | ||
916 | __func__, cur, prev, next); | ||
917 | return 1; | ||
918 | } | ||
919 | } | ||
920 | |||
921 | if (next == QLC_83XX_IDC_DEV_INIT) { | ||
922 | if ((prev != QLC_83XX_IDC_DEV_INIT) && | ||
923 | (prev != QLC_83XX_IDC_DEV_COLD) && | ||
924 | (prev != QLC_83XX_IDC_DEV_NEED_RESET)) { | ||
925 | dev_err(&adapter->pdev->dev, | ||
926 | "%s: failed, cur %d prev %d next %d\n", | ||
927 | __func__, cur, prev, next); | ||
928 | return 1; | ||
929 | } | ||
930 | } | ||
931 | |||
932 | return 0; | ||
933 | } | ||
934 | |||
935 | static void qlcnic_83xx_periodic_tasks(struct qlcnic_adapter *adapter) | ||
936 | { | ||
937 | if (adapter->fhash.fnum) | ||
938 | qlcnic_prune_lb_filters(adapter); | ||
939 | } | ||
940 | |||
941 | /** | ||
942 | * qlcnic_83xx_idc_poll_dev_state | ||
943 | * | ||
944 | * @work: kernel work queue structure used to schedule the function | ||
945 | * | ||
946 | * Poll device state periodically and perform state specific | ||
947 | * actions defined by Inter Driver Communication (IDC) protocol. | ||
948 | * | ||
949 | * Returns: None | ||
950 | * | ||
951 | **/ | ||
952 | void qlcnic_83xx_idc_poll_dev_state(struct work_struct *work) | ||
953 | { | ||
954 | struct qlcnic_adapter *adapter; | ||
955 | u32 state; | ||
956 | |||
957 | adapter = container_of(work, struct qlcnic_adapter, fw_work.work); | ||
958 | state = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_STATE); | ||
959 | |||
960 | if (qlcnic_83xx_idc_check_state_validity(adapter, state)) { | ||
961 | qlcnic_83xx_idc_log_state_history(adapter); | ||
962 | adapter->ahw->idc.curr_state = QLC_83XX_IDC_DEV_UNKNOWN; | ||
963 | } else { | ||
964 | adapter->ahw->idc.curr_state = state; | ||
965 | } | ||
966 | |||
967 | switch (adapter->ahw->idc.curr_state) { | ||
968 | case QLC_83XX_IDC_DEV_READY: | ||
969 | qlcnic_83xx_idc_ready_state(adapter); | ||
970 | break; | ||
971 | case QLC_83XX_IDC_DEV_NEED_RESET: | ||
972 | qlcnic_83xx_idc_need_reset_state(adapter); | ||
973 | break; | ||
974 | case QLC_83XX_IDC_DEV_NEED_QUISCENT: | ||
975 | qlcnic_83xx_idc_need_quiesce_state(adapter); | ||
976 | break; | ||
977 | case QLC_83XX_IDC_DEV_FAILED: | ||
978 | qlcnic_83xx_idc_failed_state(adapter); | ||
979 | return; | ||
980 | case QLC_83XX_IDC_DEV_INIT: | ||
981 | qlcnic_83xx_idc_init_state(adapter); | ||
982 | break; | ||
983 | case QLC_83XX_IDC_DEV_QUISCENT: | ||
984 | qlcnic_83xx_idc_quiesce_state(adapter); | ||
985 | break; | ||
986 | default: | ||
987 | qlcnic_83xx_idc_unknown_state(adapter); | ||
988 | return; | ||
989 | } | ||
990 | adapter->ahw->idc.prev_state = adapter->ahw->idc.curr_state; | ||
991 | qlcnic_83xx_periodic_tasks(adapter); | ||
992 | |||
993 | /* Re-schedule the function */ | ||
994 | if (test_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status)) | ||
995 | qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state, | ||
996 | adapter->ahw->idc.delay); | ||
997 | } | ||
998 | |||
999 | static void qlcnic_83xx_setup_idc_parameters(struct qlcnic_adapter *adapter) | ||
1000 | { | ||
1001 | u32 idc_params, val; | ||
1002 | |||
1003 | if (qlcnic_83xx_lockless_flash_read32(adapter, | ||
1004 | QLC_83XX_IDC_FLASH_PARAM_ADDR, | ||
1005 | (u8 *)&idc_params, 1)) { | ||
1006 | dev_info(&adapter->pdev->dev, | ||
1007 | "%s:failed to get IDC params from flash\n", __func__); | ||
1008 | adapter->dev_init_timeo = QLC_83XX_IDC_INIT_TIMEOUT_SECS; | ||
1009 | adapter->reset_ack_timeo = QLC_83XX_IDC_RESET_TIMEOUT_SECS; | ||
1010 | } else { | ||
1011 | adapter->dev_init_timeo = idc_params & 0xFFFF; | ||
1012 | adapter->reset_ack_timeo = ((idc_params >> 16) & 0xFFFF); | ||
1013 | } | ||
1014 | |||
1015 | adapter->ahw->idc.curr_state = QLC_83XX_IDC_DEV_UNKNOWN; | ||
1016 | adapter->ahw->idc.prev_state = QLC_83XX_IDC_DEV_UNKNOWN; | ||
1017 | adapter->ahw->idc.delay = QLC_83XX_IDC_FW_POLL_DELAY; | ||
1018 | adapter->ahw->idc.err_code = 0; | ||
1019 | adapter->ahw->idc.collect_dump = 0; | ||
1020 | adapter->ahw->idc.name = (char **)qlc_83xx_idc_states; | ||
1021 | |||
1022 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
1023 | set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); | ||
1024 | set_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status); | ||
1025 | |||
1026 | /* Check if reset recovery is disabled */ | ||
1027 | if (!qlcnic_auto_fw_reset) { | ||
1028 | /* Propagate do not reset request to other functions */ | ||
1029 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); | ||
1030 | val = val | QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY; | ||
1031 | QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val); | ||
1032 | } | ||
1033 | } | ||
1034 | |||
1035 | static int | ||
1036 | qlcnic_83xx_idc_first_to_load_function_handler(struct qlcnic_adapter *adapter) | ||
1037 | { | ||
1038 | u32 state, val; | ||
1039 | |||
1040 | if (qlcnic_83xx_lock_driver(adapter)) | ||
1041 | return -EIO; | ||
1042 | |||
1043 | /* Clear driver lock register */ | ||
1044 | QLCWRX(adapter->ahw, QLC_83XX_RECOVER_DRV_LOCK, 0); | ||
1045 | if (qlcnic_83xx_idc_update_major_version(adapter, 0)) { | ||
1046 | qlcnic_83xx_unlock_driver(adapter); | ||
1047 | return -EIO; | ||
1048 | } | ||
1049 | |||
1050 | state = QLCRDX(adapter->ahw, QLC_83XX_IDC_DEV_STATE); | ||
1051 | if (qlcnic_83xx_idc_check_state_validity(adapter, state)) { | ||
1052 | qlcnic_83xx_unlock_driver(adapter); | ||
1053 | return -EIO; | ||
1054 | } | ||
1055 | |||
1056 | if (state != QLC_83XX_IDC_DEV_COLD && qlcnic_load_fw_file) { | ||
1057 | QLCWRX(adapter->ahw, QLC_83XX_IDC_DEV_STATE, | ||
1058 | QLC_83XX_IDC_DEV_COLD); | ||
1059 | state = QLC_83XX_IDC_DEV_COLD; | ||
1060 | } | ||
1061 | |||
1062 | adapter->ahw->idc.curr_state = state; | ||
1063 | /* First to load function should cold boot the device */ | ||
1064 | if (state == QLC_83XX_IDC_DEV_COLD) | ||
1065 | qlcnic_83xx_idc_cold_state_handler(adapter); | ||
1066 | |||
1067 | /* Check if reset recovery is enabled */ | ||
1068 | if (qlcnic_auto_fw_reset) { | ||
1069 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); | ||
1070 | val = val & ~QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY; | ||
1071 | QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val); | ||
1072 | } | ||
1073 | |||
1074 | qlcnic_83xx_unlock_driver(adapter); | ||
1075 | |||
1076 | return 0; | ||
1077 | } | ||
1078 | |||
1079 | static int qlcnic_83xx_idc_init(struct qlcnic_adapter *adapter) | ||
1080 | { | ||
1081 | int ret = -EIO; | ||
1082 | |||
1083 | qlcnic_83xx_setup_idc_parameters(adapter); | ||
1084 | |||
1085 | if (qlcnic_83xx_get_reset_instruction_template(adapter)) | ||
1086 | return ret; | ||
1087 | |||
1088 | if (!qlcnic_83xx_idc_check_driver_presence_reg(adapter)) { | ||
1089 | if (qlcnic_83xx_idc_first_to_load_function_handler(adapter)) | ||
1090 | return -EIO; | ||
1091 | } else { | ||
1092 | if (qlcnic_83xx_idc_check_major_version(adapter)) | ||
1093 | return -EIO; | ||
1094 | } | ||
1095 | |||
1096 | qlcnic_83xx_idc_update_audit_reg(adapter, 0, 1); | ||
1097 | |||
1098 | return 0; | ||
1099 | } | ||
1100 | |||
1101 | void qlcnic_83xx_idc_exit(struct qlcnic_adapter *adapter) | ||
1102 | { | ||
1103 | int id; | ||
1104 | u32 val; | ||
1105 | |||
1106 | while (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) | ||
1107 | usleep_range(10000, 11000); | ||
1108 | |||
1109 | id = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID); | ||
1110 | id = id & 0xFF; | ||
1111 | |||
1112 | if (id == adapter->portnum) { | ||
1113 | dev_err(&adapter->pdev->dev, | ||
1114 | "%s: wait for lock recovery.. %d\n", __func__, id); | ||
1115 | msleep(20); | ||
1116 | id = QLCRDX(adapter->ahw, QLC_83XX_DRV_LOCK_ID); | ||
1117 | id = id & 0xFF; | ||
1118 | } | ||
1119 | |||
1120 | /* Clear driver presence bit */ | ||
1121 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE); | ||
1122 | val = val & ~(1 << adapter->portnum); | ||
1123 | QLCWRX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE, val); | ||
1124 | clear_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status); | ||
1125 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
1126 | |||
1127 | cancel_delayed_work_sync(&adapter->fw_work); | ||
1128 | } | ||
1129 | |||
1130 | void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *adapter, u32 key) | ||
1131 | { | ||
1132 | u32 val; | ||
1133 | |||
1134 | if (qlcnic_83xx_lock_driver(adapter)) { | ||
1135 | dev_err(&adapter->pdev->dev, | ||
1136 | "%s:failed, please retry\n", __func__); | ||
1137 | return; | ||
1138 | } | ||
1139 | |||
1140 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); | ||
1141 | if ((val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) || | ||
1142 | !qlcnic_auto_fw_reset) { | ||
1143 | dev_err(&adapter->pdev->dev, | ||
1144 | "%s:failed, device in non reset mode\n", __func__); | ||
1145 | qlcnic_83xx_unlock_driver(adapter); | ||
1146 | return; | ||
1147 | } | ||
1148 | |||
1149 | if (key == QLCNIC_FORCE_FW_RESET) { | ||
1150 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); | ||
1151 | val = val | QLC_83XX_IDC_GRACEFULL_RESET; | ||
1152 | QLCWRX(adapter->ahw, QLC_83XX_IDC_CTRL, val); | ||
1153 | } else if (key == QLCNIC_FORCE_FW_DUMP_KEY) { | ||
1154 | adapter->ahw->idc.collect_dump = 1; | ||
1155 | } | ||
1156 | |||
1157 | qlcnic_83xx_unlock_driver(adapter); | ||
1158 | return; | ||
1159 | } | ||
1160 | |||
1161 | static int qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter) | ||
1162 | { | ||
1163 | u8 *p_cache; | ||
1164 | u32 src, size; | ||
1165 | u64 dest; | ||
1166 | int ret = -EIO; | ||
1167 | |||
1168 | src = QLC_83XX_BOOTLOADER_FLASH_ADDR; | ||
1169 | dest = QLCRDX(adapter->ahw, QLCNIC_BOOTLOADER_ADDR); | ||
1170 | size = QLCRDX(adapter->ahw, QLCNIC_BOOTLOADER_SIZE); | ||
1171 | |||
1172 | /* alignment check */ | ||
1173 | if (size & 0xF) | ||
1174 | size = (size + 16) & ~0xF; | ||
1175 | |||
1176 | p_cache = kzalloc(size, GFP_KERNEL); | ||
1177 | if (p_cache == NULL) | ||
1178 | return -ENOMEM; | ||
1179 | |||
1180 | ret = qlcnic_83xx_lockless_flash_read32(adapter, src, p_cache, | ||
1181 | size / sizeof(u32)); | ||
1182 | if (ret) { | ||
1183 | kfree(p_cache); | ||
1184 | return ret; | ||
1185 | } | ||
1186 | /* 16 byte write to MS memory */ | ||
1187 | ret = qlcnic_83xx_ms_mem_write128(adapter, dest, (u32 *)p_cache, | ||
1188 | size / 16); | ||
1189 | if (ret) { | ||
1190 | kfree(p_cache); | ||
1191 | return ret; | ||
1192 | } | ||
1193 | kfree(p_cache); | ||
1194 | |||
1195 | return ret; | ||
1196 | } | ||
1197 | |||
1198 | static int qlcnic_83xx_copy_fw_file(struct qlcnic_adapter *adapter) | ||
1199 | { | ||
1200 | u32 dest, *p_cache; | ||
1201 | u64 addr; | ||
1202 | u8 data[16]; | ||
1203 | size_t size; | ||
1204 | int i, ret = -EIO; | ||
1205 | |||
1206 | dest = QLCRDX(adapter->ahw, QLCNIC_FW_IMAGE_ADDR); | ||
1207 | size = (adapter->ahw->fw_info.fw->size & ~0xF); | ||
1208 | p_cache = (u32 *)adapter->ahw->fw_info.fw->data; | ||
1209 | addr = (u64)dest; | ||
1210 | |||
1211 | ret = qlcnic_83xx_ms_mem_write128(adapter, addr, | ||
1212 | (u32 *)p_cache, size / 16); | ||
1213 | if (ret) { | ||
1214 | dev_err(&adapter->pdev->dev, "MS memory write failed\n"); | ||
1215 | release_firmware(adapter->ahw->fw_info.fw); | ||
1216 | adapter->ahw->fw_info.fw = NULL; | ||
1217 | return -EIO; | ||
1218 | } | ||
1219 | |||
1220 | /* alignment check */ | ||
1221 | if (adapter->ahw->fw_info.fw->size & 0xF) { | ||
1222 | addr = dest + size; | ||
1223 | for (i = 0; i < (adapter->ahw->fw_info.fw->size & 0xF); i++) | ||
1224 | data[i] = adapter->ahw->fw_info.fw->data[size + i]; | ||
1225 | for (; i < 16; i++) | ||
1226 | data[i] = 0; | ||
1227 | ret = qlcnic_83xx_ms_mem_write128(adapter, addr, | ||
1228 | (u32 *)data, 1); | ||
1229 | if (ret) { | ||
1230 | dev_err(&adapter->pdev->dev, | ||
1231 | "MS memory write failed\n"); | ||
1232 | release_firmware(adapter->ahw->fw_info.fw); | ||
1233 | adapter->ahw->fw_info.fw = NULL; | ||
1234 | return -EIO; | ||
1235 | } | ||
1236 | } | ||
1237 | release_firmware(adapter->ahw->fw_info.fw); | ||
1238 | adapter->ahw->fw_info.fw = NULL; | ||
1239 | |||
1240 | return 0; | ||
1241 | } | ||
1242 | |||
1243 | static void qlcnic_83xx_dump_pause_control_regs(struct qlcnic_adapter *adapter) | ||
1244 | { | ||
1245 | int i, j; | ||
1246 | u32 val = 0, val1 = 0, reg = 0; | ||
1247 | |||
1248 | val = QLCRD32(adapter, QLC_83XX_SRE_SHIM_REG); | ||
1249 | dev_info(&adapter->pdev->dev, "SRE-Shim Ctrl:0x%x\n", val); | ||
1250 | |||
1251 | for (j = 0; j < 2; j++) { | ||
1252 | if (j == 0) { | ||
1253 | dev_info(&adapter->pdev->dev, | ||
1254 | "Port 0 RxB Pause Threshold Regs[TC7..TC0]:"); | ||
1255 | reg = QLC_83XX_PORT0_THRESHOLD; | ||
1256 | } else if (j == 1) { | ||
1257 | dev_info(&adapter->pdev->dev, | ||
1258 | "Port 1 RxB Pause Threshold Regs[TC7..TC0]:"); | ||
1259 | reg = QLC_83XX_PORT1_THRESHOLD; | ||
1260 | } | ||
1261 | for (i = 0; i < 8; i++) { | ||
1262 | val = QLCRD32(adapter, reg + (i * 0x4)); | ||
1263 | dev_info(&adapter->pdev->dev, "0x%x ", val); | ||
1264 | } | ||
1265 | dev_info(&adapter->pdev->dev, "\n"); | ||
1266 | } | ||
1267 | |||
1268 | for (j = 0; j < 2; j++) { | ||
1269 | if (j == 0) { | ||
1270 | dev_info(&adapter->pdev->dev, | ||
1271 | "Port 0 RxB TC Max Cell Registers[4..1]:"); | ||
1272 | reg = QLC_83XX_PORT0_TC_MC_REG; | ||
1273 | } else if (j == 1) { | ||
1274 | dev_info(&adapter->pdev->dev, | ||
1275 | "Port 1 RxB TC Max Cell Registers[4..1]:"); | ||
1276 | reg = QLC_83XX_PORT1_TC_MC_REG; | ||
1277 | } | ||
1278 | for (i = 0; i < 4; i++) { | ||
1279 | val = QLCRD32(adapter, reg + (i * 0x4)); | ||
1280 | dev_info(&adapter->pdev->dev, "0x%x ", val); | ||
1281 | } | ||
1282 | dev_info(&adapter->pdev->dev, "\n"); | ||
1283 | } | ||
1284 | |||
1285 | for (j = 0; j < 2; j++) { | ||
1286 | if (j == 0) { | ||
1287 | dev_info(&adapter->pdev->dev, | ||
1288 | "Port 0 RxB Rx TC Stats[TC7..TC0]:"); | ||
1289 | reg = QLC_83XX_PORT0_TC_STATS; | ||
1290 | } else if (j == 1) { | ||
1291 | dev_info(&adapter->pdev->dev, | ||
1292 | "Port 1 RxB Rx TC Stats[TC7..TC0]:"); | ||
1293 | reg = QLC_83XX_PORT1_TC_STATS; | ||
1294 | } | ||
1295 | for (i = 7; i >= 0; i--) { | ||
1296 | val = QLCRD32(adapter, reg); | ||
1297 | val &= ~(0x7 << 29); /* Reset bits 29 to 31 */ | ||
1298 | QLCWR32(adapter, reg, (val | (i << 29))); | ||
1299 | val = QLCRD32(adapter, reg); | ||
1300 | dev_info(&adapter->pdev->dev, "0x%x ", val); | ||
1301 | } | ||
1302 | dev_info(&adapter->pdev->dev, "\n"); | ||
1303 | } | ||
1304 | |||
1305 | val = QLCRD32(adapter, QLC_83XX_PORT2_IFB_THRESHOLD); | ||
1306 | val1 = QLCRD32(adapter, QLC_83XX_PORT3_IFB_THRESHOLD); | ||
1307 | dev_info(&adapter->pdev->dev, | ||
1308 | "IFB-Pause Thresholds: Port 2:0x%x, Port 3:0x%x\n", | ||
1309 | val, val1); | ||
1310 | } | ||
1311 | |||
1312 | |||
1313 | static void qlcnic_83xx_disable_pause_frames(struct qlcnic_adapter *adapter) | ||
1314 | { | ||
1315 | u32 reg = 0, i, j; | ||
1316 | |||
1317 | if (qlcnic_83xx_lock_driver(adapter)) { | ||
1318 | dev_err(&adapter->pdev->dev, | ||
1319 | "%s:failed to acquire driver lock\n", __func__); | ||
1320 | return; | ||
1321 | } | ||
1322 | |||
1323 | qlcnic_83xx_dump_pause_control_regs(adapter); | ||
1324 | QLCWR32(adapter, QLC_83XX_SRE_SHIM_REG, 0x0); | ||
1325 | |||
1326 | for (j = 0; j < 2; j++) { | ||
1327 | if (j == 0) | ||
1328 | reg = QLC_83XX_PORT0_THRESHOLD; | ||
1329 | else if (j == 1) | ||
1330 | reg = QLC_83XX_PORT1_THRESHOLD; | ||
1331 | |||
1332 | for (i = 0; i < 8; i++) | ||
1333 | QLCWR32(adapter, reg + (i * 0x4), 0x0); | ||
1334 | } | ||
1335 | |||
1336 | for (j = 0; j < 2; j++) { | ||
1337 | if (j == 0) | ||
1338 | reg = QLC_83XX_PORT0_TC_MC_REG; | ||
1339 | else if (j == 1) | ||
1340 | reg = QLC_83XX_PORT1_TC_MC_REG; | ||
1341 | |||
1342 | for (i = 0; i < 4; i++) | ||
1343 | QLCWR32(adapter, reg + (i * 0x4), 0x03FF03FF); | ||
1344 | } | ||
1345 | |||
1346 | QLCWR32(adapter, QLC_83XX_PORT2_IFB_THRESHOLD, 0); | ||
1347 | QLCWR32(adapter, QLC_83XX_PORT3_IFB_THRESHOLD, 0); | ||
1348 | dev_info(&adapter->pdev->dev, | ||
1349 | "Disabled pause frames successfully on all ports\n"); | ||
1350 | qlcnic_83xx_unlock_driver(adapter); | ||
1351 | } | ||
1352 | |||
1353 | static int qlcnic_83xx_check_heartbeat(struct qlcnic_adapter *p_dev) | ||
1354 | { | ||
1355 | u32 heartbeat, peg_status; | ||
1356 | int retries, ret = -EIO; | ||
1357 | |||
1358 | retries = QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT; | ||
1359 | p_dev->heartbeat = QLC_SHARED_REG_RD32(p_dev, | ||
1360 | QLCNIC_PEG_ALIVE_COUNTER); | ||
1361 | |||
1362 | do { | ||
1363 | msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS); | ||
1364 | heartbeat = QLC_SHARED_REG_RD32(p_dev, | ||
1365 | QLCNIC_PEG_ALIVE_COUNTER); | ||
1366 | if (heartbeat != p_dev->heartbeat) { | ||
1367 | ret = QLCNIC_RCODE_SUCCESS; | ||
1368 | break; | ||
1369 | } | ||
1370 | } while (--retries); | ||
1371 | |||
1372 | if (ret) { | ||
1373 | dev_err(&p_dev->pdev->dev, "firmware hang detected\n"); | ||
1374 | qlcnic_83xx_disable_pause_frames(p_dev); | ||
1375 | peg_status = QLC_SHARED_REG_RD32(p_dev, | ||
1376 | QLCNIC_PEG_HALT_STATUS1); | ||
1377 | dev_info(&p_dev->pdev->dev, "Dumping HW/FW registers\n" | ||
1378 | "PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n" | ||
1379 | "PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n" | ||
1380 | "PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n" | ||
1381 | "PEG_NET_4_PC: 0x%x\n", peg_status, | ||
1382 | QLC_SHARED_REG_RD32(p_dev, QLCNIC_PEG_HALT_STATUS2), | ||
1383 | QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_0), | ||
1384 | QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_1), | ||
1385 | QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_2), | ||
1386 | QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_3), | ||
1387 | QLCRD32(p_dev, QLC_83XX_CRB_PEG_NET_4)); | ||
1388 | |||
1389 | if (QLCNIC_FWERROR_CODE(peg_status) == 0x67) | ||
1390 | dev_err(&p_dev->pdev->dev, | ||
1391 | "Device is being reset err code 0x00006700.\n"); | ||
1392 | } | ||
1393 | |||
1394 | return ret; | ||
1395 | } | ||
1396 | |||
1397 | static int qlcnic_83xx_check_cmd_peg_status(struct qlcnic_adapter *p_dev) | ||
1398 | { | ||
1399 | int retries = QLCNIC_CMDPEG_CHECK_RETRY_COUNT; | ||
1400 | u32 val; | ||
1401 | |||
1402 | do { | ||
1403 | val = QLC_SHARED_REG_RD32(p_dev, QLCNIC_CMDPEG_STATE); | ||
1404 | if (val == QLC_83XX_CMDPEG_COMPLETE) | ||
1405 | return 0; | ||
1406 | msleep(QLCNIC_CMDPEG_CHECK_DELAY); | ||
1407 | } while (--retries); | ||
1408 | |||
1409 | dev_err(&p_dev->pdev->dev, "%s: failed, state = 0x%x\n", __func__, val); | ||
1410 | return -EIO; | ||
1411 | } | ||
1412 | |||
1413 | int qlcnic_83xx_check_hw_status(struct qlcnic_adapter *p_dev) | ||
1414 | { | ||
1415 | int err; | ||
1416 | |||
1417 | err = qlcnic_83xx_check_cmd_peg_status(p_dev); | ||
1418 | if (err) | ||
1419 | return err; | ||
1420 | |||
1421 | err = qlcnic_83xx_check_heartbeat(p_dev); | ||
1422 | if (err) | ||
1423 | return err; | ||
1424 | |||
1425 | return err; | ||
1426 | } | ||
1427 | |||
1428 | static int qlcnic_83xx_poll_reg(struct qlcnic_adapter *p_dev, u32 addr, | ||
1429 | int duration, u32 mask, u32 status) | ||
1430 | { | ||
1431 | u32 value; | ||
1432 | int timeout_error; | ||
1433 | u8 retries; | ||
1434 | |||
1435 | value = qlcnic_83xx_rd_reg_indirect(p_dev, addr); | ||
1436 | retries = duration / 10; | ||
1437 | |||
1438 | do { | ||
1439 | if ((value & mask) != status) { | ||
1440 | timeout_error = 1; | ||
1441 | msleep(duration / 10); | ||
1442 | value = qlcnic_83xx_rd_reg_indirect(p_dev, addr); | ||
1443 | } else { | ||
1444 | timeout_error = 0; | ||
1445 | break; | ||
1446 | } | ||
1447 | } while (retries--); | ||
1448 | |||
1449 | if (timeout_error) { | ||
1450 | p_dev->ahw->reset.seq_error++; | ||
1451 | dev_err(&p_dev->pdev->dev, | ||
1452 | "%s: Timeout Err, entry_num = %d\n", | ||
1453 | __func__, p_dev->ahw->reset.seq_index); | ||
1454 | dev_err(&p_dev->pdev->dev, | ||
1455 | "0x%08x 0x%08x 0x%08x\n", | ||
1456 | value, mask, status); | ||
1457 | } | ||
1458 | |||
1459 | return timeout_error; | ||
1460 | } | ||
1461 | |||
1462 | static int qlcnic_83xx_reset_template_checksum(struct qlcnic_adapter *p_dev) | ||
1463 | { | ||
1464 | u32 sum = 0; | ||
1465 | u16 *buff = (u16 *)p_dev->ahw->reset.buff; | ||
1466 | int count = p_dev->ahw->reset.hdr->size / sizeof(u16); | ||
1467 | |||
1468 | while (count-- > 0) | ||
1469 | sum += *buff++; | ||
1470 | |||
1471 | while (sum >> 16) | ||
1472 | sum = (sum & 0xFFFF) + (sum >> 16); | ||
1473 | |||
1474 | if (~sum) { | ||
1475 | return 0; | ||
1476 | } else { | ||
1477 | dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__); | ||
1478 | return -1; | ||
1479 | } | ||
1480 | } | ||
1481 | |||
1482 | int qlcnic_83xx_get_reset_instruction_template(struct qlcnic_adapter *p_dev) | ||
1483 | { | ||
1484 | u8 *p_buff; | ||
1485 | u32 addr, count; | ||
1486 | struct qlcnic_hardware_context *ahw = p_dev->ahw; | ||
1487 | |||
1488 | ahw->reset.seq_error = 0; | ||
1489 | ahw->reset.buff = kzalloc(QLC_83XX_RESTART_TEMPLATE_SIZE, GFP_KERNEL); | ||
1490 | if (p_dev->ahw->reset.buff == NULL) | ||
1491 | return -ENOMEM; | ||
1492 | |||
1493 | p_buff = p_dev->ahw->reset.buff; | ||
1494 | addr = QLC_83XX_RESET_TEMPLATE_ADDR; | ||
1495 | count = sizeof(struct qlc_83xx_reset_hdr) / sizeof(u32); | ||
1496 | |||
1497 | /* Copy template header from flash */ | ||
1498 | if (qlcnic_83xx_flash_read32(p_dev, addr, p_buff, count)) { | ||
1499 | dev_err(&p_dev->pdev->dev, "%s: flash read failed\n", __func__); | ||
1500 | return -EIO; | ||
1501 | } | ||
1502 | ahw->reset.hdr = (struct qlc_83xx_reset_hdr *)ahw->reset.buff; | ||
1503 | addr = QLC_83XX_RESET_TEMPLATE_ADDR + ahw->reset.hdr->hdr_size; | ||
1504 | p_buff = ahw->reset.buff + ahw->reset.hdr->hdr_size; | ||
1505 | count = (ahw->reset.hdr->size - ahw->reset.hdr->hdr_size) / sizeof(u32); | ||
1506 | |||
1507 | /* Copy rest of the template */ | ||
1508 | if (qlcnic_83xx_flash_read32(p_dev, addr, p_buff, count)) { | ||
1509 | dev_err(&p_dev->pdev->dev, "%s: flash read failed\n", __func__); | ||
1510 | return -EIO; | ||
1511 | } | ||
1512 | |||
1513 | if (qlcnic_83xx_reset_template_checksum(p_dev)) | ||
1514 | return -EIO; | ||
1515 | /* Get Stop, Start and Init command offsets */ | ||
1516 | ahw->reset.init_offset = ahw->reset.buff + ahw->reset.hdr->init_offset; | ||
1517 | ahw->reset.start_offset = ahw->reset.buff + | ||
1518 | ahw->reset.hdr->start_offset; | ||
1519 | ahw->reset.stop_offset = ahw->reset.buff + ahw->reset.hdr->hdr_size; | ||
1520 | return 0; | ||
1521 | } | ||
1522 | |||
1523 | /* Read Write HW register command */ | ||
1524 | static void qlcnic_83xx_read_write_crb_reg(struct qlcnic_adapter *p_dev, | ||
1525 | u32 raddr, u32 waddr) | ||
1526 | { | ||
1527 | int value; | ||
1528 | |||
1529 | value = qlcnic_83xx_rd_reg_indirect(p_dev, raddr); | ||
1530 | qlcnic_83xx_wrt_reg_indirect(p_dev, waddr, value); | ||
1531 | } | ||
1532 | |||
1533 | /* Read Modify Write HW register command */ | ||
1534 | static void qlcnic_83xx_rmw_crb_reg(struct qlcnic_adapter *p_dev, | ||
1535 | u32 raddr, u32 waddr, | ||
1536 | struct qlc_83xx_rmw *p_rmw_hdr) | ||
1537 | { | ||
1538 | int value; | ||
1539 | |||
1540 | if (p_rmw_hdr->index_a) | ||
1541 | value = p_dev->ahw->reset.array[p_rmw_hdr->index_a]; | ||
1542 | else | ||
1543 | value = qlcnic_83xx_rd_reg_indirect(p_dev, raddr); | ||
1544 | |||
1545 | value &= p_rmw_hdr->mask; | ||
1546 | value <<= p_rmw_hdr->shl; | ||
1547 | value >>= p_rmw_hdr->shr; | ||
1548 | value |= p_rmw_hdr->or_value; | ||
1549 | value ^= p_rmw_hdr->xor_value; | ||
1550 | qlcnic_83xx_wrt_reg_indirect(p_dev, waddr, value); | ||
1551 | } | ||
1552 | |||
1553 | /* Write HW register command */ | ||
1554 | static void qlcnic_83xx_write_list(struct qlcnic_adapter *p_dev, | ||
1555 | struct qlc_83xx_entry_hdr *p_hdr) | ||
1556 | { | ||
1557 | int i; | ||
1558 | struct qlc_83xx_entry *entry; | ||
1559 | |||
1560 | entry = (struct qlc_83xx_entry *)((char *)p_hdr + | ||
1561 | sizeof(struct qlc_83xx_entry_hdr)); | ||
1562 | |||
1563 | for (i = 0; i < p_hdr->count; i++, entry++) { | ||
1564 | qlcnic_83xx_wrt_reg_indirect(p_dev, entry->arg1, | ||
1565 | entry->arg2); | ||
1566 | if (p_hdr->delay) | ||
1567 | udelay((u32)(p_hdr->delay)); | ||
1568 | } | ||
1569 | } | ||
1570 | |||
1571 | /* Read and Write instruction */ | ||
1572 | static void qlcnic_83xx_read_write_list(struct qlcnic_adapter *p_dev, | ||
1573 | struct qlc_83xx_entry_hdr *p_hdr) | ||
1574 | { | ||
1575 | int i; | ||
1576 | struct qlc_83xx_entry *entry; | ||
1577 | |||
1578 | entry = (struct qlc_83xx_entry *)((char *)p_hdr + | ||
1579 | sizeof(struct qlc_83xx_entry_hdr)); | ||
1580 | |||
1581 | for (i = 0; i < p_hdr->count; i++, entry++) { | ||
1582 | qlcnic_83xx_read_write_crb_reg(p_dev, entry->arg1, | ||
1583 | entry->arg2); | ||
1584 | if (p_hdr->delay) | ||
1585 | udelay((u32)(p_hdr->delay)); | ||
1586 | } | ||
1587 | } | ||
1588 | |||
1589 | /* Poll HW register command */ | ||
1590 | static void qlcnic_83xx_poll_list(struct qlcnic_adapter *p_dev, | ||
1591 | struct qlc_83xx_entry_hdr *p_hdr) | ||
1592 | { | ||
1593 | long delay; | ||
1594 | struct qlc_83xx_entry *entry; | ||
1595 | struct qlc_83xx_poll *poll; | ||
1596 | int i; | ||
1597 | unsigned long arg1, arg2; | ||
1598 | |||
1599 | poll = (struct qlc_83xx_poll *)((char *)p_hdr + | ||
1600 | sizeof(struct qlc_83xx_entry_hdr)); | ||
1601 | |||
1602 | entry = (struct qlc_83xx_entry *)((char *)poll + | ||
1603 | sizeof(struct qlc_83xx_poll)); | ||
1604 | delay = (long)p_hdr->delay; | ||
1605 | |||
1606 | if (!delay) { | ||
1607 | for (i = 0; i < p_hdr->count; i++, entry++) | ||
1608 | qlcnic_83xx_poll_reg(p_dev, entry->arg1, | ||
1609 | delay, poll->mask, | ||
1610 | poll->status); | ||
1611 | } else { | ||
1612 | for (i = 0; i < p_hdr->count; i++, entry++) { | ||
1613 | arg1 = entry->arg1; | ||
1614 | arg2 = entry->arg2; | ||
1615 | if (delay) { | ||
1616 | if (qlcnic_83xx_poll_reg(p_dev, | ||
1617 | arg1, delay, | ||
1618 | poll->mask, | ||
1619 | poll->status)){ | ||
1620 | qlcnic_83xx_rd_reg_indirect(p_dev, | ||
1621 | arg1); | ||
1622 | qlcnic_83xx_rd_reg_indirect(p_dev, | ||
1623 | arg2); | ||
1624 | } | ||
1625 | } | ||
1626 | } | ||
1627 | } | ||
1628 | } | ||
1629 | |||
1630 | /* Poll and write HW register command */ | ||
1631 | static void qlcnic_83xx_poll_write_list(struct qlcnic_adapter *p_dev, | ||
1632 | struct qlc_83xx_entry_hdr *p_hdr) | ||
1633 | { | ||
1634 | int i; | ||
1635 | long delay; | ||
1636 | struct qlc_83xx_quad_entry *entry; | ||
1637 | struct qlc_83xx_poll *poll; | ||
1638 | |||
1639 | poll = (struct qlc_83xx_poll *)((char *)p_hdr + | ||
1640 | sizeof(struct qlc_83xx_entry_hdr)); | ||
1641 | entry = (struct qlc_83xx_quad_entry *)((char *)poll + | ||
1642 | sizeof(struct qlc_83xx_poll)); | ||
1643 | delay = (long)p_hdr->delay; | ||
1644 | |||
1645 | for (i = 0; i < p_hdr->count; i++, entry++) { | ||
1646 | qlcnic_83xx_wrt_reg_indirect(p_dev, entry->dr_addr, | ||
1647 | entry->dr_value); | ||
1648 | qlcnic_83xx_wrt_reg_indirect(p_dev, entry->ar_addr, | ||
1649 | entry->ar_value); | ||
1650 | if (delay) | ||
1651 | qlcnic_83xx_poll_reg(p_dev, entry->ar_addr, delay, | ||
1652 | poll->mask, poll->status); | ||
1653 | } | ||
1654 | } | ||
1655 | |||
1656 | /* Read Modify Write register command */ | ||
1657 | static void qlcnic_83xx_read_modify_write(struct qlcnic_adapter *p_dev, | ||
1658 | struct qlc_83xx_entry_hdr *p_hdr) | ||
1659 | { | ||
1660 | int i; | ||
1661 | struct qlc_83xx_entry *entry; | ||
1662 | struct qlc_83xx_rmw *rmw_hdr; | ||
1663 | |||
1664 | rmw_hdr = (struct qlc_83xx_rmw *)((char *)p_hdr + | ||
1665 | sizeof(struct qlc_83xx_entry_hdr)); | ||
1666 | |||
1667 | entry = (struct qlc_83xx_entry *)((char *)rmw_hdr + | ||
1668 | sizeof(struct qlc_83xx_rmw)); | ||
1669 | |||
1670 | for (i = 0; i < p_hdr->count; i++, entry++) { | ||
1671 | qlcnic_83xx_rmw_crb_reg(p_dev, entry->arg1, | ||
1672 | entry->arg2, rmw_hdr); | ||
1673 | if (p_hdr->delay) | ||
1674 | udelay((u32)(p_hdr->delay)); | ||
1675 | } | ||
1676 | } | ||
1677 | |||
1678 | static void qlcnic_83xx_pause(struct qlc_83xx_entry_hdr *p_hdr) | ||
1679 | { | ||
1680 | if (p_hdr->delay) | ||
1681 | mdelay((u32)((long)p_hdr->delay)); | ||
1682 | } | ||
1683 | |||
1684 | /* Read and poll register command */ | ||
1685 | static void qlcnic_83xx_poll_read_list(struct qlcnic_adapter *p_dev, | ||
1686 | struct qlc_83xx_entry_hdr *p_hdr) | ||
1687 | { | ||
1688 | long delay; | ||
1689 | int index, i, j; | ||
1690 | struct qlc_83xx_quad_entry *entry; | ||
1691 | struct qlc_83xx_poll *poll; | ||
1692 | unsigned long addr; | ||
1693 | |||
1694 | poll = (struct qlc_83xx_poll *)((char *)p_hdr + | ||
1695 | sizeof(struct qlc_83xx_entry_hdr)); | ||
1696 | |||
1697 | entry = (struct qlc_83xx_quad_entry *)((char *)poll + | ||
1698 | sizeof(struct qlc_83xx_poll)); | ||
1699 | delay = (long)p_hdr->delay; | ||
1700 | |||
1701 | for (i = 0; i < p_hdr->count; i++, entry++) { | ||
1702 | qlcnic_83xx_wrt_reg_indirect(p_dev, entry->ar_addr, | ||
1703 | entry->ar_value); | ||
1704 | if (delay) { | ||
1705 | if (!qlcnic_83xx_poll_reg(p_dev, entry->ar_addr, delay, | ||
1706 | poll->mask, poll->status)){ | ||
1707 | index = p_dev->ahw->reset.array_index; | ||
1708 | addr = entry->dr_addr; | ||
1709 | j = qlcnic_83xx_rd_reg_indirect(p_dev, addr); | ||
1710 | p_dev->ahw->reset.array[index++] = j; | ||
1711 | |||
1712 | if (index == QLC_83XX_MAX_RESET_SEQ_ENTRIES) | ||
1713 | p_dev->ahw->reset.array_index = 1; | ||
1714 | } | ||
1715 | } | ||
1716 | } | ||
1717 | } | ||
1718 | |||
1719 | static inline void qlcnic_83xx_seq_end(struct qlcnic_adapter *p_dev) | ||
1720 | { | ||
1721 | p_dev->ahw->reset.seq_end = 1; | ||
1722 | } | ||
1723 | |||
1724 | static void qlcnic_83xx_template_end(struct qlcnic_adapter *p_dev) | ||
1725 | { | ||
1726 | p_dev->ahw->reset.template_end = 1; | ||
1727 | if (p_dev->ahw->reset.seq_error == 0) | ||
1728 | dev_err(&p_dev->pdev->dev, | ||
1729 | "HW restart process completed successfully.\n"); | ||
1730 | else | ||
1731 | dev_err(&p_dev->pdev->dev, | ||
1732 | "HW restart completed with timeout errors.\n"); | ||
1733 | } | ||
1734 | |||
1735 | /** | ||
1736 | * qlcnic_83xx_exec_template_cmd | ||
1737 | * | ||
1738 | * @p_dev: adapter structure | ||
1739 | * @p_buff: Poiter to instruction template | ||
1740 | * | ||
1741 | * Template provides instructions to stop, restart and initalize firmware. | ||
1742 | * These instructions are abstracted as a series of read, write and | ||
1743 | * poll operations on hardware registers. Register information and operation | ||
1744 | * specifics are not exposed to the driver. Driver reads the template from | ||
1745 | * flash and executes the instructions located at pre-defined offsets. | ||
1746 | * | ||
1747 | * Returns: None | ||
1748 | * */ | ||
1749 | static void qlcnic_83xx_exec_template_cmd(struct qlcnic_adapter *p_dev, | ||
1750 | char *p_buff) | ||
1751 | { | ||
1752 | int index, entries; | ||
1753 | struct qlc_83xx_entry_hdr *p_hdr; | ||
1754 | char *entry = p_buff; | ||
1755 | |||
1756 | p_dev->ahw->reset.seq_end = 0; | ||
1757 | p_dev->ahw->reset.template_end = 0; | ||
1758 | entries = p_dev->ahw->reset.hdr->entries; | ||
1759 | index = p_dev->ahw->reset.seq_index; | ||
1760 | |||
1761 | for (; (!p_dev->ahw->reset.seq_end) && (index < entries); index++) { | ||
1762 | p_hdr = (struct qlc_83xx_entry_hdr *)entry; | ||
1763 | |||
1764 | switch (p_hdr->cmd) { | ||
1765 | case QLC_83XX_OPCODE_NOP: | ||
1766 | break; | ||
1767 | case QLC_83XX_OPCODE_WRITE_LIST: | ||
1768 | qlcnic_83xx_write_list(p_dev, p_hdr); | ||
1769 | break; | ||
1770 | case QLC_83XX_OPCODE_READ_WRITE_LIST: | ||
1771 | qlcnic_83xx_read_write_list(p_dev, p_hdr); | ||
1772 | break; | ||
1773 | case QLC_83XX_OPCODE_POLL_LIST: | ||
1774 | qlcnic_83xx_poll_list(p_dev, p_hdr); | ||
1775 | break; | ||
1776 | case QLC_83XX_OPCODE_POLL_WRITE_LIST: | ||
1777 | qlcnic_83xx_poll_write_list(p_dev, p_hdr); | ||
1778 | break; | ||
1779 | case QLC_83XX_OPCODE_READ_MODIFY_WRITE: | ||
1780 | qlcnic_83xx_read_modify_write(p_dev, p_hdr); | ||
1781 | break; | ||
1782 | case QLC_83XX_OPCODE_SEQ_PAUSE: | ||
1783 | qlcnic_83xx_pause(p_hdr); | ||
1784 | break; | ||
1785 | case QLC_83XX_OPCODE_SEQ_END: | ||
1786 | qlcnic_83xx_seq_end(p_dev); | ||
1787 | break; | ||
1788 | case QLC_83XX_OPCODE_TMPL_END: | ||
1789 | qlcnic_83xx_template_end(p_dev); | ||
1790 | break; | ||
1791 | case QLC_83XX_OPCODE_POLL_READ_LIST: | ||
1792 | qlcnic_83xx_poll_read_list(p_dev, p_hdr); | ||
1793 | break; | ||
1794 | default: | ||
1795 | dev_err(&p_dev->pdev->dev, | ||
1796 | "%s: Unknown opcode 0x%04x in template %d\n", | ||
1797 | __func__, p_hdr->cmd, index); | ||
1798 | break; | ||
1799 | } | ||
1800 | entry += p_hdr->size; | ||
1801 | } | ||
1802 | p_dev->ahw->reset.seq_index = index; | ||
1803 | } | ||
1804 | |||
1805 | static void qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev) | ||
1806 | { | ||
1807 | p_dev->ahw->reset.seq_index = 0; | ||
1808 | |||
1809 | qlcnic_83xx_exec_template_cmd(p_dev, p_dev->ahw->reset.stop_offset); | ||
1810 | if (p_dev->ahw->reset.seq_end != 1) | ||
1811 | dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__); | ||
1812 | } | ||
1813 | |||
1814 | static void qlcnic_83xx_start_hw(struct qlcnic_adapter *p_dev) | ||
1815 | { | ||
1816 | qlcnic_83xx_exec_template_cmd(p_dev, p_dev->ahw->reset.start_offset); | ||
1817 | if (p_dev->ahw->reset.template_end != 1) | ||
1818 | dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__); | ||
1819 | } | ||
1820 | |||
1821 | static void qlcnic_83xx_init_hw(struct qlcnic_adapter *p_dev) | ||
1822 | { | ||
1823 | qlcnic_83xx_exec_template_cmd(p_dev, p_dev->ahw->reset.init_offset); | ||
1824 | if (p_dev->ahw->reset.seq_end != 1) | ||
1825 | dev_err(&p_dev->pdev->dev, "%s: failed\n", __func__); | ||
1826 | } | ||
1827 | |||
1828 | static int qlcnic_83xx_load_fw_image_from_host(struct qlcnic_adapter *adapter) | ||
1829 | { | ||
1830 | int err = -EIO; | ||
1831 | |||
1832 | if (request_firmware(&adapter->ahw->fw_info.fw, | ||
1833 | QLC_83XX_FW_FILE_NAME, &(adapter->pdev->dev))) { | ||
1834 | dev_err(&adapter->pdev->dev, | ||
1835 | "No file FW image, loading flash FW image.\n"); | ||
1836 | QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID, | ||
1837 | QLC_83XX_BOOT_FROM_FLASH); | ||
1838 | } else { | ||
1839 | if (qlcnic_83xx_copy_fw_file(adapter)) | ||
1840 | return err; | ||
1841 | QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID, | ||
1842 | QLC_83XX_BOOT_FROM_FILE); | ||
1843 | } | ||
1844 | |||
1845 | return 0; | ||
1846 | } | ||
1847 | |||
1848 | static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter) | ||
1849 | { | ||
1850 | u32 val; | ||
1851 | int err = -EIO; | ||
1852 | |||
1853 | qlcnic_83xx_stop_hw(adapter); | ||
1854 | |||
1855 | /* Collect FW register dump if required */ | ||
1856 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); | ||
1857 | if (!(val & QLC_83XX_IDC_GRACEFULL_RESET)) | ||
1858 | qlcnic_dump_fw(adapter); | ||
1859 | qlcnic_83xx_init_hw(adapter); | ||
1860 | |||
1861 | if (qlcnic_83xx_copy_bootloader(adapter)) | ||
1862 | return err; | ||
1863 | /* Boot either flash image or firmware image from host file system */ | ||
1864 | if (qlcnic_load_fw_file) { | ||
1865 | if (qlcnic_83xx_load_fw_image_from_host(adapter)) | ||
1866 | return err; | ||
1867 | } else { | ||
1868 | QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID, | ||
1869 | QLC_83XX_BOOT_FROM_FLASH); | ||
1870 | } | ||
1871 | |||
1872 | qlcnic_83xx_start_hw(adapter); | ||
1873 | if (qlcnic_83xx_check_hw_status(adapter)) | ||
1874 | return -EIO; | ||
1875 | |||
1876 | return 0; | ||
1877 | } | ||
1878 | |||
1879 | /** | ||
1880 | * qlcnic_83xx_config_default_opmode | ||
1881 | * | ||
1882 | * @adapter: adapter structure | ||
1883 | * | ||
1884 | * Configure default driver operating mode | ||
1885 | * | ||
1886 | * Returns: Error code or Success(0) | ||
1887 | * */ | ||
1888 | int qlcnic_83xx_config_default_opmode(struct qlcnic_adapter *adapter) | ||
1889 | { | ||
1890 | u32 op_mode; | ||
1891 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
1892 | |||
1893 | qlcnic_get_func_no(adapter); | ||
1894 | op_mode = QLCRDX(ahw, QLC_83XX_DRV_OP_MODE); | ||
1895 | |||
1896 | if (op_mode == QLC_83XX_DEFAULT_OPMODE) { | ||
1897 | adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver; | ||
1898 | ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; | ||
1899 | } else { | ||
1900 | return -EIO; | ||
1901 | } | ||
1902 | |||
1903 | return 0; | ||
1904 | } | ||
1905 | |||
1906 | int qlcnic_83xx_get_nic_configuration(struct qlcnic_adapter *adapter) | ||
1907 | { | ||
1908 | int err; | ||
1909 | struct qlcnic_info nic_info; | ||
1910 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
1911 | |||
1912 | memset(&nic_info, 0, sizeof(struct qlcnic_info)); | ||
1913 | err = qlcnic_get_nic_info(adapter, &nic_info, ahw->pci_func); | ||
1914 | if (err) | ||
1915 | return -EIO; | ||
1916 | |||
1917 | ahw->physical_port = (u8) nic_info.phys_port; | ||
1918 | ahw->switch_mode = nic_info.switch_mode; | ||
1919 | ahw->max_tx_ques = nic_info.max_tx_ques; | ||
1920 | ahw->max_rx_ques = nic_info.max_rx_ques; | ||
1921 | ahw->capabilities = nic_info.capabilities; | ||
1922 | ahw->max_mac_filters = nic_info.max_mac_filters; | ||
1923 | ahw->max_mtu = nic_info.max_mtu; | ||
1924 | |||
1925 | if (ahw->capabilities & BIT_23) | ||
1926 | ahw->nic_mode = QLC_83XX_VIRTUAL_NIC_MODE; | ||
1927 | else | ||
1928 | ahw->nic_mode = QLC_83XX_DEFAULT_MODE; | ||
1929 | |||
1930 | return ahw->nic_mode; | ||
1931 | } | ||
1932 | |||
1933 | static int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter) | ||
1934 | { | ||
1935 | int ret; | ||
1936 | |||
1937 | ret = qlcnic_83xx_get_nic_configuration(adapter); | ||
1938 | if (ret == -EIO) | ||
1939 | return -EIO; | ||
1940 | |||
1941 | if (ret == QLC_83XX_VIRTUAL_NIC_MODE) { | ||
1942 | if (qlcnic_83xx_config_vnic_opmode(adapter)) | ||
1943 | return -EIO; | ||
1944 | } else if (ret == QLC_83XX_DEFAULT_MODE) { | ||
1945 | if (qlcnic_83xx_config_default_opmode(adapter)) | ||
1946 | return -EIO; | ||
1947 | } | ||
1948 | |||
1949 | return 0; | ||
1950 | } | ||
1951 | |||
1952 | static void qlcnic_83xx_config_buff_descriptors(struct qlcnic_adapter *adapter) | ||
1953 | { | ||
1954 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
1955 | |||
1956 | if (ahw->port_type == QLCNIC_XGBE) { | ||
1957 | adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_10G; | ||
1958 | adapter->max_rxd = MAX_RCV_DESCRIPTORS_10G; | ||
1959 | adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G; | ||
1960 | adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G; | ||
1961 | |||
1962 | } else if (ahw->port_type == QLCNIC_GBE) { | ||
1963 | adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G; | ||
1964 | adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G; | ||
1965 | adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G; | ||
1966 | adapter->max_rxd = MAX_RCV_DESCRIPTORS_1G; | ||
1967 | } | ||
1968 | adapter->num_txd = MAX_CMD_DESCRIPTORS; | ||
1969 | adapter->max_rds_rings = MAX_RDS_RINGS; | ||
1970 | } | ||
1971 | |||
1972 | static int qlcnic_83xx_init_default_driver(struct qlcnic_adapter *adapter) | ||
1973 | { | ||
1974 | int err = -EIO; | ||
1975 | |||
1976 | qlcnic_83xx_get_minidump_template(adapter); | ||
1977 | if (qlcnic_83xx_get_port_info(adapter)) | ||
1978 | return err; | ||
1979 | |||
1980 | qlcnic_83xx_config_buff_descriptors(adapter); | ||
1981 | adapter->ahw->msix_supported = !!qlcnic_use_msi_x; | ||
1982 | adapter->flags |= QLCNIC_ADAPTER_INITIALIZED; | ||
1983 | |||
1984 | dev_info(&adapter->pdev->dev, "HAL Version: %d\n", | ||
1985 | adapter->ahw->fw_hal_version); | ||
1986 | |||
1987 | return 0; | ||
1988 | } | ||
1989 | |||
1990 | #define IS_QLC_83XX_USED(a, b, c) (((1 << a->portnum) & b) || ((c >> 6) & 0x1)) | ||
1991 | static void qlcnic_83xx_clear_function_resources(struct qlcnic_adapter *adapter) | ||
1992 | { | ||
1993 | struct qlcnic_cmd_args cmd; | ||
1994 | u32 presence_mask, audit_mask; | ||
1995 | int status; | ||
1996 | |||
1997 | presence_mask = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_PRESENCE); | ||
1998 | audit_mask = QLCRDX(adapter->ahw, QLC_83XX_IDC_DRV_AUDIT); | ||
1999 | |||
2000 | if (IS_QLC_83XX_USED(adapter, presence_mask, audit_mask)) { | ||
2001 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_STOP_NIC_FUNC); | ||
2002 | cmd.req.arg[1] = BIT_31; | ||
2003 | status = qlcnic_issue_cmd(adapter, &cmd); | ||
2004 | if (status) | ||
2005 | dev_err(&adapter->pdev->dev, | ||
2006 | "Failed to clean up the function resources\n"); | ||
2007 | qlcnic_free_mbx_args(&cmd); | ||
2008 | } | ||
2009 | } | ||
2010 | |||
2011 | int qlcnic_83xx_init(struct qlcnic_adapter *adapter) | ||
2012 | { | ||
2013 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2014 | |||
2015 | if (qlcnic_83xx_check_hw_status(adapter)) | ||
2016 | return -EIO; | ||
2017 | |||
2018 | /* Initilaize 83xx mailbox spinlock */ | ||
2019 | spin_lock_init(&ahw->mbx_lock); | ||
2020 | |||
2021 | set_bit(QLC_83XX_MBX_READY, &adapter->ahw->idc.status); | ||
2022 | qlcnic_83xx_clear_function_resources(adapter); | ||
2023 | |||
2024 | /* register for NIC IDC AEN Events */ | ||
2025 | qlcnic_83xx_register_nic_idc_func(adapter, 1); | ||
2026 | |||
2027 | if (!qlcnic_83xx_read_flash_descriptor_table(adapter)) | ||
2028 | qlcnic_83xx_read_flash_mfg_id(adapter); | ||
2029 | |||
2030 | if (qlcnic_83xx_idc_init(adapter)) | ||
2031 | return -EIO; | ||
2032 | |||
2033 | /* Configure default, SR-IOV or Virtual NIC mode of operation */ | ||
2034 | if (qlcnic_83xx_configure_opmode(adapter)) | ||
2035 | return -EIO; | ||
2036 | |||
2037 | /* Perform operating mode specific initialization */ | ||
2038 | if (adapter->nic_ops->init_driver(adapter)) | ||
2039 | return -EIO; | ||
2040 | |||
2041 | INIT_DELAYED_WORK(&adapter->idc_aen_work, qlcnic_83xx_idc_aen_work); | ||
2042 | |||
2043 | /* Periodically monitor device status */ | ||
2044 | qlcnic_83xx_idc_poll_dev_state(&adapter->fw_work.work); | ||
2045 | |||
2046 | return adapter->ahw->idc.err_code; | ||
2047 | } | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c new file mode 100644 index 000000000000..b0c3de9ede03 --- /dev/null +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c | |||
@@ -0,0 +1,225 @@ | |||
1 | /* | ||
2 | * QLogic qlcnic NIC Driver | ||
3 | * Copyright (c) 2009-2013 QLogic Corporation | ||
4 | * | ||
5 | * See LICENSE.qlcnic for copyright and licensing details. | ||
6 | */ | ||
7 | |||
8 | #include "qlcnic.h" | ||
9 | #include "qlcnic_hw.h" | ||
10 | |||
11 | int qlcnic_83xx_enable_vnic_mode(struct qlcnic_adapter *adapter, int lock) | ||
12 | { | ||
13 | if (lock) { | ||
14 | if (qlcnic_83xx_lock_driver(adapter)) | ||
15 | return -EBUSY; | ||
16 | } | ||
17 | QLCWRX(adapter->ahw, QLC_83XX_VNIC_STATE, QLCNIC_DEV_NPAR_OPER); | ||
18 | if (lock) | ||
19 | qlcnic_83xx_unlock_driver(adapter); | ||
20 | |||
21 | return 0; | ||
22 | } | ||
23 | |||
24 | int qlcnic_83xx_disable_vnic_mode(struct qlcnic_adapter *adapter, int lock) | ||
25 | { | ||
26 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
27 | |||
28 | if (lock) { | ||
29 | if (qlcnic_83xx_lock_driver(adapter)) | ||
30 | return -EBUSY; | ||
31 | } | ||
32 | |||
33 | QLCWRX(adapter->ahw, QLC_83XX_VNIC_STATE, QLCNIC_DEV_NPAR_NON_OPER); | ||
34 | ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER; | ||
35 | |||
36 | if (lock) | ||
37 | qlcnic_83xx_unlock_driver(adapter); | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter) | ||
43 | { | ||
44 | u8 id; | ||
45 | int i, ret = -EBUSY; | ||
46 | u32 data = QLCNIC_MGMT_FUNC; | ||
47 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
48 | |||
49 | if (qlcnic_83xx_lock_driver(adapter)) | ||
50 | return ret; | ||
51 | |||
52 | if (qlcnic_config_npars) { | ||
53 | for (i = 0; i < ahw->act_pci_func; i++) { | ||
54 | id = adapter->npars[i].pci_func; | ||
55 | if (id == ahw->pci_func) | ||
56 | continue; | ||
57 | data |= qlcnic_config_npars & | ||
58 | QLC_83XX_SET_FUNC_OPMODE(0x3, id); | ||
59 | } | ||
60 | } else { | ||
61 | data = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE); | ||
62 | data = (data & ~QLC_83XX_SET_FUNC_OPMODE(0x3, ahw->pci_func)) | | ||
63 | QLC_83XX_SET_FUNC_OPMODE(QLCNIC_MGMT_FUNC, | ||
64 | ahw->pci_func); | ||
65 | } | ||
66 | QLCWRX(adapter->ahw, QLC_83XX_DRV_OP_MODE, data); | ||
67 | |||
68 | qlcnic_83xx_unlock_driver(adapter); | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static void | ||
74 | qlcnic_83xx_config_vnic_buff_descriptors(struct qlcnic_adapter *adapter) | ||
75 | { | ||
76 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
77 | |||
78 | if (ahw->port_type == QLCNIC_XGBE) { | ||
79 | adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_VF; | ||
80 | adapter->max_rxd = MAX_RCV_DESCRIPTORS_VF; | ||
81 | adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G; | ||
82 | adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G; | ||
83 | |||
84 | } else if (ahw->port_type == QLCNIC_GBE) { | ||
85 | adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G; | ||
86 | adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G; | ||
87 | adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G; | ||
88 | adapter->max_rxd = MAX_RCV_DESCRIPTORS_1G; | ||
89 | } | ||
90 | adapter->num_txd = MAX_CMD_DESCRIPTORS; | ||
91 | adapter->max_rds_rings = MAX_RDS_RINGS; | ||
92 | } | ||
93 | |||
94 | |||
95 | /** | ||
96 | * qlcnic_83xx_init_mgmt_vnic | ||
97 | * | ||
98 | * @adapter: adapter structure | ||
99 | * Management virtual NIC sets the operational mode of other vNIC's and | ||
100 | * configures embedded switch (ESWITCH). | ||
101 | * Returns: Success(0) or error code. | ||
102 | * | ||
103 | **/ | ||
104 | static int qlcnic_83xx_init_mgmt_vnic(struct qlcnic_adapter *adapter) | ||
105 | { | ||
106 | int err = -EIO; | ||
107 | |||
108 | qlcnic_83xx_get_minidump_template(adapter); | ||
109 | if (!(adapter->flags & QLCNIC_ADAPTER_INITIALIZED)) { | ||
110 | if (qlcnic_init_pci_info(adapter)) | ||
111 | return err; | ||
112 | |||
113 | if (qlcnic_83xx_set_vnic_opmode(adapter)) | ||
114 | return err; | ||
115 | |||
116 | if (qlcnic_set_default_offload_settings(adapter)) | ||
117 | return err; | ||
118 | } else { | ||
119 | if (qlcnic_reset_npar_config(adapter)) | ||
120 | return err; | ||
121 | } | ||
122 | |||
123 | if (qlcnic_83xx_get_port_info(adapter)) | ||
124 | return err; | ||
125 | |||
126 | qlcnic_83xx_config_vnic_buff_descriptors(adapter); | ||
127 | adapter->ahw->msix_supported = !!qlcnic_use_msi_x; | ||
128 | adapter->flags |= QLCNIC_ADAPTER_INITIALIZED; | ||
129 | qlcnic_83xx_enable_vnic_mode(adapter, 1); | ||
130 | |||
131 | dev_info(&adapter->pdev->dev, "HAL Version: %d, Management function\n", | ||
132 | adapter->ahw->fw_hal_version); | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static int qlcnic_83xx_init_privileged_vnic(struct qlcnic_adapter *adapter) | ||
138 | { | ||
139 | int err = -EIO; | ||
140 | |||
141 | qlcnic_83xx_get_minidump_template(adapter); | ||
142 | if (qlcnic_83xx_get_port_info(adapter)) | ||
143 | return err; | ||
144 | |||
145 | qlcnic_83xx_config_vnic_buff_descriptors(adapter); | ||
146 | adapter->ahw->msix_supported = !!qlcnic_use_msi_x; | ||
147 | adapter->flags |= QLCNIC_ADAPTER_INITIALIZED; | ||
148 | |||
149 | dev_info(&adapter->pdev->dev, | ||
150 | "HAL Version: %d, Privileged function\n", | ||
151 | adapter->ahw->fw_hal_version); | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static int qlcnic_83xx_init_non_privileged_vnic(struct qlcnic_adapter *adapter) | ||
156 | { | ||
157 | int err = -EIO; | ||
158 | |||
159 | qlcnic_83xx_get_fw_version(adapter); | ||
160 | if (qlcnic_set_eswitch_port_config(adapter)) | ||
161 | return err; | ||
162 | |||
163 | if (qlcnic_83xx_get_port_info(adapter)) | ||
164 | return err; | ||
165 | |||
166 | qlcnic_83xx_config_vnic_buff_descriptors(adapter); | ||
167 | adapter->ahw->msix_supported = !!qlcnic_use_msi_x; | ||
168 | adapter->flags |= QLCNIC_ADAPTER_INITIALIZED; | ||
169 | |||
170 | dev_info(&adapter->pdev->dev, "HAL Version: %d, Virtual function\n", | ||
171 | adapter->ahw->fw_hal_version); | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * qlcnic_83xx_vnic_opmode | ||
178 | * | ||
179 | * @adapter: adapter structure | ||
180 | * Identify virtual NIC operational modes. | ||
181 | * | ||
182 | * Returns: Success(0) or error code. | ||
183 | * | ||
184 | **/ | ||
185 | int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter) | ||
186 | { | ||
187 | u32 op_mode, priv_level; | ||
188 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
189 | struct qlcnic_nic_template *nic_ops = adapter->nic_ops; | ||
190 | |||
191 | qlcnic_get_func_no(adapter); | ||
192 | op_mode = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE); | ||
193 | |||
194 | if (op_mode == QLC_83XX_DEFAULT_OPMODE) | ||
195 | priv_level = QLCNIC_MGMT_FUNC; | ||
196 | else | ||
197 | priv_level = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode, | ||
198 | ahw->pci_func); | ||
199 | |||
200 | if (priv_level == QLCNIC_NON_PRIV_FUNC) { | ||
201 | ahw->op_mode = QLCNIC_NON_PRIV_FUNC; | ||
202 | ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; | ||
203 | nic_ops->init_driver = qlcnic_83xx_init_non_privileged_vnic; | ||
204 | } else if (priv_level == QLCNIC_PRIV_FUNC) { | ||
205 | ahw->op_mode = QLCNIC_PRIV_FUNC; | ||
206 | ahw->idc.state_entry = qlcnic_83xx_idc_vnic_pf_entry; | ||
207 | nic_ops->init_driver = qlcnic_83xx_init_privileged_vnic; | ||
208 | } else if (priv_level == QLCNIC_MGMT_FUNC) { | ||
209 | ahw->op_mode = QLCNIC_MGMT_FUNC; | ||
210 | ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; | ||
211 | nic_ops->init_driver = qlcnic_83xx_init_mgmt_vnic; | ||
212 | } else { | ||
213 | return -EIO; | ||
214 | } | ||
215 | |||
216 | if (ahw->capabilities & BIT_23) | ||
217 | adapter->flags |= QLCNIC_ESWITCH_ENABLED; | ||
218 | else | ||
219 | adapter->flags &= ~QLCNIC_ESWITCH_ENABLED; | ||
220 | |||
221 | adapter->ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER; | ||
222 | adapter->ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO; | ||
223 | |||
224 | return 0; | ||
225 | } | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index b14b8f0787ea..a69097c6b84d 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c | |||
@@ -1,12 +1,92 @@ | |||
1 | /* | 1 | /* |
2 | * QLogic qlcnic NIC Driver | 2 | * QLogic qlcnic NIC Driver |
3 | * Copyright (c) 2009-2010 QLogic Corporation | 3 | * Copyright (c) 2009-2013 QLogic Corporation |
4 | * | 4 | * |
5 | * See LICENSE.qlcnic for copyright and licensing details. | 5 | * See LICENSE.qlcnic for copyright and licensing details. |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include "qlcnic.h" | 8 | #include "qlcnic.h" |
9 | 9 | ||
10 | static const struct qlcnic_mailbox_metadata qlcnic_mbx_tbl[] = { | ||
11 | {QLCNIC_CMD_CREATE_RX_CTX, 4, 1}, | ||
12 | {QLCNIC_CMD_DESTROY_RX_CTX, 2, 1}, | ||
13 | {QLCNIC_CMD_CREATE_TX_CTX, 4, 1}, | ||
14 | {QLCNIC_CMD_DESTROY_TX_CTX, 2, 1}, | ||
15 | {QLCNIC_CMD_INTRPT_TEST, 4, 1}, | ||
16 | {QLCNIC_CMD_SET_MTU, 4, 1}, | ||
17 | {QLCNIC_CMD_READ_PHY, 4, 2}, | ||
18 | {QLCNIC_CMD_WRITE_PHY, 5, 1}, | ||
19 | {QLCNIC_CMD_READ_HW_REG, 4, 1}, | ||
20 | {QLCNIC_CMD_GET_FLOW_CTL, 4, 2}, | ||
21 | {QLCNIC_CMD_SET_FLOW_CTL, 4, 1}, | ||
22 | {QLCNIC_CMD_READ_MAX_MTU, 4, 2}, | ||
23 | {QLCNIC_CMD_READ_MAX_LRO, 4, 2}, | ||
24 | {QLCNIC_CMD_MAC_ADDRESS, 4, 3}, | ||
25 | {QLCNIC_CMD_GET_PCI_INFO, 4, 1}, | ||
26 | {QLCNIC_CMD_GET_NIC_INFO, 4, 1}, | ||
27 | {QLCNIC_CMD_SET_NIC_INFO, 4, 1}, | ||
28 | {QLCNIC_CMD_GET_ESWITCH_CAPABILITY, 4, 3}, | ||
29 | {QLCNIC_CMD_TOGGLE_ESWITCH, 4, 1}, | ||
30 | {QLCNIC_CMD_GET_ESWITCH_STATUS, 4, 3}, | ||
31 | {QLCNIC_CMD_SET_PORTMIRRORING, 4, 1}, | ||
32 | {QLCNIC_CMD_CONFIGURE_ESWITCH, 4, 1}, | ||
33 | {QLCNIC_CMD_GET_MAC_STATS, 4, 1}, | ||
34 | {QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG, 4, 3}, | ||
35 | {QLCNIC_CMD_GET_ESWITCH_STATS, 5, 1}, | ||
36 | {QLCNIC_CMD_CONFIG_PORT, 4, 1}, | ||
37 | {QLCNIC_CMD_TEMP_SIZE, 4, 4}, | ||
38 | {QLCNIC_CMD_GET_TEMP_HDR, 4, 1}, | ||
39 | {QLCNIC_CMD_SET_DRV_VER, 4, 1}, | ||
40 | }; | ||
41 | |||
42 | static inline u32 qlcnic_get_cmd_signature(struct qlcnic_hardware_context *ahw) | ||
43 | { | ||
44 | return (ahw->pci_func & 0xff) | ((ahw->fw_hal_version & 0xff) << 8) | | ||
45 | (0xcafe << 16); | ||
46 | } | ||
47 | |||
48 | /* Allocate mailbox registers */ | ||
49 | int qlcnic_82xx_alloc_mbx_args(struct qlcnic_cmd_args *mbx, | ||
50 | struct qlcnic_adapter *adapter, u32 type) | ||
51 | { | ||
52 | int i, size; | ||
53 | const struct qlcnic_mailbox_metadata *mbx_tbl; | ||
54 | |||
55 | mbx_tbl = qlcnic_mbx_tbl; | ||
56 | size = ARRAY_SIZE(qlcnic_mbx_tbl); | ||
57 | for (i = 0; i < size; i++) { | ||
58 | if (type == mbx_tbl[i].cmd) { | ||
59 | mbx->req.num = mbx_tbl[i].in_args; | ||
60 | mbx->rsp.num = mbx_tbl[i].out_args; | ||
61 | mbx->req.arg = kcalloc(mbx->req.num, | ||
62 | sizeof(u32), GFP_ATOMIC); | ||
63 | if (!mbx->req.arg) | ||
64 | return -ENOMEM; | ||
65 | mbx->rsp.arg = kcalloc(mbx->rsp.num, | ||
66 | sizeof(u32), GFP_ATOMIC); | ||
67 | if (!mbx->rsp.arg) { | ||
68 | kfree(mbx->req.arg); | ||
69 | mbx->req.arg = NULL; | ||
70 | return -ENOMEM; | ||
71 | } | ||
72 | memset(mbx->req.arg, 0, sizeof(u32) * mbx->req.num); | ||
73 | memset(mbx->rsp.arg, 0, sizeof(u32) * mbx->rsp.num); | ||
74 | mbx->req.arg[0] = type; | ||
75 | break; | ||
76 | } | ||
77 | } | ||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | /* Free up mailbox registers */ | ||
82 | void qlcnic_free_mbx_args(struct qlcnic_cmd_args *cmd) | ||
83 | { | ||
84 | kfree(cmd->req.arg); | ||
85 | cmd->req.arg = NULL; | ||
86 | kfree(cmd->rsp.arg); | ||
87 | cmd->rsp.arg = NULL; | ||
88 | } | ||
89 | |||
10 | static int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func) | 90 | static int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func) |
11 | { | 91 | { |
12 | int i; | 92 | int i; |
@@ -38,194 +118,123 @@ qlcnic_poll_rsp(struct qlcnic_adapter *adapter) | |||
38 | return rsp; | 118 | return rsp; |
39 | } | 119 | } |
40 | 120 | ||
41 | void | 121 | int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter, |
42 | qlcnic_issue_cmd(struct qlcnic_adapter *adapter, struct qlcnic_cmd_args *cmd) | 122 | struct qlcnic_cmd_args *cmd) |
43 | { | 123 | { |
124 | int i; | ||
44 | u32 rsp; | 125 | u32 rsp; |
45 | u32 signature; | 126 | u32 signature; |
46 | struct pci_dev *pdev = adapter->pdev; | 127 | struct pci_dev *pdev = adapter->pdev; |
47 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 128 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
129 | const char *fmt; | ||
48 | 130 | ||
49 | signature = QLCNIC_CDRP_SIGNATURE_MAKE(ahw->pci_func, | 131 | signature = qlcnic_get_cmd_signature(ahw); |
50 | adapter->ahw->fw_hal_version); | ||
51 | 132 | ||
52 | /* Acquire semaphore before accessing CRB */ | 133 | /* Acquire semaphore before accessing CRB */ |
53 | if (qlcnic_api_lock(adapter)) { | 134 | if (qlcnic_api_lock(adapter)) { |
54 | cmd->rsp.cmd = QLCNIC_RCODE_TIMEOUT; | 135 | cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT; |
55 | return; | 136 | return cmd->rsp.arg[0]; |
56 | } | 137 | } |
57 | 138 | ||
58 | QLCWR32(adapter, QLCNIC_SIGN_CRB_OFFSET, signature); | 139 | QLCWR32(adapter, QLCNIC_SIGN_CRB_OFFSET, signature); |
59 | QLCWR32(adapter, QLCNIC_ARG1_CRB_OFFSET, cmd->req.arg1); | 140 | for (i = 1; i < QLCNIC_CDRP_MAX_ARGS; i++) |
60 | QLCWR32(adapter, QLCNIC_ARG2_CRB_OFFSET, cmd->req.arg2); | 141 | QLCWR32(adapter, QLCNIC_CDRP_ARG(i), cmd->req.arg[i]); |
61 | QLCWR32(adapter, QLCNIC_ARG3_CRB_OFFSET, cmd->req.arg3); | ||
62 | QLCWR32(adapter, QLCNIC_CDRP_CRB_OFFSET, | 142 | QLCWR32(adapter, QLCNIC_CDRP_CRB_OFFSET, |
63 | QLCNIC_CDRP_FORM_CMD(cmd->req.cmd)); | 143 | QLCNIC_CDRP_FORM_CMD(cmd->req.arg[0])); |
64 | |||
65 | rsp = qlcnic_poll_rsp(adapter); | 144 | rsp = qlcnic_poll_rsp(adapter); |
66 | 145 | ||
67 | if (rsp == QLCNIC_CDRP_RSP_TIMEOUT) { | 146 | if (rsp == QLCNIC_CDRP_RSP_TIMEOUT) { |
68 | dev_err(&pdev->dev, "CDRP response timeout.\n"); | 147 | dev_err(&pdev->dev, "card response timeout.\n"); |
69 | cmd->rsp.cmd = QLCNIC_RCODE_TIMEOUT; | 148 | cmd->rsp.arg[0] = QLCNIC_RCODE_TIMEOUT; |
70 | } else if (rsp == QLCNIC_CDRP_RSP_FAIL) { | 149 | } else if (rsp == QLCNIC_CDRP_RSP_FAIL) { |
71 | cmd->rsp.cmd = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); | 150 | cmd->rsp.arg[0] = QLCRD32(adapter, QLCNIC_CDRP_ARG(1)); |
72 | switch (cmd->rsp.cmd) { | 151 | switch (cmd->rsp.arg[0]) { |
73 | case QLCNIC_RCODE_INVALID_ARGS: | 152 | case QLCNIC_RCODE_INVALID_ARGS: |
74 | dev_err(&pdev->dev, "CDRP invalid args: 0x%x.\n", | 153 | fmt = "CDRP invalid args: [%d]\n"; |
75 | cmd->rsp.cmd); | ||
76 | break; | 154 | break; |
77 | case QLCNIC_RCODE_NOT_SUPPORTED: | 155 | case QLCNIC_RCODE_NOT_SUPPORTED: |
78 | case QLCNIC_RCODE_NOT_IMPL: | 156 | case QLCNIC_RCODE_NOT_IMPL: |
79 | dev_err(&pdev->dev, | 157 | fmt = "CDRP command not supported: [%d]\n"; |
80 | "CDRP command not supported: 0x%x.\n", | ||
81 | cmd->rsp.cmd); | ||
82 | break; | 158 | break; |
83 | case QLCNIC_RCODE_NOT_PERMITTED: | 159 | case QLCNIC_RCODE_NOT_PERMITTED: |
84 | dev_err(&pdev->dev, | 160 | fmt = "CDRP requested action not permitted: [%d]\n"; |
85 | "CDRP requested action not permitted: 0x%x.\n", | ||
86 | cmd->rsp.cmd); | ||
87 | break; | 161 | break; |
88 | case QLCNIC_RCODE_INVALID: | 162 | case QLCNIC_RCODE_INVALID: |
89 | dev_err(&pdev->dev, | 163 | fmt = "CDRP invalid or unknown cmd received: [%d]\n"; |
90 | "CDRP invalid or unknown cmd received: 0x%x.\n", | ||
91 | cmd->rsp.cmd); | ||
92 | break; | 164 | break; |
93 | case QLCNIC_RCODE_TIMEOUT: | 165 | case QLCNIC_RCODE_TIMEOUT: |
94 | dev_err(&pdev->dev, "CDRP command timeout: 0x%x.\n", | 166 | fmt = "CDRP command timeout: [%d]\n"; |
95 | cmd->rsp.cmd); | ||
96 | break; | 167 | break; |
97 | default: | 168 | default: |
98 | dev_err(&pdev->dev, "CDRP command failed: 0x%x.\n", | 169 | fmt = "CDRP command failed: [%d]\n"; |
99 | cmd->rsp.cmd); | 170 | break; |
100 | } | 171 | } |
101 | } else if (rsp == QLCNIC_CDRP_RSP_OK) { | 172 | dev_err(&pdev->dev, fmt, cmd->rsp.arg[0]); |
102 | cmd->rsp.cmd = QLCNIC_RCODE_SUCCESS; | 173 | } else if (rsp == QLCNIC_CDRP_RSP_OK) |
103 | if (cmd->rsp.arg2) | 174 | cmd->rsp.arg[0] = QLCNIC_RCODE_SUCCESS; |
104 | cmd->rsp.arg2 = QLCRD32(adapter, | 175 | |
105 | QLCNIC_ARG2_CRB_OFFSET); | 176 | for (i = 1; i < cmd->rsp.num; i++) |
106 | if (cmd->rsp.arg3) | 177 | cmd->rsp.arg[i] = QLCRD32(adapter, QLCNIC_CDRP_ARG(i)); |
107 | cmd->rsp.arg3 = QLCRD32(adapter, | ||
108 | QLCNIC_ARG3_CRB_OFFSET); | ||
109 | } | ||
110 | if (cmd->rsp.arg1) | ||
111 | cmd->rsp.arg1 = QLCRD32(adapter, QLCNIC_ARG1_CRB_OFFSET); | ||
112 | 178 | ||
113 | /* Release semaphore */ | 179 | /* Release semaphore */ |
114 | qlcnic_api_unlock(adapter); | 180 | qlcnic_api_unlock(adapter); |
115 | 181 | return cmd->rsp.arg[0]; | |
116 | } | ||
117 | |||
118 | static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u32 temp_size) | ||
119 | { | ||
120 | uint64_t sum = 0; | ||
121 | int count = temp_size / sizeof(uint32_t); | ||
122 | while (count-- > 0) | ||
123 | sum += *temp_buffer++; | ||
124 | while (sum >> 32) | ||
125 | sum = (sum & 0xFFFFFFFF) + (sum >> 32); | ||
126 | return ~sum; | ||
127 | } | 182 | } |
128 | 183 | ||
129 | int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) | 184 | int qlcnic_fw_cmd_set_drv_version(struct qlcnic_adapter *adapter) |
130 | { | 185 | { |
131 | int err, i; | ||
132 | void *tmp_addr; | ||
133 | u32 temp_size, version, csum, *template; | ||
134 | __le32 *tmp_buf; | ||
135 | struct qlcnic_cmd_args cmd; | 186 | struct qlcnic_cmd_args cmd; |
136 | struct qlcnic_hardware_context *ahw; | 187 | u32 arg1, arg2, arg3; |
137 | struct qlcnic_dump_template_hdr *tmpl_hdr; | 188 | char drv_string[12]; |
138 | dma_addr_t tmp_addr_t = 0; | 189 | int err = 0; |
139 | |||
140 | ahw = adapter->ahw; | ||
141 | memset(&cmd, 0, sizeof(cmd)); | ||
142 | cmd.req.cmd = QLCNIC_CDRP_CMD_TEMP_SIZE; | ||
143 | memset(&cmd.rsp, 1, sizeof(struct _cdrp_cmd)); | ||
144 | qlcnic_issue_cmd(adapter, &cmd); | ||
145 | if (cmd.rsp.cmd != QLCNIC_RCODE_SUCCESS) { | ||
146 | dev_info(&adapter->pdev->dev, | ||
147 | "Can't get template size %d\n", cmd.rsp.cmd); | ||
148 | err = -EIO; | ||
149 | return err; | ||
150 | } | ||
151 | temp_size = cmd.rsp.arg2; | ||
152 | version = cmd.rsp.arg3; | ||
153 | dev_info(&adapter->pdev->dev, | ||
154 | "minidump template version = 0x%x", version); | ||
155 | if (!temp_size) | ||
156 | return -EIO; | ||
157 | 190 | ||
158 | tmp_addr = dma_alloc_coherent(&adapter->pdev->dev, temp_size, | 191 | memset(drv_string, 0, sizeof(drv_string)); |
159 | &tmp_addr_t, GFP_KERNEL); | 192 | snprintf(drv_string, sizeof(drv_string), "%d"".""%d"".""%d", |
160 | if (!tmp_addr) { | 193 | _QLCNIC_LINUX_MAJOR, _QLCNIC_LINUX_MINOR, |
161 | dev_err(&adapter->pdev->dev, | 194 | _QLCNIC_LINUX_SUBVERSION); |
162 | "Can't get memory for FW dump template\n"); | ||
163 | return -ENOMEM; | ||
164 | } | ||
165 | memset(&cmd.rsp, 0, sizeof(struct _cdrp_cmd)); | ||
166 | cmd.req.cmd = QLCNIC_CDRP_CMD_GET_TEMP_HDR; | ||
167 | cmd.req.arg1 = LSD(tmp_addr_t); | ||
168 | cmd.req.arg2 = MSD(tmp_addr_t); | ||
169 | cmd.req.arg3 = temp_size; | ||
170 | qlcnic_issue_cmd(adapter, &cmd); | ||
171 | |||
172 | err = cmd.rsp.cmd; | ||
173 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
174 | dev_err(&adapter->pdev->dev, | ||
175 | "Failed to get mini dump template header %d\n", err); | ||
176 | err = -EIO; | ||
177 | goto error; | ||
178 | } | ||
179 | ahw->fw_dump.tmpl_hdr = vzalloc(temp_size); | ||
180 | if (!ahw->fw_dump.tmpl_hdr) { | ||
181 | err = -EIO; | ||
182 | goto error; | ||
183 | } | ||
184 | tmp_buf = tmp_addr; | ||
185 | template = (u32 *) ahw->fw_dump.tmpl_hdr; | ||
186 | for (i = 0; i < temp_size/sizeof(u32); i++) | ||
187 | *template++ = __le32_to_cpu(*tmp_buf++); | ||
188 | 195 | ||
189 | csum = qlcnic_temp_checksum((u32 *)ahw->fw_dump.tmpl_hdr, temp_size); | 196 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_DRV_VER); |
190 | if (csum) { | 197 | memcpy(&arg1, drv_string, sizeof(u32)); |
191 | dev_err(&adapter->pdev->dev, | 198 | memcpy(&arg2, drv_string + 4, sizeof(u32)); |
192 | "Template header checksum validation failed\n"); | 199 | memcpy(&arg3, drv_string + 8, sizeof(u32)); |
193 | err = -EIO; | 200 | |
194 | goto error; | 201 | cmd.req.arg[1] = arg1; |
202 | cmd.req.arg[2] = arg2; | ||
203 | cmd.req.arg[3] = arg3; | ||
204 | |||
205 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
206 | if (err) { | ||
207 | dev_info(&adapter->pdev->dev, | ||
208 | "Failed to set driver version in firmware\n"); | ||
209 | return -EIO; | ||
195 | } | 210 | } |
196 | 211 | ||
197 | tmpl_hdr = ahw->fw_dump.tmpl_hdr; | 212 | return 0; |
198 | tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF; | ||
199 | ahw->fw_dump.enable = 1; | ||
200 | error: | ||
201 | dma_free_coherent(&adapter->pdev->dev, temp_size, tmp_addr, tmp_addr_t); | ||
202 | return err; | ||
203 | } | 213 | } |
204 | 214 | ||
205 | int | 215 | int |
206 | qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu) | 216 | qlcnic_fw_cmd_set_mtu(struct qlcnic_adapter *adapter, int mtu) |
207 | { | 217 | { |
218 | int err = 0; | ||
208 | struct qlcnic_cmd_args cmd; | 219 | struct qlcnic_cmd_args cmd; |
209 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | 220 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; |
210 | 221 | ||
211 | memset(&cmd, 0, sizeof(cmd)); | 222 | if (recv_ctx->state != QLCNIC_HOST_CTX_STATE_ACTIVE) |
212 | cmd.req.cmd = QLCNIC_CDRP_CMD_SET_MTU; | 223 | return err; |
213 | cmd.req.arg1 = recv_ctx->context_id; | 224 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_MTU); |
214 | cmd.req.arg2 = mtu; | 225 | cmd.req.arg[1] = recv_ctx->context_id; |
215 | cmd.req.arg3 = 0; | 226 | cmd.req.arg[2] = mtu; |
216 | if (recv_ctx->state == QLCNIC_HOST_CTX_STATE_ACTIVE) { | ||
217 | qlcnic_issue_cmd(adapter, &cmd); | ||
218 | if (cmd.rsp.cmd) { | ||
219 | dev_err(&adapter->pdev->dev, "Failed to set mtu\n"); | ||
220 | return -EIO; | ||
221 | } | ||
222 | } | ||
223 | 227 | ||
224 | return 0; | 228 | err = qlcnic_issue_cmd(adapter, &cmd); |
229 | if (err) { | ||
230 | dev_err(&adapter->pdev->dev, "Failed to set mtu\n"); | ||
231 | err = -EIO; | ||
232 | } | ||
233 | qlcnic_free_mbx_args(&cmd); | ||
234 | return err; | ||
225 | } | 235 | } |
226 | 236 | ||
227 | static int | 237 | int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) |
228 | qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | ||
229 | { | 238 | { |
230 | void *addr; | 239 | void *addr; |
231 | struct qlcnic_hostrq_rx_ctx *prq; | 240 | struct qlcnic_hostrq_rx_ctx *prq; |
@@ -242,10 +251,10 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
242 | u64 phys_addr; | 251 | u64 phys_addr; |
243 | 252 | ||
244 | u8 i, nrds_rings, nsds_rings; | 253 | u8 i, nrds_rings, nsds_rings; |
254 | u16 temp_u16; | ||
245 | size_t rq_size, rsp_size; | 255 | size_t rq_size, rsp_size; |
246 | u32 cap, reg, val, reg2; | 256 | u32 cap, reg, val, reg2; |
247 | int err; | 257 | int err; |
248 | u16 temp; | ||
249 | 258 | ||
250 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | 259 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; |
251 | 260 | ||
@@ -279,11 +288,8 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
279 | | QLCNIC_CAP0_VALIDOFF); | 288 | | QLCNIC_CAP0_VALIDOFF); |
280 | cap |= (QLCNIC_CAP0_JUMBO_CONTIGUOUS | QLCNIC_CAP0_LRO_CONTIGUOUS); | 289 | cap |= (QLCNIC_CAP0_JUMBO_CONTIGUOUS | QLCNIC_CAP0_LRO_CONTIGUOUS); |
281 | 290 | ||
282 | if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) | 291 | temp_u16 = offsetof(struct qlcnic_hostrq_rx_ctx, msix_handler); |
283 | cap |= QLCNIC_CAP0_LRO_MSS; | 292 | prq->valid_field_offset = cpu_to_le16(temp_u16); |
284 | |||
285 | temp = offsetof(struct qlcnic_hostrq_rx_ctx, msix_handler); | ||
286 | prq->valid_field_offset = cpu_to_le16(temp); | ||
287 | prq->txrx_sds_binding = nsds_rings - 1; | 293 | prq->txrx_sds_binding = nsds_rings - 1; |
288 | 294 | ||
289 | prq->capabilities[0] = cpu_to_le32(cap); | 295 | prq->capabilities[0] = cpu_to_le32(cap); |
@@ -329,20 +335,17 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
329 | } | 335 | } |
330 | 336 | ||
331 | phys_addr = hostrq_phys_addr; | 337 | phys_addr = hostrq_phys_addr; |
332 | memset(&cmd, 0, sizeof(cmd)); | 338 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_RX_CTX); |
333 | cmd.req.arg1 = (u32) (phys_addr >> 32); | 339 | cmd.req.arg[1] = MSD(phys_addr); |
334 | cmd.req.arg2 = (u32) (phys_addr & 0xffffffff); | 340 | cmd.req.arg[2] = LSD(phys_addr); |
335 | cmd.req.arg3 = rq_size; | 341 | cmd.req.arg[3] = rq_size; |
336 | cmd.req.cmd = QLCNIC_CDRP_CMD_CREATE_RX_CTX; | 342 | err = qlcnic_issue_cmd(adapter, &cmd); |
337 | qlcnic_issue_cmd(adapter, &cmd); | ||
338 | err = cmd.rsp.cmd; | ||
339 | if (err) { | 343 | if (err) { |
340 | dev_err(&adapter->pdev->dev, | 344 | dev_err(&adapter->pdev->dev, |
341 | "Failed to create rx ctx in firmware%d\n", err); | 345 | "Failed to create rx ctx in firmware%d\n", err); |
342 | goto out_free_rsp; | 346 | goto out_free_rsp; |
343 | } | 347 | } |
344 | 348 | ||
345 | |||
346 | prsp_rds = ((struct qlcnic_cardrsp_rds_ring *) | 349 | prsp_rds = ((struct qlcnic_cardrsp_rds_ring *) |
347 | &prsp->data[le32_to_cpu(prsp->rds_ring_offset)]); | 350 | &prsp->data[le32_to_cpu(prsp->rds_ring_offset)]); |
348 | 351 | ||
@@ -373,6 +376,7 @@ qlcnic_fw_cmd_create_rx_ctx(struct qlcnic_adapter *adapter) | |||
373 | out_free_rsp: | 376 | out_free_rsp: |
374 | dma_free_coherent(&adapter->pdev->dev, rsp_size, prsp, | 377 | dma_free_coherent(&adapter->pdev->dev, rsp_size, prsp, |
375 | cardrsp_phys_addr); | 378 | cardrsp_phys_addr); |
379 | qlcnic_free_mbx_args(&cmd); | ||
376 | out_free_rq: | 380 | out_free_rq: |
377 | dma_free_coherent(&adapter->pdev->dev, rq_size, prq, hostrq_phys_addr); | 381 | dma_free_coherent(&adapter->pdev->dev, rq_size, prq, hostrq_phys_addr); |
378 | return err; | 382 | return err; |
@@ -381,24 +385,24 @@ out_free_rq: | |||
381 | static void | 385 | static void |
382 | qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter) | 386 | qlcnic_fw_cmd_destroy_rx_ctx(struct qlcnic_adapter *adapter) |
383 | { | 387 | { |
388 | int err; | ||
384 | struct qlcnic_cmd_args cmd; | 389 | struct qlcnic_cmd_args cmd; |
385 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | 390 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; |
386 | 391 | ||
387 | memset(&cmd, 0, sizeof(cmd)); | 392 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_RX_CTX); |
388 | cmd.req.arg1 = recv_ctx->context_id; | 393 | cmd.req.arg[1] = recv_ctx->context_id; |
389 | cmd.req.arg2 = QLCNIC_DESTROY_CTX_RESET; | 394 | err = qlcnic_issue_cmd(adapter, &cmd); |
390 | cmd.req.arg3 = 0; | 395 | if (err) |
391 | cmd.req.cmd = QLCNIC_CDRP_CMD_DESTROY_RX_CTX; | ||
392 | qlcnic_issue_cmd(adapter, &cmd); | ||
393 | if (cmd.rsp.cmd) | ||
394 | dev_err(&adapter->pdev->dev, | 396 | dev_err(&adapter->pdev->dev, |
395 | "Failed to destroy rx ctx in firmware\n"); | 397 | "Failed to destroy rx ctx in firmware\n"); |
396 | 398 | ||
397 | recv_ctx->state = QLCNIC_HOST_CTX_STATE_FREED; | 399 | recv_ctx->state = QLCNIC_HOST_CTX_STATE_FREED; |
400 | qlcnic_free_mbx_args(&cmd); | ||
398 | } | 401 | } |
399 | 402 | ||
400 | static int | 403 | int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter, |
401 | qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) | 404 | struct qlcnic_host_tx_ring *tx_ring, |
405 | int ring) | ||
402 | { | 406 | { |
403 | struct qlcnic_hostrq_tx_ctx *prq; | 407 | struct qlcnic_hostrq_tx_ctx *prq; |
404 | struct qlcnic_hostrq_cds_ring *prq_cds; | 408 | struct qlcnic_hostrq_cds_ring *prq_cds; |
@@ -410,7 +414,6 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) | |||
410 | int err; | 414 | int err; |
411 | u64 phys_addr; | 415 | u64 phys_addr; |
412 | dma_addr_t rq_phys_addr, rsp_phys_addr; | 416 | dma_addr_t rq_phys_addr, rsp_phys_addr; |
413 | struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; | ||
414 | 417 | ||
415 | /* reset host resources */ | 418 | /* reset host resources */ |
416 | tx_ring->producer = 0; | 419 | tx_ring->producer = 0; |
@@ -445,9 +448,9 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) | |||
445 | 448 | ||
446 | prq->host_int_crb_mode = | 449 | prq->host_int_crb_mode = |
447 | cpu_to_le32(QLCNIC_HOST_INT_CRB_MODE_SHARED); | 450 | cpu_to_le32(QLCNIC_HOST_INT_CRB_MODE_SHARED); |
451 | prq->msi_index = 0; | ||
448 | 452 | ||
449 | prq->interrupt_ctl = 0; | 453 | prq->interrupt_ctl = 0; |
450 | prq->msi_index = 0; | ||
451 | prq->cmd_cons_dma_addr = cpu_to_le64(tx_ring->hw_cons_phys_addr); | 454 | prq->cmd_cons_dma_addr = cpu_to_le64(tx_ring->hw_cons_phys_addr); |
452 | 455 | ||
453 | prq_cds = &prq->cds_ring; | 456 | prq_cds = &prq->cds_ring; |
@@ -456,19 +459,17 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) | |||
456 | prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc); | 459 | prq_cds->ring_size = cpu_to_le32(tx_ring->num_desc); |
457 | 460 | ||
458 | phys_addr = rq_phys_addr; | 461 | phys_addr = rq_phys_addr; |
459 | memset(&cmd, 0, sizeof(cmd)); | 462 | |
460 | cmd.req.arg1 = (u32)(phys_addr >> 32); | 463 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CREATE_TX_CTX); |
461 | cmd.req.arg2 = ((u32)phys_addr & 0xffffffff); | 464 | cmd.req.arg[1] = MSD(phys_addr); |
462 | cmd.req.arg3 = rq_size; | 465 | cmd.req.arg[2] = LSD(phys_addr); |
463 | cmd.req.cmd = QLCNIC_CDRP_CMD_CREATE_TX_CTX; | 466 | cmd.req.arg[3] = rq_size; |
464 | qlcnic_issue_cmd(adapter, &cmd); | 467 | err = qlcnic_issue_cmd(adapter, &cmd); |
465 | err = cmd.rsp.cmd; | ||
466 | 468 | ||
467 | if (err == QLCNIC_RCODE_SUCCESS) { | 469 | if (err == QLCNIC_RCODE_SUCCESS) { |
468 | temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); | 470 | temp = le32_to_cpu(prsp->cds_ring.host_producer_crb); |
469 | tx_ring->crb_cmd_producer = adapter->ahw->pci_base0 + temp; | 471 | tx_ring->crb_cmd_producer = adapter->ahw->pci_base0 + temp; |
470 | 472 | tx_ring->ctx_id = le16_to_cpu(prsp->context_id); | |
471 | adapter->tx_ring->ctx_id = le16_to_cpu(prsp->context_id); | ||
472 | } else { | 473 | } else { |
473 | dev_err(&adapter->pdev->dev, | 474 | dev_err(&adapter->pdev->dev, |
474 | "Failed to create tx ctx in firmware%d\n", err); | 475 | "Failed to create tx ctx in firmware%d\n", err); |
@@ -476,76 +477,81 @@ qlcnic_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter) | |||
476 | } | 477 | } |
477 | 478 | ||
478 | dma_free_coherent(&adapter->pdev->dev, rsp_size, rsp_addr, | 479 | dma_free_coherent(&adapter->pdev->dev, rsp_size, rsp_addr, |
479 | rsp_phys_addr); | 480 | rsp_phys_addr); |
480 | 481 | ||
481 | out_free_rq: | 482 | out_free_rq: |
482 | dma_free_coherent(&adapter->pdev->dev, rq_size, rq_addr, rq_phys_addr); | 483 | dma_free_coherent(&adapter->pdev->dev, rq_size, rq_addr, rq_phys_addr); |
484 | qlcnic_free_mbx_args(&cmd); | ||
483 | 485 | ||
484 | return err; | 486 | return err; |
485 | } | 487 | } |
486 | 488 | ||
487 | static void | 489 | static void |
488 | qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter) | 490 | qlcnic_fw_cmd_destroy_tx_ctx(struct qlcnic_adapter *adapter, |
491 | struct qlcnic_host_tx_ring *tx_ring) | ||
489 | { | 492 | { |
490 | struct qlcnic_cmd_args cmd; | 493 | struct qlcnic_cmd_args cmd; |
491 | 494 | ||
492 | memset(&cmd, 0, sizeof(cmd)); | 495 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_DESTROY_TX_CTX); |
493 | cmd.req.arg1 = adapter->tx_ring->ctx_id; | 496 | cmd.req.arg[1] = tx_ring->ctx_id; |
494 | cmd.req.arg2 = QLCNIC_DESTROY_CTX_RESET; | 497 | if (qlcnic_issue_cmd(adapter, &cmd)) |
495 | cmd.req.arg3 = 0; | ||
496 | cmd.req.cmd = QLCNIC_CDRP_CMD_DESTROY_TX_CTX; | ||
497 | qlcnic_issue_cmd(adapter, &cmd); | ||
498 | if (cmd.rsp.cmd) | ||
499 | dev_err(&adapter->pdev->dev, | 498 | dev_err(&adapter->pdev->dev, |
500 | "Failed to destroy tx ctx in firmware\n"); | 499 | "Failed to destroy tx ctx in firmware\n"); |
500 | qlcnic_free_mbx_args(&cmd); | ||
501 | } | 501 | } |
502 | 502 | ||
503 | int | 503 | int |
504 | qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config) | 504 | qlcnic_fw_cmd_set_port(struct qlcnic_adapter *adapter, u32 config) |
505 | { | 505 | { |
506 | int err; | ||
506 | struct qlcnic_cmd_args cmd; | 507 | struct qlcnic_cmd_args cmd; |
507 | 508 | ||
508 | memset(&cmd, 0, sizeof(cmd)); | 509 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIG_PORT); |
509 | cmd.req.arg1 = config; | 510 | cmd.req.arg[1] = config; |
510 | cmd.req.cmd = QLCNIC_CDRP_CMD_CONFIG_PORT; | 511 | err = qlcnic_issue_cmd(adapter, &cmd); |
511 | qlcnic_issue_cmd(adapter, &cmd); | 512 | qlcnic_free_mbx_args(&cmd); |
512 | 513 | return err; | |
513 | return cmd.rsp.cmd; | ||
514 | } | 514 | } |
515 | 515 | ||
516 | int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter) | 516 | int qlcnic_alloc_hw_resources(struct qlcnic_adapter *adapter) |
517 | { | 517 | { |
518 | void *addr; | 518 | void *addr; |
519 | int err; | 519 | int err, ring; |
520 | int ring; | ||
521 | struct qlcnic_recv_context *recv_ctx; | 520 | struct qlcnic_recv_context *recv_ctx; |
522 | struct qlcnic_host_rds_ring *rds_ring; | 521 | struct qlcnic_host_rds_ring *rds_ring; |
523 | struct qlcnic_host_sds_ring *sds_ring; | 522 | struct qlcnic_host_sds_ring *sds_ring; |
524 | struct qlcnic_host_tx_ring *tx_ring; | 523 | struct qlcnic_host_tx_ring *tx_ring; |
524 | __le32 *ptr; | ||
525 | 525 | ||
526 | struct pci_dev *pdev = adapter->pdev; | 526 | struct pci_dev *pdev = adapter->pdev; |
527 | 527 | ||
528 | recv_ctx = adapter->recv_ctx; | 528 | recv_ctx = adapter->recv_ctx; |
529 | tx_ring = adapter->tx_ring; | ||
530 | 529 | ||
531 | tx_ring->hw_consumer = (__le32 *) dma_alloc_coherent(&pdev->dev, | 530 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { |
532 | sizeof(u32), &tx_ring->hw_cons_phys_addr, GFP_KERNEL); | 531 | tx_ring = &adapter->tx_ring[ring]; |
533 | if (tx_ring->hw_consumer == NULL) { | 532 | ptr = (__le32 *)dma_alloc_coherent(&pdev->dev, sizeof(u32), |
534 | dev_err(&pdev->dev, "failed to allocate tx consumer\n"); | 533 | &tx_ring->hw_cons_phys_addr, |
535 | return -ENOMEM; | 534 | GFP_KERNEL); |
536 | } | ||
537 | 535 | ||
538 | /* cmd desc ring */ | 536 | if (ptr == NULL) { |
539 | addr = dma_alloc_coherent(&pdev->dev, TX_DESC_RINGSIZE(tx_ring), | 537 | dev_err(&pdev->dev, "failed to allocate tx consumer\n"); |
540 | &tx_ring->phys_addr, GFP_KERNEL); | 538 | return -ENOMEM; |
539 | } | ||
540 | tx_ring->hw_consumer = ptr; | ||
541 | /* cmd desc ring */ | ||
542 | addr = dma_alloc_coherent(&pdev->dev, TX_DESC_RINGSIZE(tx_ring), | ||
543 | &tx_ring->phys_addr, | ||
544 | GFP_KERNEL); | ||
541 | 545 | ||
542 | if (addr == NULL) { | 546 | if (addr == NULL) { |
543 | dev_err(&pdev->dev, "failed to allocate tx desc ring\n"); | 547 | dev_err(&pdev->dev, |
544 | err = -ENOMEM; | 548 | "failed to allocate tx desc ring\n"); |
545 | goto err_out_free; | 549 | err = -ENOMEM; |
546 | } | 550 | goto err_out_free; |
551 | } | ||
547 | 552 | ||
548 | tx_ring->desc_head = addr; | 553 | tx_ring->desc_head = addr; |
554 | } | ||
549 | 555 | ||
550 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | 556 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { |
551 | rds_ring = &recv_ctx->rds_rings[ring]; | 557 | rds_ring = &recv_ctx->rds_rings[ring]; |
@@ -584,36 +590,70 @@ err_out_free: | |||
584 | return err; | 590 | return err; |
585 | } | 591 | } |
586 | 592 | ||
587 | 593 | int qlcnic_fw_create_ctx(struct qlcnic_adapter *dev) | |
588 | int qlcnic_fw_create_ctx(struct qlcnic_adapter *adapter) | ||
589 | { | 594 | { |
590 | int err; | 595 | int i, err, ring; |
591 | 596 | ||
592 | if (adapter->flags & QLCNIC_NEED_FLR) { | 597 | if (dev->flags & QLCNIC_NEED_FLR) { |
593 | pci_reset_function(adapter->pdev); | 598 | pci_reset_function(dev->pdev); |
594 | adapter->flags &= ~QLCNIC_NEED_FLR; | 599 | dev->flags &= ~QLCNIC_NEED_FLR; |
595 | } | 600 | } |
596 | 601 | ||
597 | err = qlcnic_fw_cmd_create_rx_ctx(adapter); | 602 | if (qlcnic_83xx_check(dev) && (dev->flags & QLCNIC_MSIX_ENABLED)) { |
598 | if (err) | 603 | if (dev->ahw->diag_test != QLCNIC_LOOPBACK_TEST) { |
599 | return err; | 604 | err = qlcnic_83xx_config_intrpt(dev, 1); |
605 | if (err) | ||
606 | return err; | ||
607 | } | ||
608 | } | ||
600 | 609 | ||
601 | err = qlcnic_fw_cmd_create_tx_ctx(adapter); | 610 | err = qlcnic_fw_cmd_create_rx_ctx(dev); |
602 | if (err) { | 611 | if (err) |
603 | qlcnic_fw_cmd_destroy_rx_ctx(adapter); | 612 | goto err_out; |
604 | return err; | 613 | |
614 | for (ring = 0; ring < dev->max_drv_tx_rings; ring++) { | ||
615 | err = qlcnic_fw_cmd_create_tx_ctx(dev, | ||
616 | &dev->tx_ring[ring], | ||
617 | ring); | ||
618 | if (err) { | ||
619 | qlcnic_fw_cmd_destroy_rx_ctx(dev); | ||
620 | if (ring == 0) | ||
621 | goto err_out; | ||
622 | |||
623 | for (i = 0; i < ring; i++) | ||
624 | qlcnic_fw_cmd_destroy_tx_ctx(dev, | ||
625 | &dev->tx_ring[i]); | ||
626 | |||
627 | goto err_out; | ||
628 | } | ||
605 | } | 629 | } |
606 | 630 | ||
607 | set_bit(__QLCNIC_FW_ATTACHED, &adapter->state); | 631 | set_bit(__QLCNIC_FW_ATTACHED, &dev->state); |
608 | return 0; | 632 | return 0; |
633 | |||
634 | err_out: | ||
635 | if (qlcnic_83xx_check(dev) && (dev->flags & QLCNIC_MSIX_ENABLED)) { | ||
636 | if (dev->ahw->diag_test != QLCNIC_LOOPBACK_TEST) | ||
637 | qlcnic_83xx_config_intrpt(dev, 0); | ||
638 | } | ||
639 | return err; | ||
609 | } | 640 | } |
610 | 641 | ||
611 | void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter) | 642 | void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter) |
612 | { | 643 | { |
644 | int ring; | ||
645 | |||
613 | if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) { | 646 | if (test_and_clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state)) { |
614 | qlcnic_fw_cmd_destroy_rx_ctx(adapter); | 647 | qlcnic_fw_cmd_destroy_rx_ctx(adapter); |
615 | qlcnic_fw_cmd_destroy_tx_ctx(adapter); | 648 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) |
616 | 649 | qlcnic_fw_cmd_destroy_tx_ctx(adapter, | |
650 | &adapter->tx_ring[ring]); | ||
651 | |||
652 | if (qlcnic_83xx_check(adapter) && | ||
653 | (adapter->flags & QLCNIC_MSIX_ENABLED)) { | ||
654 | if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) | ||
655 | qlcnic_83xx_config_intrpt(adapter, 0); | ||
656 | } | ||
617 | /* Allow dma queues to drain after context reset */ | 657 | /* Allow dma queues to drain after context reset */ |
618 | mdelay(20); | 658 | mdelay(20); |
619 | } | 659 | } |
@@ -629,20 +669,23 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) | |||
629 | 669 | ||
630 | recv_ctx = adapter->recv_ctx; | 670 | recv_ctx = adapter->recv_ctx; |
631 | 671 | ||
632 | tx_ring = adapter->tx_ring; | 672 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { |
633 | if (tx_ring->hw_consumer != NULL) { | 673 | tx_ring = &adapter->tx_ring[ring]; |
634 | dma_free_coherent(&adapter->pdev->dev, | 674 | if (tx_ring->hw_consumer != NULL) { |
635 | sizeof(u32), | 675 | dma_free_coherent(&adapter->pdev->dev, sizeof(u32), |
636 | tx_ring->hw_consumer, | 676 | tx_ring->hw_consumer, |
637 | tx_ring->hw_cons_phys_addr); | 677 | tx_ring->hw_cons_phys_addr); |
638 | tx_ring->hw_consumer = NULL; | ||
639 | } | ||
640 | 678 | ||
641 | if (tx_ring->desc_head != NULL) { | 679 | tx_ring->hw_consumer = NULL; |
642 | dma_free_coherent(&adapter->pdev->dev, | 680 | } |
643 | TX_DESC_RINGSIZE(tx_ring), | 681 | |
644 | tx_ring->desc_head, tx_ring->phys_addr); | 682 | if (tx_ring->desc_head != NULL) { |
645 | tx_ring->desc_head = NULL; | 683 | dma_free_coherent(&adapter->pdev->dev, |
684 | TX_DESC_RINGSIZE(tx_ring), | ||
685 | tx_ring->desc_head, | ||
686 | tx_ring->phys_addr); | ||
687 | tx_ring->desc_head = NULL; | ||
688 | } | ||
646 | } | 689 | } |
647 | 690 | ||
648 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | 691 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { |
@@ -671,40 +714,43 @@ void qlcnic_free_hw_resources(struct qlcnic_adapter *adapter) | |||
671 | } | 714 | } |
672 | 715 | ||
673 | 716 | ||
674 | /* Get MAC address of a NIC partition */ | 717 | int qlcnic_82xx_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac) |
675 | int qlcnic_get_mac_address(struct qlcnic_adapter *adapter, u8 *mac) | ||
676 | { | 718 | { |
677 | int err; | 719 | int err, i; |
678 | struct qlcnic_cmd_args cmd; | 720 | struct qlcnic_cmd_args cmd; |
721 | u32 mac_low, mac_high; | ||
679 | 722 | ||
680 | memset(&cmd, 0, sizeof(cmd)); | 723 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_MAC_ADDRESS); |
681 | cmd.req.arg1 = adapter->ahw->pci_func | BIT_8; | 724 | cmd.req.arg[1] = adapter->ahw->pci_func | BIT_8; |
682 | cmd.req.cmd = QLCNIC_CDRP_CMD_MAC_ADDRESS; | 725 | err = qlcnic_issue_cmd(adapter, &cmd); |
683 | cmd.rsp.arg1 = cmd.rsp.arg2 = 1; | ||
684 | qlcnic_issue_cmd(adapter, &cmd); | ||
685 | err = cmd.rsp.cmd; | ||
686 | 726 | ||
687 | if (err == QLCNIC_RCODE_SUCCESS) | 727 | if (err == QLCNIC_RCODE_SUCCESS) { |
688 | qlcnic_fetch_mac(cmd.rsp.arg1, cmd.rsp.arg2, 0, mac); | 728 | mac_low = cmd.rsp.arg[1]; |
689 | else { | 729 | mac_high = cmd.rsp.arg[2]; |
730 | |||
731 | for (i = 0; i < 2; i++) | ||
732 | mac[i] = (u8) (mac_high >> ((1 - i) * 8)); | ||
733 | for (i = 2; i < 6; i++) | ||
734 | mac[i] = (u8) (mac_low >> ((5 - i) * 8)); | ||
735 | } else { | ||
690 | dev_err(&adapter->pdev->dev, | 736 | dev_err(&adapter->pdev->dev, |
691 | "Failed to get mac address%d\n", err); | 737 | "Failed to get mac address%d\n", err); |
692 | err = -EIO; | 738 | err = -EIO; |
693 | } | 739 | } |
694 | 740 | qlcnic_free_mbx_args(&cmd); | |
695 | return err; | 741 | return err; |
696 | } | 742 | } |
697 | 743 | ||
698 | /* Get info of a NIC partition */ | 744 | /* Get info of a NIC partition */ |
699 | int qlcnic_get_nic_info(struct qlcnic_adapter *adapter, | 745 | int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter, |
700 | struct qlcnic_info *npar_info, u8 func_id) | 746 | struct qlcnic_info *npar_info, u8 func_id) |
701 | { | 747 | { |
702 | int err; | 748 | int err; |
703 | dma_addr_t nic_dma_t; | 749 | dma_addr_t nic_dma_t; |
704 | struct qlcnic_info_le *nic_info; | 750 | const struct qlcnic_info_le *nic_info; |
705 | void *nic_info_addr; | 751 | void *nic_info_addr; |
706 | struct qlcnic_cmd_args cmd; | 752 | struct qlcnic_cmd_args cmd; |
707 | size_t nic_size = sizeof(struct qlcnic_info_le); | 753 | size_t nic_size = sizeof(struct qlcnic_info_le); |
708 | 754 | ||
709 | nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size, | 755 | nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size, |
710 | &nic_dma_t, GFP_KERNEL); | 756 | &nic_dma_t, GFP_KERNEL); |
@@ -713,47 +759,39 @@ int qlcnic_get_nic_info(struct qlcnic_adapter *adapter, | |||
713 | memset(nic_info_addr, 0, nic_size); | 759 | memset(nic_info_addr, 0, nic_size); |
714 | 760 | ||
715 | nic_info = nic_info_addr; | 761 | nic_info = nic_info_addr; |
716 | memset(&cmd, 0, sizeof(cmd)); | ||
717 | cmd.req.cmd = QLCNIC_CDRP_CMD_GET_NIC_INFO; | ||
718 | cmd.req.arg1 = MSD(nic_dma_t); | ||
719 | cmd.req.arg2 = LSD(nic_dma_t); | ||
720 | cmd.req.arg3 = (func_id << 16 | nic_size); | ||
721 | qlcnic_issue_cmd(adapter, &cmd); | ||
722 | err = cmd.rsp.cmd; | ||
723 | 762 | ||
724 | if (err == QLCNIC_RCODE_SUCCESS) { | 763 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_NIC_INFO); |
764 | cmd.req.arg[1] = MSD(nic_dma_t); | ||
765 | cmd.req.arg[2] = LSD(nic_dma_t); | ||
766 | cmd.req.arg[3] = (func_id << 16 | nic_size); | ||
767 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
768 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
769 | dev_err(&adapter->pdev->dev, | ||
770 | "Failed to get nic info%d\n", err); | ||
771 | err = -EIO; | ||
772 | } else { | ||
725 | npar_info->pci_func = le16_to_cpu(nic_info->pci_func); | 773 | npar_info->pci_func = le16_to_cpu(nic_info->pci_func); |
726 | npar_info->op_mode = le16_to_cpu(nic_info->op_mode); | 774 | npar_info->op_mode = le16_to_cpu(nic_info->op_mode); |
775 | npar_info->min_tx_bw = le16_to_cpu(nic_info->min_tx_bw); | ||
776 | npar_info->max_tx_bw = le16_to_cpu(nic_info->max_tx_bw); | ||
727 | npar_info->phys_port = le16_to_cpu(nic_info->phys_port); | 777 | npar_info->phys_port = le16_to_cpu(nic_info->phys_port); |
728 | npar_info->switch_mode = le16_to_cpu(nic_info->switch_mode); | 778 | npar_info->switch_mode = le16_to_cpu(nic_info->switch_mode); |
729 | npar_info->max_tx_ques = le16_to_cpu(nic_info->max_tx_ques); | 779 | npar_info->max_tx_ques = le16_to_cpu(nic_info->max_tx_ques); |
730 | npar_info->max_rx_ques = le16_to_cpu(nic_info->max_rx_ques); | 780 | npar_info->max_rx_ques = le16_to_cpu(nic_info->max_rx_ques); |
731 | npar_info->min_tx_bw = le16_to_cpu(nic_info->min_tx_bw); | ||
732 | npar_info->max_tx_bw = le16_to_cpu(nic_info->max_tx_bw); | ||
733 | npar_info->capabilities = le32_to_cpu(nic_info->capabilities); | 781 | npar_info->capabilities = le32_to_cpu(nic_info->capabilities); |
734 | npar_info->max_mtu = le16_to_cpu(nic_info->max_mtu); | 782 | npar_info->max_mtu = le16_to_cpu(nic_info->max_mtu); |
735 | |||
736 | dev_info(&adapter->pdev->dev, | ||
737 | "phy port: %d switch_mode: %d,\n" | ||
738 | "\tmax_tx_q: %d max_rx_q: %d min_tx_bw: 0x%x,\n" | ||
739 | "\tmax_tx_bw: 0x%x max_mtu:0x%x, capabilities: 0x%x\n", | ||
740 | npar_info->phys_port, npar_info->switch_mode, | ||
741 | npar_info->max_tx_ques, npar_info->max_rx_ques, | ||
742 | npar_info->min_tx_bw, npar_info->max_tx_bw, | ||
743 | npar_info->max_mtu, npar_info->capabilities); | ||
744 | } else { | ||
745 | dev_err(&adapter->pdev->dev, | ||
746 | "Failed to get nic info%d\n", err); | ||
747 | err = -EIO; | ||
748 | } | 783 | } |
749 | 784 | ||
750 | dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr, | 785 | dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr, |
751 | nic_dma_t); | 786 | nic_dma_t); |
787 | qlcnic_free_mbx_args(&cmd); | ||
788 | |||
752 | return err; | 789 | return err; |
753 | } | 790 | } |
754 | 791 | ||
755 | /* Configure a NIC partition */ | 792 | /* Configure a NIC partition */ |
756 | int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic) | 793 | int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *adapter, |
794 | struct qlcnic_info *nic) | ||
757 | { | 795 | { |
758 | int err = -EIO; | 796 | int err = -EIO; |
759 | dma_addr_t nic_dma_t; | 797 | dma_addr_t nic_dma_t; |
@@ -784,13 +822,11 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic) | |||
784 | nic_info->min_tx_bw = cpu_to_le16(nic->min_tx_bw); | 822 | nic_info->min_tx_bw = cpu_to_le16(nic->min_tx_bw); |
785 | nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw); | 823 | nic_info->max_tx_bw = cpu_to_le16(nic->max_tx_bw); |
786 | 824 | ||
787 | memset(&cmd, 0, sizeof(cmd)); | 825 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_NIC_INFO); |
788 | cmd.req.cmd = QLCNIC_CDRP_CMD_SET_NIC_INFO; | 826 | cmd.req.arg[1] = MSD(nic_dma_t); |
789 | cmd.req.arg1 = MSD(nic_dma_t); | 827 | cmd.req.arg[2] = LSD(nic_dma_t); |
790 | cmd.req.arg2 = LSD(nic_dma_t); | 828 | cmd.req.arg[3] = ((nic->pci_func << 16) | nic_size); |
791 | cmd.req.arg3 = ((nic->pci_func << 16) | nic_size); | 829 | err = qlcnic_issue_cmd(adapter, &cmd); |
792 | qlcnic_issue_cmd(adapter, &cmd); | ||
793 | err = cmd.rsp.cmd; | ||
794 | 830 | ||
795 | if (err != QLCNIC_RCODE_SUCCESS) { | 831 | if (err != QLCNIC_RCODE_SUCCESS) { |
796 | dev_err(&adapter->pdev->dev, | 832 | dev_err(&adapter->pdev->dev, |
@@ -800,12 +836,14 @@ int qlcnic_set_nic_info(struct qlcnic_adapter *adapter, struct qlcnic_info *nic) | |||
800 | 836 | ||
801 | dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr, | 837 | dma_free_coherent(&adapter->pdev->dev, nic_size, nic_info_addr, |
802 | nic_dma_t); | 838 | nic_dma_t); |
839 | qlcnic_free_mbx_args(&cmd); | ||
840 | |||
803 | return err; | 841 | return err; |
804 | } | 842 | } |
805 | 843 | ||
806 | /* Get PCI Info of a partition */ | 844 | /* Get PCI Info of a partition */ |
807 | int qlcnic_get_pci_info(struct qlcnic_adapter *adapter, | 845 | int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter, |
808 | struct qlcnic_pci_info *pci_info) | 846 | struct qlcnic_pci_info *pci_info) |
809 | { | 847 | { |
810 | int err = 0, i; | 848 | int err = 0, i; |
811 | struct qlcnic_cmd_args cmd; | 849 | struct qlcnic_cmd_args cmd; |
@@ -822,13 +860,11 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter, | |||
822 | memset(pci_info_addr, 0, pci_size); | 860 | memset(pci_info_addr, 0, pci_size); |
823 | 861 | ||
824 | npar = pci_info_addr; | 862 | npar = pci_info_addr; |
825 | memset(&cmd, 0, sizeof(cmd)); | 863 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_PCI_INFO); |
826 | cmd.req.cmd = QLCNIC_CDRP_CMD_GET_PCI_INFO; | 864 | cmd.req.arg[1] = MSD(pci_info_dma_t); |
827 | cmd.req.arg1 = MSD(pci_info_dma_t); | 865 | cmd.req.arg[2] = LSD(pci_info_dma_t); |
828 | cmd.req.arg2 = LSD(pci_info_dma_t); | 866 | cmd.req.arg[3] = pci_size; |
829 | cmd.req.arg3 = pci_size; | 867 | err = qlcnic_issue_cmd(adapter, &cmd); |
830 | qlcnic_issue_cmd(adapter, &cmd); | ||
831 | err = cmd.rsp.cmd; | ||
832 | 868 | ||
833 | adapter->ahw->act_pci_func = 0; | 869 | adapter->ahw->act_pci_func = 0; |
834 | if (err == QLCNIC_RCODE_SUCCESS) { | 870 | if (err == QLCNIC_RCODE_SUCCESS) { |
@@ -854,6 +890,8 @@ int qlcnic_get_pci_info(struct qlcnic_adapter *adapter, | |||
854 | 890 | ||
855 | dma_free_coherent(&adapter->pdev->dev, pci_size, pci_info_addr, | 891 | dma_free_coherent(&adapter->pdev->dev, pci_size, pci_info_addr, |
856 | pci_info_dma_t); | 892 | pci_info_dma_t); |
893 | qlcnic_free_mbx_args(&cmd); | ||
894 | |||
857 | return err; | 895 | return err; |
858 | } | 896 | } |
859 | 897 | ||
@@ -872,21 +910,19 @@ int qlcnic_config_port_mirroring(struct qlcnic_adapter *adapter, u8 id, | |||
872 | arg1 = id | (enable_mirroring ? BIT_4 : 0); | 910 | arg1 = id | (enable_mirroring ? BIT_4 : 0); |
873 | arg1 |= pci_func << 8; | 911 | arg1 |= pci_func << 8; |
874 | 912 | ||
875 | memset(&cmd, 0, sizeof(cmd)); | 913 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_SET_PORTMIRRORING); |
876 | cmd.req.cmd = QLCNIC_CDRP_CMD_SET_PORTMIRRORING; | 914 | cmd.req.arg[1] = arg1; |
877 | cmd.req.arg1 = arg1; | 915 | err = qlcnic_issue_cmd(adapter, &cmd); |
878 | qlcnic_issue_cmd(adapter, &cmd); | ||
879 | err = cmd.rsp.cmd; | ||
880 | 916 | ||
881 | if (err != QLCNIC_RCODE_SUCCESS) { | 917 | if (err != QLCNIC_RCODE_SUCCESS) |
882 | dev_err(&adapter->pdev->dev, | 918 | dev_err(&adapter->pdev->dev, |
883 | "Failed to configure port mirroring%d on eswitch:%d\n", | 919 | "Failed to configure port mirroring%d on eswitch:%d\n", |
884 | pci_func, id); | 920 | pci_func, id); |
885 | } else { | 921 | else |
886 | dev_info(&adapter->pdev->dev, | 922 | dev_info(&adapter->pdev->dev, |
887 | "Configured eSwitch %d for port mirroring:%d\n", | 923 | "Configured eSwitch %d for port mirroring:%d\n", |
888 | id, pci_func); | 924 | id, pci_func); |
889 | } | 925 | qlcnic_free_mbx_args(&cmd); |
890 | 926 | ||
891 | return err; | 927 | return err; |
892 | } | 928 | } |
@@ -923,13 +959,11 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, | |||
923 | arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12; | 959 | arg1 = func | QLCNIC_STATS_VERSION << 8 | QLCNIC_STATS_PORT << 12; |
924 | arg1 |= rx_tx << 15 | stats_size << 16; | 960 | arg1 |= rx_tx << 15 | stats_size << 16; |
925 | 961 | ||
926 | memset(&cmd, 0, sizeof(cmd)); | 962 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_ESWITCH_STATS); |
927 | cmd.req.cmd = QLCNIC_CDRP_CMD_GET_ESWITCH_STATS; | 963 | cmd.req.arg[1] = arg1; |
928 | cmd.req.arg1 = arg1; | 964 | cmd.req.arg[2] = MSD(stats_dma_t); |
929 | cmd.req.arg2 = MSD(stats_dma_t); | 965 | cmd.req.arg[3] = LSD(stats_dma_t); |
930 | cmd.req.arg3 = LSD(stats_dma_t); | 966 | err = qlcnic_issue_cmd(adapter, &cmd); |
931 | qlcnic_issue_cmd(adapter, &cmd); | ||
932 | err = cmd.rsp.cmd; | ||
933 | 967 | ||
934 | if (!err) { | 968 | if (!err) { |
935 | stats = stats_addr; | 969 | stats = stats_addr; |
@@ -949,6 +983,8 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func, | |||
949 | 983 | ||
950 | dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr, | 984 | dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr, |
951 | stats_dma_t); | 985 | stats_dma_t); |
986 | qlcnic_free_mbx_args(&cmd); | ||
987 | |||
952 | return err; | 988 | return err; |
953 | } | 989 | } |
954 | 990 | ||
@@ -963,6 +999,9 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter, | |||
963 | void *stats_addr; | 999 | void *stats_addr; |
964 | int err; | 1000 | int err; |
965 | 1001 | ||
1002 | if (mac_stats == NULL) | ||
1003 | return -ENOMEM; | ||
1004 | |||
966 | stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size, | 1005 | stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size, |
967 | &stats_dma_t, GFP_KERNEL); | 1006 | &stats_dma_t, GFP_KERNEL); |
968 | if (!stats_addr) { | 1007 | if (!stats_addr) { |
@@ -971,15 +1010,11 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter, | |||
971 | return -ENOMEM; | 1010 | return -ENOMEM; |
972 | } | 1011 | } |
973 | memset(stats_addr, 0, stats_size); | 1012 | memset(stats_addr, 0, stats_size); |
974 | memset(&cmd, 0, sizeof(cmd)); | 1013 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_MAC_STATS); |
975 | cmd.req.cmd = QLCNIC_CDRP_CMD_GET_MAC_STATS; | 1014 | cmd.req.arg[1] = stats_size << 16; |
976 | cmd.req.arg1 = stats_size << 16; | 1015 | cmd.req.arg[2] = MSD(stats_dma_t); |
977 | cmd.req.arg2 = MSD(stats_dma_t); | 1016 | cmd.req.arg[3] = LSD(stats_dma_t); |
978 | cmd.req.arg3 = LSD(stats_dma_t); | 1017 | err = qlcnic_issue_cmd(adapter, &cmd); |
979 | |||
980 | qlcnic_issue_cmd(adapter, &cmd); | ||
981 | err = cmd.rsp.cmd; | ||
982 | |||
983 | if (!err) { | 1018 | if (!err) { |
984 | stats = stats_addr; | 1019 | stats = stats_addr; |
985 | mac_stats->mac_tx_frames = le64_to_cpu(stats->mac_tx_frames); | 1020 | mac_stats->mac_tx_frames = le64_to_cpu(stats->mac_tx_frames); |
@@ -1001,10 +1036,16 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter, | |||
1001 | mac_stats->mac_rx_jabber = le64_to_cpu(stats->mac_rx_jabber); | 1036 | mac_stats->mac_rx_jabber = le64_to_cpu(stats->mac_rx_jabber); |
1002 | mac_stats->mac_rx_dropped = le64_to_cpu(stats->mac_rx_dropped); | 1037 | mac_stats->mac_rx_dropped = le64_to_cpu(stats->mac_rx_dropped); |
1003 | mac_stats->mac_rx_crc_error = le64_to_cpu(stats->mac_rx_crc_error); | 1038 | mac_stats->mac_rx_crc_error = le64_to_cpu(stats->mac_rx_crc_error); |
1039 | } else { | ||
1040 | dev_err(&adapter->pdev->dev, | ||
1041 | "%s: Get mac stats failed, err=%d.\n", __func__, err); | ||
1004 | } | 1042 | } |
1005 | 1043 | ||
1006 | dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr, | 1044 | dma_free_coherent(&adapter->pdev->dev, stats_size, stats_addr, |
1007 | stats_dma_t); | 1045 | stats_dma_t); |
1046 | |||
1047 | qlcnic_free_mbx_args(&cmd); | ||
1048 | |||
1008 | return err; | 1049 | return err; |
1009 | } | 1050 | } |
1010 | 1051 | ||
@@ -1065,7 +1106,7 @@ int qlcnic_get_eswitch_stats(struct qlcnic_adapter *adapter, const u8 eswitch, | |||
1065 | int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw, | 1106 | int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw, |
1066 | const u8 port, const u8 rx_tx) | 1107 | const u8 port, const u8 rx_tx) |
1067 | { | 1108 | { |
1068 | 1109 | int err; | |
1069 | u32 arg1; | 1110 | u32 arg1; |
1070 | struct qlcnic_cmd_args cmd; | 1111 | struct qlcnic_cmd_args cmd; |
1071 | 1112 | ||
@@ -1088,15 +1129,16 @@ int qlcnic_clear_esw_stats(struct qlcnic_adapter *adapter, const u8 func_esw, | |||
1088 | arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12; | 1129 | arg1 = port | QLCNIC_STATS_VERSION << 8 | func_esw << 12; |
1089 | arg1 |= BIT_14 | rx_tx << 15; | 1130 | arg1 |= BIT_14 | rx_tx << 15; |
1090 | 1131 | ||
1091 | memset(&cmd, 0, sizeof(cmd)); | 1132 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_ESWITCH_STATS); |
1092 | cmd.req.cmd = QLCNIC_CDRP_CMD_GET_ESWITCH_STATS; | 1133 | cmd.req.arg[1] = arg1; |
1093 | cmd.req.arg1 = arg1; | 1134 | err = qlcnic_issue_cmd(adapter, &cmd); |
1094 | qlcnic_issue_cmd(adapter, &cmd); | 1135 | qlcnic_free_mbx_args(&cmd); |
1095 | return cmd.rsp.cmd; | 1136 | return err; |
1096 | 1137 | ||
1097 | err_ret: | 1138 | err_ret: |
1098 | dev_err(&adapter->pdev->dev, "Invalid argument func_esw=%d port=%d" | 1139 | dev_err(&adapter->pdev->dev, |
1099 | "rx_ctx=%d\n", func_esw, port, rx_tx); | 1140 | "Invalid args func_esw %d port %d rx_ctx %d\n", |
1141 | func_esw, port, rx_tx); | ||
1100 | return -EIO; | 1142 | return -EIO; |
1101 | } | 1143 | } |
1102 | 1144 | ||
@@ -1109,22 +1151,21 @@ __qlcnic_get_eswitch_port_config(struct qlcnic_adapter *adapter, | |||
1109 | u8 pci_func; | 1151 | u8 pci_func; |
1110 | pci_func = (*arg1 >> 8); | 1152 | pci_func = (*arg1 >> 8); |
1111 | 1153 | ||
1112 | cmd.req.cmd = QLCNIC_CDRP_CMD_GET_ESWITCH_PORT_CONFIG; | 1154 | qlcnic_alloc_mbx_args(&cmd, adapter, |
1113 | cmd.req.arg1 = *arg1; | 1155 | QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG); |
1114 | cmd.rsp.arg1 = cmd.rsp.arg2 = 1; | 1156 | cmd.req.arg[1] = *arg1; |
1115 | qlcnic_issue_cmd(adapter, &cmd); | 1157 | err = qlcnic_issue_cmd(adapter, &cmd); |
1116 | *arg1 = cmd.rsp.arg1; | 1158 | *arg1 = cmd.rsp.arg[1]; |
1117 | *arg2 = cmd.rsp.arg2; | 1159 | *arg2 = cmd.rsp.arg[2]; |
1118 | err = cmd.rsp.cmd; | 1160 | qlcnic_free_mbx_args(&cmd); |
1119 | 1161 | ||
1120 | if (err == QLCNIC_RCODE_SUCCESS) { | 1162 | if (err == QLCNIC_RCODE_SUCCESS) |
1121 | dev_info(&adapter->pdev->dev, | 1163 | dev_info(&adapter->pdev->dev, |
1122 | "eSwitch port config for pci func %d\n", pci_func); | 1164 | "eSwitch port config for pci func %d\n", pci_func); |
1123 | } else { | 1165 | else |
1124 | dev_err(&adapter->pdev->dev, | 1166 | dev_err(&adapter->pdev->dev, |
1125 | "Failed to get eswitch port config for pci func %d\n", | 1167 | "Failed to get eswitch port config for pci func %d\n", |
1126 | pci_func); | 1168 | pci_func); |
1127 | } | ||
1128 | return err; | 1169 | return err; |
1129 | } | 1170 | } |
1130 | /* Configure eSwitch port | 1171 | /* Configure eSwitch port |
@@ -1189,20 +1230,18 @@ int qlcnic_config_switch_port(struct qlcnic_adapter *adapter, | |||
1189 | return err; | 1230 | return err; |
1190 | } | 1231 | } |
1191 | 1232 | ||
1192 | memset(&cmd, 0, sizeof(cmd)); | 1233 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_CONFIGURE_ESWITCH); |
1193 | cmd.req.cmd = QLCNIC_CDRP_CMD_CONFIGURE_ESWITCH; | 1234 | cmd.req.arg[1] = arg1; |
1194 | cmd.req.arg1 = arg1; | 1235 | cmd.req.arg[2] = arg2; |
1195 | cmd.req.arg2 = arg2; | 1236 | err = qlcnic_issue_cmd(adapter, &cmd); |
1196 | qlcnic_issue_cmd(adapter, &cmd); | 1237 | qlcnic_free_mbx_args(&cmd); |
1197 | 1238 | ||
1198 | err = cmd.rsp.cmd; | 1239 | if (err != QLCNIC_RCODE_SUCCESS) |
1199 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
1200 | dev_err(&adapter->pdev->dev, | 1240 | dev_err(&adapter->pdev->dev, |
1201 | "Failed to configure eswitch pci func %d\n", pci_func); | 1241 | "Failed to configure eswitch pci func %d\n", pci_func); |
1202 | } else { | 1242 | else |
1203 | dev_info(&adapter->pdev->dev, | 1243 | dev_info(&adapter->pdev->dev, |
1204 | "Configured eSwitch for pci func %d\n", pci_func); | 1244 | "Configured eSwitch for pci func %d\n", pci_func); |
1205 | } | ||
1206 | 1245 | ||
1207 | return err; | 1246 | return err; |
1208 | } | 1247 | } |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c index 74b98110c5b4..5641f8ec49ab 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * QLogic qlcnic NIC Driver | 2 | * QLogic qlcnic NIC Driver |
3 | * Copyright (c) 2009-2010 QLogic Corporation | 3 | * Copyright (c) 2009-2013 QLogic Corporation |
4 | * | 4 | * |
5 | * See LICENSE.qlcnic for copyright and licensing details. | 5 | * See LICENSE.qlcnic for copyright and licensing details. |
6 | */ | 6 | */ |
@@ -22,42 +22,37 @@ struct qlcnic_stats { | |||
22 | 22 | ||
23 | #define QLC_SIZEOF(m) FIELD_SIZEOF(struct qlcnic_adapter, m) | 23 | #define QLC_SIZEOF(m) FIELD_SIZEOF(struct qlcnic_adapter, m) |
24 | #define QLC_OFF(m) offsetof(struct qlcnic_adapter, m) | 24 | #define QLC_OFF(m) offsetof(struct qlcnic_adapter, m) |
25 | static const u32 qlcnic_fw_dump_level[] = { | ||
26 | 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff | ||
27 | }; | ||
25 | 28 | ||
26 | static const struct qlcnic_stats qlcnic_gstrings_stats[] = { | 29 | static const struct qlcnic_stats qlcnic_gstrings_stats[] = { |
27 | {"xmit_called", | 30 | {"xmit_called", QLC_SIZEOF(stats.xmitcalled), |
28 | QLC_SIZEOF(stats.xmitcalled), QLC_OFF(stats.xmitcalled)}, | 31 | QLC_OFF(stats.xmitcalled)}, |
29 | {"xmit_finished", | 32 | {"xmit_finished", QLC_SIZEOF(stats.xmitfinished), |
30 | QLC_SIZEOF(stats.xmitfinished), QLC_OFF(stats.xmitfinished)}, | 33 | QLC_OFF(stats.xmitfinished)}, |
31 | {"rx_dropped", | 34 | {"rx_dropped", QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)}, |
32 | QLC_SIZEOF(stats.rxdropped), QLC_OFF(stats.rxdropped)}, | 35 | {"tx_dropped", QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)}, |
33 | {"tx_dropped", | 36 | {"csummed", QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)}, |
34 | QLC_SIZEOF(stats.txdropped), QLC_OFF(stats.txdropped)}, | 37 | {"rx_pkts", QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)}, |
35 | {"csummed", | 38 | {"lro_pkts", QLC_SIZEOF(stats.lro_pkts), QLC_OFF(stats.lro_pkts)}, |
36 | QLC_SIZEOF(stats.csummed), QLC_OFF(stats.csummed)}, | 39 | {"rx_bytes", QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)}, |
37 | {"rx_pkts", | 40 | {"tx_bytes", QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)}, |
38 | QLC_SIZEOF(stats.rx_pkts), QLC_OFF(stats.rx_pkts)}, | 41 | {"lrobytes", QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)}, |
39 | {"lro_pkts", | 42 | {"lso_frames", QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)}, |
40 | QLC_SIZEOF(stats.lro_pkts), QLC_OFF(stats.lro_pkts)}, | 43 | {"xmit_on", QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)}, |
41 | {"rx_bytes", | 44 | {"xmit_off", QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)}, |
42 | QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)}, | ||
43 | {"tx_bytes", | ||
44 | QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)}, | ||
45 | {"lrobytes", | ||
46 | QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)}, | ||
47 | {"lso_frames", | ||
48 | QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)}, | ||
49 | {"xmit_on", | ||
50 | QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)}, | ||
51 | {"xmit_off", | ||
52 | QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)}, | ||
53 | {"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure), | 45 | {"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure), |
54 | QLC_OFF(stats.skb_alloc_failure)}, | 46 | QLC_OFF(stats.skb_alloc_failure)}, |
55 | {"null rxbuf", | 47 | {"null rxbuf", QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)}, |
56 | QLC_SIZEOF(stats.null_rxbuf), QLC_OFF(stats.null_rxbuf)}, | ||
57 | {"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error), | 48 | {"rx dma map error", QLC_SIZEOF(stats.rx_dma_map_error), |
58 | QLC_OFF(stats.rx_dma_map_error)}, | 49 | QLC_OFF(stats.rx_dma_map_error)}, |
59 | {"tx dma map error", QLC_SIZEOF(stats.tx_dma_map_error), | 50 | {"tx dma map error", QLC_SIZEOF(stats.tx_dma_map_error), |
60 | QLC_OFF(stats.tx_dma_map_error)}, | 51 | QLC_OFF(stats.tx_dma_map_error)}, |
52 | {"mac_filter_limit_overrun", QLC_SIZEOF(stats.mac_filter_limit_overrun), | ||
53 | QLC_OFF(stats.mac_filter_limit_overrun)}, | ||
54 | {"spurious intr", QLC_SIZEOF(stats.spurious_intr), | ||
55 | QLC_OFF(stats.spurious_intr)}, | ||
61 | 56 | ||
62 | }; | 57 | }; |
63 | 58 | ||
@@ -78,7 +73,15 @@ static const char qlcnic_device_gstrings_stats[][ETH_GSTRING_LEN] = { | |||
78 | "tx numbytes", | 73 | "tx numbytes", |
79 | }; | 74 | }; |
80 | 75 | ||
81 | static const char qlcnic_mac_stats_strings [][ETH_GSTRING_LEN] = { | 76 | static const char qlcnic_83xx_tx_stats_strings[][ETH_GSTRING_LEN] = { |
77 | "ctx_tx_bytes", | ||
78 | "ctx_tx_pkts", | ||
79 | "ctx_tx_errors", | ||
80 | "ctx_tx_dropped_pkts", | ||
81 | "ctx_tx_num_buffers", | ||
82 | }; | ||
83 | |||
84 | static const char qlcnic_83xx_mac_stats_strings[][ETH_GSTRING_LEN] = { | ||
82 | "mac_tx_frames", | 85 | "mac_tx_frames", |
83 | "mac_tx_bytes", | 86 | "mac_tx_bytes", |
84 | "mac_tx_mcast_pkts", | 87 | "mac_tx_mcast_pkts", |
@@ -110,35 +113,70 @@ static const char qlcnic_mac_stats_strings [][ETH_GSTRING_LEN] = { | |||
110 | "mac_rx_length_large", | 113 | "mac_rx_length_large", |
111 | "mac_rx_jabber", | 114 | "mac_rx_jabber", |
112 | "mac_rx_dropped", | 115 | "mac_rx_dropped", |
113 | "mac_rx_crc_error", | 116 | "mac_crc_error", |
114 | "mac_align_error", | 117 | "mac_align_error", |
115 | }; | 118 | }; |
116 | 119 | ||
117 | #define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats) | 120 | #define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats) |
118 | #define QLCNIC_MAC_STATS_LEN ARRAY_SIZE(qlcnic_mac_stats_strings) | 121 | static const char qlcnic_83xx_rx_stats_strings[][ETH_GSTRING_LEN] = { |
119 | #define QLCNIC_DEVICE_STATS_LEN ARRAY_SIZE(qlcnic_device_gstrings_stats) | 122 | "ctx_rx_bytes", |
120 | #define QLCNIC_TOTAL_STATS_LEN QLCNIC_STATS_LEN + QLCNIC_MAC_STATS_LEN | 123 | "ctx_rx_pkts", |
124 | "ctx_lro_pkt_cnt", | ||
125 | "ctx_ip_csum_error", | ||
126 | "ctx_rx_pkts_wo_ctx", | ||
127 | "ctx_rx_pkts_dropped_wo_sts", | ||
128 | "ctx_rx_osized_pkts", | ||
129 | "ctx_rx_pkts_dropped_wo_rds", | ||
130 | "ctx_rx_unexpected_mcast_pkts", | ||
131 | "ctx_invalid_mac_address", | ||
132 | "ctx_rx_rds_ring_prim_attemoted", | ||
133 | "ctx_rx_rds_ring_prim_success", | ||
134 | "ctx_num_lro_flows_added", | ||
135 | "ctx_num_lro_flows_removed", | ||
136 | "ctx_num_lro_flows_active", | ||
137 | "ctx_pkts_dropped_unknown", | ||
138 | }; | ||
121 | 139 | ||
122 | static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = { | 140 | static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = { |
123 | "Register_Test_on_offline", | 141 | "Register_Test_on_offline", |
124 | "Link_Test_on_offline", | 142 | "Link_Test_on_offline", |
125 | "Interrupt_Test_offline", | 143 | "Interrupt_Test_offline", |
126 | "Internal_Loopback_offline", | 144 | "Internal_Loopback_offline", |
127 | "External_Loopback_offline" | 145 | "EEPROM_Test_offline" |
128 | }; | 146 | }; |
129 | 147 | ||
130 | #define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test) | 148 | #define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test) |
131 | 149 | ||
150 | static inline int qlcnic_82xx_statistics(void) | ||
151 | { | ||
152 | return QLCNIC_STATS_LEN + ARRAY_SIZE(qlcnic_83xx_mac_stats_strings); | ||
153 | } | ||
154 | |||
155 | static inline int qlcnic_83xx_statistics(void) | ||
156 | { | ||
157 | return ARRAY_SIZE(qlcnic_83xx_tx_stats_strings) + | ||
158 | ARRAY_SIZE(qlcnic_83xx_mac_stats_strings) + | ||
159 | ARRAY_SIZE(qlcnic_83xx_rx_stats_strings); | ||
160 | } | ||
161 | |||
162 | static int qlcnic_dev_statistics_len(struct qlcnic_adapter *adapter) | ||
163 | { | ||
164 | if (qlcnic_82xx_check(adapter)) | ||
165 | return qlcnic_82xx_statistics(); | ||
166 | else if (qlcnic_83xx_check(adapter)) | ||
167 | return qlcnic_83xx_statistics(); | ||
168 | else | ||
169 | return -1; | ||
170 | } | ||
171 | |||
132 | #define QLCNIC_RING_REGS_COUNT 20 | 172 | #define QLCNIC_RING_REGS_COUNT 20 |
133 | #define QLCNIC_RING_REGS_LEN (QLCNIC_RING_REGS_COUNT * sizeof(u32)) | 173 | #define QLCNIC_RING_REGS_LEN (QLCNIC_RING_REGS_COUNT * sizeof(u32)) |
134 | #define QLCNIC_MAX_EEPROM_LEN 1024 | 174 | #define QLCNIC_MAX_EEPROM_LEN 1024 |
135 | 175 | ||
136 | static const u32 diag_registers[] = { | 176 | static const u32 diag_registers[] = { |
137 | CRB_CMDPEG_STATE, | 177 | QLCNIC_CMDPEG_STATE, |
138 | CRB_RCVPEG_STATE, | 178 | QLCNIC_RCVPEG_STATE, |
139 | CRB_XG_STATE_P3P, | 179 | QLCNIC_FW_CAPABILITIES, |
140 | CRB_FW_CAPABILITIES_1, | ||
141 | ISR_INT_STATE_REG, | ||
142 | QLCNIC_CRB_DRV_ACTIVE, | 180 | QLCNIC_CRB_DRV_ACTIVE, |
143 | QLCNIC_CRB_DEV_STATE, | 181 | QLCNIC_CRB_DEV_STATE, |
144 | QLCNIC_CRB_DRV_STATE, | 182 | QLCNIC_CRB_DRV_STATE, |
@@ -148,6 +186,13 @@ static const u32 diag_registers[] = { | |||
148 | QLCNIC_PEG_ALIVE_COUNTER, | 186 | QLCNIC_PEG_ALIVE_COUNTER, |
149 | QLCNIC_PEG_HALT_STATUS1, | 187 | QLCNIC_PEG_HALT_STATUS1, |
150 | QLCNIC_PEG_HALT_STATUS2, | 188 | QLCNIC_PEG_HALT_STATUS2, |
189 | -1 | ||
190 | }; | ||
191 | |||
192 | |||
193 | static const u32 ext_diag_registers[] = { | ||
194 | CRB_XG_STATE_P3P, | ||
195 | ISR_INT_STATE_REG, | ||
151 | QLCNIC_CRB_PEG_NET_0+0x3c, | 196 | QLCNIC_CRB_PEG_NET_0+0x3c, |
152 | QLCNIC_CRB_PEG_NET_1+0x3c, | 197 | QLCNIC_CRB_PEG_NET_1+0x3c, |
153 | QLCNIC_CRB_PEG_NET_2+0x3c, | 198 | QLCNIC_CRB_PEG_NET_2+0x3c, |
@@ -156,12 +201,19 @@ static const u32 diag_registers[] = { | |||
156 | }; | 201 | }; |
157 | 202 | ||
158 | #define QLCNIC_MGMT_API_VERSION 2 | 203 | #define QLCNIC_MGMT_API_VERSION 2 |
159 | #define QLCNIC_DEV_INFO_SIZE 1 | 204 | #define QLCNIC_ETHTOOL_REGS_VER 3 |
160 | #define QLCNIC_ETHTOOL_REGS_VER 2 | 205 | |
161 | static int qlcnic_get_regs_len(struct net_device *dev) | 206 | static int qlcnic_get_regs_len(struct net_device *dev) |
162 | { | 207 | { |
163 | return sizeof(diag_registers) + QLCNIC_RING_REGS_LEN + | 208 | struct qlcnic_adapter *adapter = netdev_priv(dev); |
164 | QLCNIC_DEV_INFO_SIZE + 1; | 209 | u32 len; |
210 | |||
211 | if (qlcnic_83xx_check(adapter)) | ||
212 | len = qlcnic_83xx_get_regs_len(adapter); | ||
213 | else | ||
214 | len = sizeof(ext_diag_registers) + sizeof(diag_registers); | ||
215 | |||
216 | return QLCNIC_RING_REGS_LEN + len + QLCNIC_DEV_INFO_SIZE + 1; | ||
165 | } | 217 | } |
166 | 218 | ||
167 | static int qlcnic_get_eeprom_len(struct net_device *dev) | 219 | static int qlcnic_get_eeprom_len(struct net_device *dev) |
@@ -174,10 +226,9 @@ qlcnic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) | |||
174 | { | 226 | { |
175 | struct qlcnic_adapter *adapter = netdev_priv(dev); | 227 | struct qlcnic_adapter *adapter = netdev_priv(dev); |
176 | u32 fw_major, fw_minor, fw_build; | 228 | u32 fw_major, fw_minor, fw_build; |
177 | 229 | fw_major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR); | |
178 | fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR); | 230 | fw_minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR); |
179 | fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR); | 231 | fw_build = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB); |
180 | fw_build = QLCRD32(adapter, QLCNIC_FW_VERSION_SUB); | ||
181 | snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), | 232 | snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), |
182 | "%d.%d.%d", fw_major, fw_minor, fw_build); | 233 | "%d.%d.%d", fw_major, fw_minor, fw_build); |
183 | 234 | ||
@@ -192,7 +243,10 @@ static int | |||
192 | qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | 243 | qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) |
193 | { | 244 | { |
194 | struct qlcnic_adapter *adapter = netdev_priv(dev); | 245 | struct qlcnic_adapter *adapter = netdev_priv(dev); |
246 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
247 | u32 speed, reg; | ||
195 | int check_sfp_module = 0; | 248 | int check_sfp_module = 0; |
249 | u16 pcifn = ahw->pci_func; | ||
196 | 250 | ||
197 | /* read which mode */ | 251 | /* read which mode */ |
198 | if (adapter->ahw->port_type == QLCNIC_GBE) { | 252 | if (adapter->ahw->port_type == QLCNIC_GBE) { |
@@ -213,9 +267,12 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
213 | ecmd->autoneg = adapter->ahw->link_autoneg; | 267 | ecmd->autoneg = adapter->ahw->link_autoneg; |
214 | 268 | ||
215 | } else if (adapter->ahw->port_type == QLCNIC_XGBE) { | 269 | } else if (adapter->ahw->port_type == QLCNIC_XGBE) { |
216 | u32 val; | 270 | u32 val = 0; |
271 | if (qlcnic_83xx_check(adapter)) | ||
272 | qlcnic_83xx_get_settings(adapter); | ||
273 | else | ||
274 | val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR); | ||
217 | 275 | ||
218 | val = QLCRD32(adapter, QLCNIC_PORT_MODE_ADDR); | ||
219 | if (val == QLCNIC_PORT_MODE_802_3_AP) { | 276 | if (val == QLCNIC_PORT_MODE_802_3_AP) { |
220 | ecmd->supported = SUPPORTED_1000baseT_Full; | 277 | ecmd->supported = SUPPORTED_1000baseT_Full; |
221 | ecmd->advertising = ADVERTISED_1000baseT_Full; | 278 | ecmd->advertising = ADVERTISED_1000baseT_Full; |
@@ -225,6 +282,12 @@ qlcnic_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
225 | } | 282 | } |
226 | 283 | ||
227 | if (netif_running(dev) && adapter->ahw->has_link_events) { | 284 | if (netif_running(dev) && adapter->ahw->has_link_events) { |
285 | if (qlcnic_82xx_check(adapter)) { | ||
286 | reg = QLCRD32(adapter, | ||
287 | P3P_LINK_SPEED_REG(pcifn)); | ||
288 | speed = P3P_LINK_SPEED_VAL(pcifn, reg); | ||
289 | ahw->link_speed = speed * P3P_LINK_SPEED_MHZ; | ||
290 | } | ||
228 | ethtool_cmd_speed_set(ecmd, adapter->ahw->link_speed); | 291 | ethtool_cmd_speed_set(ecmd, adapter->ahw->link_speed); |
229 | ecmd->autoneg = adapter->ahw->link_autoneg; | 292 | ecmd->autoneg = adapter->ahw->link_autoneg; |
230 | ecmd->duplex = adapter->ahw->link_duplex; | 293 | ecmd->duplex = adapter->ahw->link_duplex; |
@@ -294,6 +357,13 @@ skip: | |||
294 | ecmd->port = PORT_TP; | 357 | ecmd->port = PORT_TP; |
295 | } | 358 | } |
296 | break; | 359 | break; |
360 | case QLCNIC_BRDTYPE_83XX_10G: | ||
361 | ecmd->autoneg = AUTONEG_DISABLE; | ||
362 | ecmd->supported |= (SUPPORTED_FIBRE | SUPPORTED_TP); | ||
363 | ecmd->advertising |= (ADVERTISED_FIBRE | ADVERTISED_TP); | ||
364 | ecmd->port = PORT_FIBRE; | ||
365 | check_sfp_module = netif_running(dev) && ahw->has_link_events; | ||
366 | break; | ||
297 | default: | 367 | default: |
298 | dev_err(&adapter->pdev->dev, "Unsupported board model %d\n", | 368 | dev_err(&adapter->pdev->dev, "Unsupported board model %d\n", |
299 | adapter->ahw->board_type); | 369 | adapter->ahw->board_type); |
@@ -321,16 +391,10 @@ skip: | |||
321 | return 0; | 391 | return 0; |
322 | } | 392 | } |
323 | 393 | ||
324 | static int | 394 | static int qlcnic_set_port_config(struct qlcnic_adapter *adapter, |
325 | qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | 395 | struct ethtool_cmd *ecmd) |
326 | { | 396 | { |
327 | u32 config = 0; | 397 | u32 ret = 0, config = 0; |
328 | u32 ret = 0; | ||
329 | struct qlcnic_adapter *adapter = netdev_priv(dev); | ||
330 | |||
331 | if (adapter->ahw->port_type != QLCNIC_GBE) | ||
332 | return -EOPNOTSUPP; | ||
333 | |||
334 | /* read which mode */ | 398 | /* read which mode */ |
335 | if (ecmd->duplex) | 399 | if (ecmd->duplex) |
336 | config |= 0x1; | 400 | config |= 0x1; |
@@ -358,6 +422,24 @@ qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
358 | return -EOPNOTSUPP; | 422 | return -EOPNOTSUPP; |
359 | else if (ret) | 423 | else if (ret) |
360 | return -EIO; | 424 | return -EIO; |
425 | return ret; | ||
426 | } | ||
427 | |||
428 | static int qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | ||
429 | { | ||
430 | u32 ret = 0; | ||
431 | struct qlcnic_adapter *adapter = netdev_priv(dev); | ||
432 | |||
433 | if (adapter->ahw->port_type != QLCNIC_GBE) | ||
434 | return -EOPNOTSUPP; | ||
435 | |||
436 | if (qlcnic_83xx_check(adapter)) | ||
437 | ret = qlcnic_83xx_set_settings(adapter, ecmd); | ||
438 | else | ||
439 | ret = qlcnic_set_port_config(adapter, ecmd); | ||
440 | |||
441 | if (!ret) | ||
442 | return ret; | ||
361 | 443 | ||
362 | adapter->ahw->link_speed = ethtool_cmd_speed(ecmd); | 444 | adapter->ahw->link_speed = ethtool_cmd_speed(ecmd); |
363 | adapter->ahw->link_duplex = ecmd->duplex; | 445 | adapter->ahw->link_duplex = ecmd->duplex; |
@@ -370,6 +452,19 @@ qlcnic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
370 | return dev->netdev_ops->ndo_open(dev); | 452 | return dev->netdev_ops->ndo_open(dev); |
371 | } | 453 | } |
372 | 454 | ||
455 | static int qlcnic_82xx_get_registers(struct qlcnic_adapter *adapter, | ||
456 | u32 *regs_buff) | ||
457 | { | ||
458 | int i, j = 0; | ||
459 | |||
460 | for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++) | ||
461 | regs_buff[i] = QLC_SHARED_REG_RD32(adapter, diag_registers[j]); | ||
462 | j = 0; | ||
463 | while (ext_diag_registers[j] != -1) | ||
464 | regs_buff[i++] = QLCRD32(adapter, ext_diag_registers[j++]); | ||
465 | return i; | ||
466 | } | ||
467 | |||
373 | static void | 468 | static void |
374 | qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) | 469 | qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) |
375 | { | 470 | { |
@@ -377,17 +472,20 @@ qlcnic_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p) | |||
377 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | 472 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; |
378 | struct qlcnic_host_sds_ring *sds_ring; | 473 | struct qlcnic_host_sds_ring *sds_ring; |
379 | u32 *regs_buff = p; | 474 | u32 *regs_buff = p; |
380 | int ring, i = 0, j = 0; | 475 | int ring, i = 0; |
381 | 476 | ||
382 | memset(p, 0, qlcnic_get_regs_len(dev)); | 477 | memset(p, 0, qlcnic_get_regs_len(dev)); |
478 | |||
383 | regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) | | 479 | regs->version = (QLCNIC_ETHTOOL_REGS_VER << 24) | |
384 | (adapter->ahw->revision_id << 16) | (adapter->pdev)->device; | 480 | (adapter->ahw->revision_id << 16) | (adapter->pdev)->device; |
385 | 481 | ||
386 | regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff)); | 482 | regs_buff[0] = (0xcafe0000 | (QLCNIC_DEV_INFO_SIZE & 0xffff)); |
387 | regs_buff[1] = QLCNIC_MGMT_API_VERSION; | 483 | regs_buff[1] = QLCNIC_MGMT_API_VERSION; |
388 | 484 | ||
389 | for (i = QLCNIC_DEV_INFO_SIZE + 1; diag_registers[j] != -1; j++, i++) | 485 | if (qlcnic_82xx_check(adapter)) |
390 | regs_buff[i] = QLCRD32(adapter, diag_registers[j]); | 486 | i = qlcnic_82xx_get_registers(adapter, regs_buff); |
487 | else | ||
488 | i = qlcnic_83xx_get_registers(adapter, regs_buff); | ||
391 | 489 | ||
392 | if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) | 490 | if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) |
393 | return; | 491 | return; |
@@ -415,6 +513,10 @@ static u32 qlcnic_test_link(struct net_device *dev) | |||
415 | struct qlcnic_adapter *adapter = netdev_priv(dev); | 513 | struct qlcnic_adapter *adapter = netdev_priv(dev); |
416 | u32 val; | 514 | u32 val; |
417 | 515 | ||
516 | if (qlcnic_83xx_check(adapter)) { | ||
517 | val = qlcnic_83xx_test_link(adapter); | ||
518 | return (val & 1) ? 0 : 1; | ||
519 | } | ||
418 | val = QLCRD32(adapter, CRB_XG_STATE_P3P); | 520 | val = QLCRD32(adapter, CRB_XG_STATE_P3P); |
419 | val = XG_LINK_STATE_P3P(adapter->ahw->pci_func, val); | 521 | val = XG_LINK_STATE_P3P(adapter->ahw->pci_func, val); |
420 | return (val == XG_LINK_UP_P3P) ? 0 : 1; | 522 | return (val == XG_LINK_UP_P3P) ? 0 : 1; |
@@ -426,8 +528,10 @@ qlcnic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, | |||
426 | { | 528 | { |
427 | struct qlcnic_adapter *adapter = netdev_priv(dev); | 529 | struct qlcnic_adapter *adapter = netdev_priv(dev); |
428 | int offset; | 530 | int offset; |
429 | int ret; | 531 | int ret = -1; |
430 | 532 | ||
533 | if (qlcnic_83xx_check(adapter)) | ||
534 | return 0; | ||
431 | if (eeprom->len == 0) | 535 | if (eeprom->len == 0) |
432 | return -EINVAL; | 536 | return -EINVAL; |
433 | 537 | ||
@@ -435,8 +539,9 @@ qlcnic_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, | |||
435 | ((adapter->pdev)->device << 16); | 539 | ((adapter->pdev)->device << 16); |
436 | offset = eeprom->offset; | 540 | offset = eeprom->offset; |
437 | 541 | ||
438 | ret = qlcnic_rom_fast_read_words(adapter, offset, bytes, | 542 | if (qlcnic_82xx_check(adapter)) |
439 | eeprom->len); | 543 | ret = qlcnic_rom_fast_read_words(adapter, offset, bytes, |
544 | eeprom->len); | ||
440 | if (ret < 0) | 545 | if (ret < 0) |
441 | return ret; | 546 | return ret; |
442 | 547 | ||
@@ -529,11 +634,11 @@ static int qlcnic_set_channels(struct net_device *dev, | |||
529 | channel->tx_count != channel->max_tx) | 634 | channel->tx_count != channel->max_tx) |
530 | return -EINVAL; | 635 | return -EINVAL; |
531 | 636 | ||
532 | err = qlcnic_validate_max_rss(dev, channel->max_rx, channel->rx_count); | 637 | err = qlcnic_validate_max_rss(channel->max_rx, channel->rx_count); |
533 | if (err) | 638 | if (err) |
534 | return err; | 639 | return err; |
535 | 640 | ||
536 | err = qlcnic_set_max_rss(adapter, channel->rx_count); | 641 | err = qlcnic_set_max_rss(adapter, channel->rx_count, 0); |
537 | netdev_info(dev, "allocated 0x%x sds rings\n", | 642 | netdev_info(dev, "allocated 0x%x sds rings\n", |
538 | adapter->max_sds_rings); | 643 | adapter->max_sds_rings); |
539 | return err; | 644 | return err; |
@@ -547,6 +652,10 @@ qlcnic_get_pauseparam(struct net_device *netdev, | |||
547 | int port = adapter->ahw->physical_port; | 652 | int port = adapter->ahw->physical_port; |
548 | __u32 val; | 653 | __u32 val; |
549 | 654 | ||
655 | if (qlcnic_83xx_check(adapter)) { | ||
656 | qlcnic_83xx_get_pauseparam(adapter, pause); | ||
657 | return; | ||
658 | } | ||
550 | if (adapter->ahw->port_type == QLCNIC_GBE) { | 659 | if (adapter->ahw->port_type == QLCNIC_GBE) { |
551 | if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS)) | 660 | if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS)) |
552 | return; | 661 | return; |
@@ -592,6 +701,9 @@ qlcnic_set_pauseparam(struct net_device *netdev, | |||
592 | int port = adapter->ahw->physical_port; | 701 | int port = adapter->ahw->physical_port; |
593 | __u32 val; | 702 | __u32 val; |
594 | 703 | ||
704 | if (qlcnic_83xx_check(adapter)) | ||
705 | return qlcnic_83xx_set_pauseparam(adapter, pause); | ||
706 | |||
595 | /* read mode */ | 707 | /* read mode */ |
596 | if (adapter->ahw->port_type == QLCNIC_GBE) { | 708 | if (adapter->ahw->port_type == QLCNIC_GBE) { |
597 | if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS)) | 709 | if ((port < 0) || (port > QLCNIC_NIU_MAX_GBE_PORTS)) |
@@ -606,6 +718,7 @@ qlcnic_set_pauseparam(struct net_device *netdev, | |||
606 | 718 | ||
607 | QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), | 719 | QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), |
608 | val); | 720 | val); |
721 | QLCWR32(adapter, QLCNIC_NIU_GB_MAC_CONFIG_0(port), val); | ||
609 | /* set autoneg */ | 722 | /* set autoneg */ |
610 | val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL); | 723 | val = QLCRD32(adapter, QLCNIC_NIU_GB_PAUSE_CTL); |
611 | switch (port) { | 724 | switch (port) { |
@@ -668,6 +781,9 @@ static int qlcnic_reg_test(struct net_device *dev) | |||
668 | struct qlcnic_adapter *adapter = netdev_priv(dev); | 781 | struct qlcnic_adapter *adapter = netdev_priv(dev); |
669 | u32 data_read; | 782 | u32 data_read; |
670 | 783 | ||
784 | if (qlcnic_83xx_check(adapter)) | ||
785 | return qlcnic_83xx_reg_test(adapter); | ||
786 | |||
671 | data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0)); | 787 | data_read = QLCRD32(adapter, QLCNIC_PCIX_PH_REG(0)); |
672 | if ((data_read & 0xffff) != adapter->pdev->vendor) | 788 | if ((data_read & 0xffff) != adapter->pdev->vendor) |
673 | return 1; | 789 | return 1; |
@@ -675,16 +791,30 @@ static int qlcnic_reg_test(struct net_device *dev) | |||
675 | return 0; | 791 | return 0; |
676 | } | 792 | } |
677 | 793 | ||
794 | static int qlcnic_eeprom_test(struct net_device *dev) | ||
795 | { | ||
796 | struct qlcnic_adapter *adapter = netdev_priv(dev); | ||
797 | |||
798 | if (qlcnic_82xx_check(adapter)) | ||
799 | return 0; | ||
800 | |||
801 | return qlcnic_83xx_flash_test(adapter); | ||
802 | } | ||
803 | |||
678 | static int qlcnic_get_sset_count(struct net_device *dev, int sset) | 804 | static int qlcnic_get_sset_count(struct net_device *dev, int sset) |
679 | { | 805 | { |
806 | int len; | ||
807 | |||
680 | struct qlcnic_adapter *adapter = netdev_priv(dev); | 808 | struct qlcnic_adapter *adapter = netdev_priv(dev); |
681 | switch (sset) { | 809 | switch (sset) { |
682 | case ETH_SS_TEST: | 810 | case ETH_SS_TEST: |
683 | return QLCNIC_TEST_LEN; | 811 | return QLCNIC_TEST_LEN; |
684 | case ETH_SS_STATS: | 812 | case ETH_SS_STATS: |
685 | if (adapter->flags & QLCNIC_ESWITCH_ENABLED) | 813 | len = qlcnic_dev_statistics_len(adapter) + QLCNIC_STATS_LEN; |
686 | return QLCNIC_TOTAL_STATS_LEN + QLCNIC_DEVICE_STATS_LEN; | 814 | if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) || |
687 | return QLCNIC_TOTAL_STATS_LEN; | 815 | qlcnic_83xx_check(adapter)) |
816 | return len; | ||
817 | return qlcnic_82xx_statistics(); | ||
688 | default: | 818 | default: |
689 | return -EOPNOTSUPP; | 819 | return -EOPNOTSUPP; |
690 | } | 820 | } |
@@ -693,35 +823,36 @@ static int qlcnic_get_sset_count(struct net_device *dev, int sset) | |||
693 | static int qlcnic_irq_test(struct net_device *netdev) | 823 | static int qlcnic_irq_test(struct net_device *netdev) |
694 | { | 824 | { |
695 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 825 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
696 | int max_sds_rings = adapter->max_sds_rings; | 826 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
697 | int ret; | ||
698 | struct qlcnic_cmd_args cmd; | 827 | struct qlcnic_cmd_args cmd; |
828 | int ret, max_sds_rings = adapter->max_sds_rings; | ||
829 | |||
830 | if (qlcnic_83xx_check(adapter)) | ||
831 | return qlcnic_83xx_interrupt_test(netdev); | ||
699 | 832 | ||
700 | if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) | 833 | if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) |
701 | return -EIO; | 834 | return -EIO; |
702 | 835 | ||
703 | ret = qlcnic_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST); | 836 | ret = qlcnic_diag_alloc_res(netdev, QLCNIC_INTERRUPT_TEST); |
704 | if (ret) | 837 | if (ret) |
705 | goto clear_it; | 838 | goto clear_diag_irq; |
706 | 839 | ||
707 | adapter->ahw->diag_cnt = 0; | 840 | ahw->diag_cnt = 0; |
708 | memset(&cmd, 0, sizeof(cmd)); | 841 | qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_INTRPT_TEST); |
709 | cmd.req.cmd = QLCNIC_CDRP_CMD_INTRPT_TEST; | ||
710 | cmd.req.arg1 = adapter->ahw->pci_func; | ||
711 | qlcnic_issue_cmd(adapter, &cmd); | ||
712 | ret = cmd.rsp.cmd; | ||
713 | 842 | ||
843 | cmd.req.arg[1] = ahw->pci_func; | ||
844 | ret = qlcnic_issue_cmd(adapter, &cmd); | ||
714 | if (ret) | 845 | if (ret) |
715 | goto done; | 846 | goto done; |
716 | 847 | ||
717 | msleep(10); | 848 | usleep_range(1000, 12000); |
718 | 849 | ret = !ahw->diag_cnt; | |
719 | ret = !adapter->ahw->diag_cnt; | ||
720 | 850 | ||
721 | done: | 851 | done: |
852 | qlcnic_free_mbx_args(&cmd); | ||
722 | qlcnic_diag_free_res(netdev, max_sds_rings); | 853 | qlcnic_diag_free_res(netdev, max_sds_rings); |
723 | 854 | ||
724 | clear_it: | 855 | clear_diag_irq: |
725 | adapter->max_sds_rings = max_sds_rings; | 856 | adapter->max_sds_rings = max_sds_rings; |
726 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 857 | clear_bit(__QLCNIC_RESETTING, &adapter->state); |
727 | return ret; | 858 | return ret; |
@@ -750,7 +881,7 @@ int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[]) | |||
750 | return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE); | 881 | return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE); |
751 | } | 882 | } |
752 | 883 | ||
753 | static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode) | 884 | int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode) |
754 | { | 885 | { |
755 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | 886 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; |
756 | struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0]; | 887 | struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0]; |
@@ -761,11 +892,10 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode) | |||
761 | skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE); | 892 | skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE); |
762 | qlcnic_create_loopback_buff(skb->data, adapter->mac_addr); | 893 | qlcnic_create_loopback_buff(skb->data, adapter->mac_addr); |
763 | skb_put(skb, QLCNIC_ILB_PKT_SIZE); | 894 | skb_put(skb, QLCNIC_ILB_PKT_SIZE); |
764 | |||
765 | adapter->ahw->diag_cnt = 0; | 895 | adapter->ahw->diag_cnt = 0; |
766 | qlcnic_xmit_frame(skb, adapter->netdev); | 896 | qlcnic_xmit_frame(skb, adapter->netdev); |
767 | |||
768 | loop = 0; | 897 | loop = 0; |
898 | |||
769 | do { | 899 | do { |
770 | msleep(1); | 900 | msleep(1); |
771 | qlcnic_process_rcv_ring_diag(sds_ring); | 901 | qlcnic_process_rcv_ring_diag(sds_ring); |
@@ -776,42 +906,46 @@ static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode) | |||
776 | dev_kfree_skb_any(skb); | 906 | dev_kfree_skb_any(skb); |
777 | 907 | ||
778 | if (!adapter->ahw->diag_cnt) | 908 | if (!adapter->ahw->diag_cnt) |
779 | QLCDB(adapter, DRV, | 909 | dev_warn(&adapter->pdev->dev, |
780 | "LB Test: packet #%d was not received\n", i + 1); | 910 | "LB Test: packet #%d was not received\n", |
911 | i + 1); | ||
781 | else | 912 | else |
782 | cnt++; | 913 | cnt++; |
783 | } | 914 | } |
784 | if (cnt != i) { | 915 | if (cnt != i) { |
785 | dev_warn(&adapter->pdev->dev, "LB Test failed\n"); | 916 | dev_err(&adapter->pdev->dev, |
786 | if (mode != QLCNIC_ILB_MODE) { | 917 | "LB Test: failed, TX[%d], RX[%d]\n", i, cnt); |
918 | if (mode != QLCNIC_ILB_MODE) | ||
787 | dev_warn(&adapter->pdev->dev, | 919 | dev_warn(&adapter->pdev->dev, |
788 | "WARNING: Please make sure external" | 920 | "WARNING: Please check loopback cable\n"); |
789 | "loopback connector is plugged in\n"); | ||
790 | } | ||
791 | return -1; | 921 | return -1; |
792 | } | 922 | } |
793 | return 0; | 923 | return 0; |
794 | } | 924 | } |
795 | 925 | ||
796 | static int qlcnic_loopback_test(struct net_device *netdev, u8 mode) | 926 | int qlcnic_loopback_test(struct net_device *netdev, u8 mode) |
797 | { | 927 | { |
798 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 928 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
799 | int max_sds_rings = adapter->max_sds_rings; | 929 | int max_sds_rings = adapter->max_sds_rings; |
800 | struct qlcnic_host_sds_ring *sds_ring; | 930 | struct qlcnic_host_sds_ring *sds_ring; |
931 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
801 | int loop = 0; | 932 | int loop = 0; |
802 | int ret; | 933 | int ret; |
803 | 934 | ||
804 | if (!(adapter->ahw->capabilities & | 935 | if (qlcnic_83xx_check(adapter)) |
805 | QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) { | 936 | return qlcnic_83xx_loopback_test(netdev, mode); |
806 | netdev_info(netdev, "Firmware is not loopback test capable\n"); | 937 | |
938 | if (!(ahw->capabilities & QLCNIC_FW_CAPABILITY_MULTI_LOOPBACK)) { | ||
939 | dev_info(&adapter->pdev->dev, | ||
940 | "Firmware do not support loopback test\n"); | ||
807 | return -EOPNOTSUPP; | 941 | return -EOPNOTSUPP; |
808 | } | 942 | } |
809 | 943 | ||
810 | QLCDB(adapter, DRV, "%s loopback test in progress\n", | 944 | dev_warn(&adapter->pdev->dev, "%s loopback test in progress\n", |
811 | mode == QLCNIC_ILB_MODE ? "internal" : "external"); | 945 | mode == QLCNIC_ILB_MODE ? "internal" : "external"); |
812 | if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { | 946 | if (ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { |
813 | netdev_warn(netdev, "Loopback test not supported for non " | 947 | dev_warn(&adapter->pdev->dev, |
814 | "privilege function\n"); | 948 | "Loopback test not supported in nonprivileged mode\n"); |
815 | return 0; | 949 | return 0; |
816 | } | 950 | } |
817 | 951 | ||
@@ -823,12 +957,11 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode) | |||
823 | goto clear_it; | 957 | goto clear_it; |
824 | 958 | ||
825 | sds_ring = &adapter->recv_ctx->sds_rings[0]; | 959 | sds_ring = &adapter->recv_ctx->sds_rings[0]; |
826 | |||
827 | ret = qlcnic_set_lb_mode(adapter, mode); | 960 | ret = qlcnic_set_lb_mode(adapter, mode); |
828 | if (ret) | 961 | if (ret) |
829 | goto free_res; | 962 | goto free_res; |
830 | 963 | ||
831 | adapter->ahw->diag_cnt = 0; | 964 | ahw->diag_cnt = 0; |
832 | do { | 965 | do { |
833 | msleep(500); | 966 | msleep(500); |
834 | qlcnic_process_rcv_ring_diag(sds_ring); | 967 | qlcnic_process_rcv_ring_diag(sds_ring); |
@@ -841,11 +974,11 @@ static int qlcnic_loopback_test(struct net_device *netdev, u8 mode) | |||
841 | ret = adapter->ahw->diag_cnt; | 974 | ret = adapter->ahw->diag_cnt; |
842 | goto free_res; | 975 | goto free_res; |
843 | } | 976 | } |
844 | } while (!QLCNIC_IS_LB_CONFIGURED(adapter->ahw->loopback_state)); | 977 | } while (!QLCNIC_IS_LB_CONFIGURED(ahw->loopback_state)); |
845 | 978 | ||
846 | ret = qlcnic_do_lb_test(adapter, mode); | 979 | ret = qlcnic_do_lb_test(adapter, mode); |
847 | 980 | ||
848 | qlcnic_clear_lb_mode(adapter); | 981 | qlcnic_clear_lb_mode(adapter, mode); |
849 | 982 | ||
850 | free_res: | 983 | free_res: |
851 | qlcnic_diag_free_res(netdev, max_sds_rings); | 984 | qlcnic_diag_free_res(netdev, max_sds_rings); |
@@ -878,20 +1011,18 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test, | |||
878 | data[3] = qlcnic_loopback_test(dev, QLCNIC_ILB_MODE); | 1011 | data[3] = qlcnic_loopback_test(dev, QLCNIC_ILB_MODE); |
879 | if (data[3]) | 1012 | if (data[3]) |
880 | eth_test->flags |= ETH_TEST_FL_FAILED; | 1013 | eth_test->flags |= ETH_TEST_FL_FAILED; |
881 | if (eth_test->flags & ETH_TEST_FL_EXTERNAL_LB) { | 1014 | |
882 | data[4] = qlcnic_loopback_test(dev, QLCNIC_ELB_MODE); | 1015 | data[4] = qlcnic_eeprom_test(dev); |
883 | if (data[4]) | 1016 | if (data[4]) |
884 | eth_test->flags |= ETH_TEST_FL_FAILED; | 1017 | eth_test->flags |= ETH_TEST_FL_FAILED; |
885 | eth_test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE; | ||
886 | } | ||
887 | } | 1018 | } |
888 | } | 1019 | } |
889 | 1020 | ||
890 | static void | 1021 | static void |
891 | qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data) | 1022 | qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 *data) |
892 | { | 1023 | { |
893 | struct qlcnic_adapter *adapter = netdev_priv(dev); | 1024 | struct qlcnic_adapter *adapter = netdev_priv(dev); |
894 | int index, i, j; | 1025 | int index, i, num_stats; |
895 | 1026 | ||
896 | switch (stringset) { | 1027 | switch (stringset) { |
897 | case ETH_SS_TEST: | 1028 | case ETH_SS_TEST: |
@@ -904,14 +1035,34 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data) | |||
904 | qlcnic_gstrings_stats[index].stat_string, | 1035 | qlcnic_gstrings_stats[index].stat_string, |
905 | ETH_GSTRING_LEN); | 1036 | ETH_GSTRING_LEN); |
906 | } | 1037 | } |
907 | for (j = 0; j < QLCNIC_MAC_STATS_LEN; index++, j++) { | 1038 | if (qlcnic_83xx_check(adapter)) { |
908 | memcpy(data + index * ETH_GSTRING_LEN, | 1039 | num_stats = ARRAY_SIZE(qlcnic_83xx_tx_stats_strings); |
909 | qlcnic_mac_stats_strings[j], | 1040 | for (i = 0; i < num_stats; i++, index++) |
910 | ETH_GSTRING_LEN); | 1041 | memcpy(data + index * ETH_GSTRING_LEN, |
1042 | qlcnic_83xx_tx_stats_strings[i], | ||
1043 | ETH_GSTRING_LEN); | ||
1044 | num_stats = ARRAY_SIZE(qlcnic_83xx_mac_stats_strings); | ||
1045 | for (i = 0; i < num_stats; i++, index++) | ||
1046 | memcpy(data + index * ETH_GSTRING_LEN, | ||
1047 | qlcnic_83xx_mac_stats_strings[i], | ||
1048 | ETH_GSTRING_LEN); | ||
1049 | num_stats = ARRAY_SIZE(qlcnic_83xx_rx_stats_strings); | ||
1050 | for (i = 0; i < num_stats; i++, index++) | ||
1051 | memcpy(data + index * ETH_GSTRING_LEN, | ||
1052 | qlcnic_83xx_rx_stats_strings[i], | ||
1053 | ETH_GSTRING_LEN); | ||
1054 | return; | ||
1055 | } else { | ||
1056 | num_stats = ARRAY_SIZE(qlcnic_83xx_mac_stats_strings); | ||
1057 | for (i = 0; i < num_stats; i++, index++) | ||
1058 | memcpy(data + index * ETH_GSTRING_LEN, | ||
1059 | qlcnic_83xx_mac_stats_strings[i], | ||
1060 | ETH_GSTRING_LEN); | ||
911 | } | 1061 | } |
912 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) | 1062 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) |
913 | return; | 1063 | return; |
914 | for (i = 0; i < QLCNIC_DEVICE_STATS_LEN; index++, i++) { | 1064 | num_stats = ARRAY_SIZE(qlcnic_device_gstrings_stats); |
1065 | for (i = 0; i < num_stats; index++, i++) { | ||
915 | memcpy(data + index * ETH_GSTRING_LEN, | 1066 | memcpy(data + index * ETH_GSTRING_LEN, |
916 | qlcnic_device_gstrings_stats[i], | 1067 | qlcnic_device_gstrings_stats[i], |
917 | ETH_GSTRING_LEN); | 1068 | ETH_GSTRING_LEN); |
@@ -920,89 +1071,84 @@ qlcnic_get_strings(struct net_device *dev, u32 stringset, u8 * data) | |||
920 | } | 1071 | } |
921 | 1072 | ||
922 | static void | 1073 | static void |
923 | qlcnic_fill_stats(int *index, u64 *data, void *stats, int type) | 1074 | qlcnic_fill_stats(u64 *data, void *stats, int type) |
924 | { | 1075 | { |
925 | int ind = *index; | ||
926 | |||
927 | if (type == QLCNIC_MAC_STATS) { | 1076 | if (type == QLCNIC_MAC_STATS) { |
928 | struct qlcnic_mac_statistics *mac_stats = | 1077 | struct qlcnic_mac_statistics *mac_stats = |
929 | (struct qlcnic_mac_statistics *)stats; | 1078 | (struct qlcnic_mac_statistics *)stats; |
930 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_frames); | 1079 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_frames); |
931 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_bytes); | 1080 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_bytes); |
932 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_mcast_pkts); | 1081 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_mcast_pkts); |
933 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_bcast_pkts); | 1082 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_bcast_pkts); |
934 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_pause_cnt); | 1083 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_pause_cnt); |
935 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_ctrl_pkt); | 1084 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_ctrl_pkt); |
936 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_64b_pkts); | 1085 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_64b_pkts); |
937 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_127b_pkts); | 1086 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_127b_pkts); |
938 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_255b_pkts); | 1087 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_255b_pkts); |
939 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_511b_pkts); | 1088 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_511b_pkts); |
940 | data[ind++] = | 1089 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1023b_pkts); |
941 | QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1023b_pkts); | 1090 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1518b_pkts); |
942 | data[ind++] = | 1091 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_tx_gt_1518b_pkts); |
943 | QLCNIC_FILL_STATS(mac_stats->mac_tx_lt_1518b_pkts); | 1092 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_frames); |
944 | data[ind++] = | 1093 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_bytes); |
945 | QLCNIC_FILL_STATS(mac_stats->mac_tx_gt_1518b_pkts); | 1094 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_mcast_pkts); |
946 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_frames); | 1095 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_bcast_pkts); |
947 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_bytes); | 1096 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_pause_cnt); |
948 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_mcast_pkts); | 1097 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_ctrl_pkt); |
949 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_bcast_pkts); | 1098 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_64b_pkts); |
950 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_pause_cnt); | 1099 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_127b_pkts); |
951 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_ctrl_pkt); | 1100 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_255b_pkts); |
952 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_64b_pkts); | 1101 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_511b_pkts); |
953 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_127b_pkts); | 1102 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1023b_pkts); |
954 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_255b_pkts); | 1103 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1518b_pkts); |
955 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_511b_pkts); | 1104 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_gt_1518b_pkts); |
956 | data[ind++] = | 1105 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_error); |
957 | QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1023b_pkts); | 1106 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_small); |
958 | data[ind++] = | 1107 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_large); |
959 | QLCNIC_FILL_STATS(mac_stats->mac_rx_lt_1518b_pkts); | 1108 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_jabber); |
960 | data[ind++] = | 1109 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_dropped); |
961 | QLCNIC_FILL_STATS(mac_stats->mac_rx_gt_1518b_pkts); | 1110 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_rx_crc_error); |
962 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_error); | 1111 | *data++ = QLCNIC_FILL_STATS(mac_stats->mac_align_error); |
963 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_small); | ||
964 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_length_large); | ||
965 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_jabber); | ||
966 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_dropped); | ||
967 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_rx_crc_error); | ||
968 | data[ind++] = QLCNIC_FILL_STATS(mac_stats->mac_align_error); | ||
969 | } else if (type == QLCNIC_ESW_STATS) { | 1112 | } else if (type == QLCNIC_ESW_STATS) { |
970 | struct __qlcnic_esw_statistics *esw_stats = | 1113 | struct __qlcnic_esw_statistics *esw_stats = |
971 | (struct __qlcnic_esw_statistics *)stats; | 1114 | (struct __qlcnic_esw_statistics *)stats; |
972 | data[ind++] = QLCNIC_FILL_STATS(esw_stats->unicast_frames); | 1115 | *data++ = QLCNIC_FILL_STATS(esw_stats->unicast_frames); |
973 | data[ind++] = QLCNIC_FILL_STATS(esw_stats->multicast_frames); | 1116 | *data++ = QLCNIC_FILL_STATS(esw_stats->multicast_frames); |
974 | data[ind++] = QLCNIC_FILL_STATS(esw_stats->broadcast_frames); | 1117 | *data++ = QLCNIC_FILL_STATS(esw_stats->broadcast_frames); |
975 | data[ind++] = QLCNIC_FILL_STATS(esw_stats->dropped_frames); | 1118 | *data++ = QLCNIC_FILL_STATS(esw_stats->dropped_frames); |
976 | data[ind++] = QLCNIC_FILL_STATS(esw_stats->errors); | 1119 | *data++ = QLCNIC_FILL_STATS(esw_stats->errors); |
977 | data[ind++] = QLCNIC_FILL_STATS(esw_stats->local_frames); | 1120 | *data++ = QLCNIC_FILL_STATS(esw_stats->local_frames); |
978 | data[ind++] = QLCNIC_FILL_STATS(esw_stats->numbytes); | 1121 | *data++ = QLCNIC_FILL_STATS(esw_stats->numbytes); |
979 | } | 1122 | } |
980 | |||
981 | *index = ind; | ||
982 | } | 1123 | } |
983 | 1124 | ||
984 | static void | 1125 | static void qlcnic_get_ethtool_stats(struct net_device *dev, |
985 | qlcnic_get_ethtool_stats(struct net_device *dev, | 1126 | struct ethtool_stats *stats, u64 *data) |
986 | struct ethtool_stats *stats, u64 * data) | ||
987 | { | 1127 | { |
988 | struct qlcnic_adapter *adapter = netdev_priv(dev); | 1128 | struct qlcnic_adapter *adapter = netdev_priv(dev); |
989 | struct qlcnic_esw_statistics port_stats; | 1129 | struct qlcnic_esw_statistics port_stats; |
990 | struct qlcnic_mac_statistics mac_stats; | 1130 | struct qlcnic_mac_statistics mac_stats; |
991 | int index, ret; | 1131 | int index, ret, length, size; |
992 | 1132 | char *p; | |
993 | for (index = 0; index < QLCNIC_STATS_LEN; index++) { | 1133 | |
994 | char *p = | 1134 | memset(data, 0, stats->n_stats * sizeof(u64)); |
995 | (char *)adapter + | 1135 | length = QLCNIC_STATS_LEN; |
996 | qlcnic_gstrings_stats[index].stat_offset; | 1136 | for (index = 0; index < length; index++) { |
997 | data[index] = | 1137 | p = (char *)adapter + qlcnic_gstrings_stats[index].stat_offset; |
998 | (qlcnic_gstrings_stats[index].sizeof_stat == | 1138 | size = qlcnic_gstrings_stats[index].sizeof_stat; |
999 | sizeof(u64)) ? *(u64 *)p:(*(u32 *)p); | 1139 | *data++ = (size == sizeof(u64)) ? (*(u64 *)p) : ((*(u32 *)p)); |
1000 | } | 1140 | } |
1001 | 1141 | ||
1002 | /* Retrieve MAC statistics from firmware */ | 1142 | if (qlcnic_83xx_check(adapter)) { |
1003 | memset(&mac_stats, 0, sizeof(struct qlcnic_mac_statistics)); | 1143 | if (adapter->ahw->linkup) |
1004 | qlcnic_get_mac_stats(adapter, &mac_stats); | 1144 | qlcnic_83xx_get_stats(adapter, data); |
1005 | qlcnic_fill_stats(&index, data, &mac_stats, QLCNIC_MAC_STATS); | 1145 | return; |
1146 | } else { | ||
1147 | /* Retrieve MAC statistics from firmware */ | ||
1148 | memset(&mac_stats, 0, sizeof(struct qlcnic_mac_statistics)); | ||
1149 | qlcnic_get_mac_stats(adapter, &mac_stats); | ||
1150 | qlcnic_fill_stats(data, &mac_stats, QLCNIC_MAC_STATS); | ||
1151 | } | ||
1006 | 1152 | ||
1007 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) | 1153 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) |
1008 | return; | 1154 | return; |
@@ -1013,14 +1159,13 @@ qlcnic_get_ethtool_stats(struct net_device *dev, | |||
1013 | if (ret) | 1159 | if (ret) |
1014 | return; | 1160 | return; |
1015 | 1161 | ||
1016 | qlcnic_fill_stats(&index, data, &port_stats.rx, QLCNIC_ESW_STATS); | 1162 | qlcnic_fill_stats(data, &port_stats.rx, QLCNIC_ESW_STATS); |
1017 | |||
1018 | ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func, | 1163 | ret = qlcnic_get_port_stats(adapter, adapter->ahw->pci_func, |
1019 | QLCNIC_QUERY_TX_COUNTER, &port_stats.tx); | 1164 | QLCNIC_QUERY_TX_COUNTER, &port_stats.tx); |
1020 | if (ret) | 1165 | if (ret) |
1021 | return; | 1166 | return; |
1022 | 1167 | ||
1023 | qlcnic_fill_stats(&index, data, &port_stats.tx, QLCNIC_ESW_STATS); | 1168 | qlcnic_fill_stats(data, &port_stats.tx, QLCNIC_ESW_STATS); |
1024 | } | 1169 | } |
1025 | 1170 | ||
1026 | static int qlcnic_set_led(struct net_device *dev, | 1171 | static int qlcnic_set_led(struct net_device *dev, |
@@ -1030,6 +1175,8 @@ static int qlcnic_set_led(struct net_device *dev, | |||
1030 | int max_sds_rings = adapter->max_sds_rings; | 1175 | int max_sds_rings = adapter->max_sds_rings; |
1031 | int err = -EIO, active = 1; | 1176 | int err = -EIO, active = 1; |
1032 | 1177 | ||
1178 | if (qlcnic_83xx_check(adapter)) | ||
1179 | return -EOPNOTSUPP; | ||
1033 | if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { | 1180 | if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { |
1034 | netdev_warn(dev, "LED test not supported for non " | 1181 | netdev_warn(dev, "LED test not supported for non " |
1035 | "privilege function\n"); | 1182 | "privilege function\n"); |
@@ -1096,6 +1243,8 @@ qlcnic_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | |||
1096 | struct qlcnic_adapter *adapter = netdev_priv(dev); | 1243 | struct qlcnic_adapter *adapter = netdev_priv(dev); |
1097 | u32 wol_cfg; | 1244 | u32 wol_cfg; |
1098 | 1245 | ||
1246 | if (qlcnic_83xx_check(adapter)) | ||
1247 | return; | ||
1099 | wol->supported = 0; | 1248 | wol->supported = 0; |
1100 | wol->wolopts = 0; | 1249 | wol->wolopts = 0; |
1101 | 1250 | ||
@@ -1114,8 +1263,10 @@ qlcnic_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | |||
1114 | struct qlcnic_adapter *adapter = netdev_priv(dev); | 1263 | struct qlcnic_adapter *adapter = netdev_priv(dev); |
1115 | u32 wol_cfg; | 1264 | u32 wol_cfg; |
1116 | 1265 | ||
1117 | if (wol->wolopts & ~WAKE_MAGIC) | 1266 | if (qlcnic_83xx_check(adapter)) |
1118 | return -EOPNOTSUPP; | 1267 | return -EOPNOTSUPP; |
1268 | if (wol->wolopts & ~WAKE_MAGIC) | ||
1269 | return -EINVAL; | ||
1119 | 1270 | ||
1120 | wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV); | 1271 | wol_cfg = QLCRD32(adapter, QLCNIC_WOL_CONFIG_NV); |
1121 | if (!(wol_cfg & (1 << adapter->portnum))) | 1272 | if (!(wol_cfg & (1 << adapter->portnum))) |
@@ -1307,7 +1458,7 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) | |||
1307 | return 0; | 1458 | return 0; |
1308 | } | 1459 | } |
1309 | netdev_info(netdev, "Forcing a FW dump\n"); | 1460 | netdev_info(netdev, "Forcing a FW dump\n"); |
1310 | qlcnic_dev_request_reset(adapter); | 1461 | qlcnic_dev_request_reset(adapter, val->flag); |
1311 | break; | 1462 | break; |
1312 | case QLCNIC_DISABLE_FW_DUMP: | 1463 | case QLCNIC_DISABLE_FW_DUMP: |
1313 | if (fw_dump->enable && fw_dump->tmpl_hdr) { | 1464 | if (fw_dump->enable && fw_dump->tmpl_hdr) { |
@@ -1327,7 +1478,7 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) | |||
1327 | return 0; | 1478 | return 0; |
1328 | case QLCNIC_FORCE_FW_RESET: | 1479 | case QLCNIC_FORCE_FW_RESET: |
1329 | netdev_info(netdev, "Forcing a FW reset\n"); | 1480 | netdev_info(netdev, "Forcing a FW reset\n"); |
1330 | qlcnic_dev_request_reset(adapter); | 1481 | qlcnic_dev_request_reset(adapter, val->flag); |
1331 | adapter->flags &= ~QLCNIC_FW_RESET_OWNER; | 1482 | adapter->flags &= ~QLCNIC_FW_RESET_OWNER; |
1332 | return 0; | 1483 | return 0; |
1333 | case QLCNIC_SET_QUIESCENT: | 1484 | case QLCNIC_SET_QUIESCENT: |
@@ -1341,8 +1492,8 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val) | |||
1341 | netdev_err(netdev, "FW dump not supported\n"); | 1492 | netdev_err(netdev, "FW dump not supported\n"); |
1342 | return -ENOTSUPP; | 1493 | return -ENOTSUPP; |
1343 | } | 1494 | } |
1344 | for (i = 0; i < ARRAY_SIZE(FW_DUMP_LEVELS); i++) { | 1495 | for (i = 0; i < ARRAY_SIZE(qlcnic_fw_dump_level); i++) { |
1345 | if (val->flag == FW_DUMP_LEVELS[i]) { | 1496 | if (val->flag == qlcnic_fw_dump_level[i]) { |
1346 | fw_dump->tmpl_hdr->drv_cap_mask = | 1497 | fw_dump->tmpl_hdr->drv_cap_mask = |
1347 | val->flag; | 1498 | val->flag; |
1348 | netdev_info(netdev, "Driver mask changed to: 0x%x\n", | 1499 | netdev_info(netdev, "Driver mask changed to: 0x%x\n", |
@@ -1386,10 +1537,3 @@ const struct ethtool_ops qlcnic_ethtool_ops = { | |||
1386 | .get_dump_data = qlcnic_get_dump_data, | 1537 | .get_dump_data = qlcnic_get_dump_data, |
1387 | .set_dump = qlcnic_set_dump, | 1538 | .set_dump = qlcnic_set_dump, |
1388 | }; | 1539 | }; |
1389 | |||
1390 | const struct ethtool_ops qlcnic_ethtool_failed_ops = { | ||
1391 | .get_settings = qlcnic_get_settings, | ||
1392 | .get_drvinfo = qlcnic_get_drvinfo, | ||
1393 | .set_msglevel = qlcnic_set_msglevel, | ||
1394 | .get_msglevel = qlcnic_get_msglevel, | ||
1395 | }; | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h index 49cc1ac4f057..44197ca1456c 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hdr.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * QLogic qlcnic NIC Driver | 2 | * QLogic qlcnic NIC Driver |
3 | * Copyright (c) 2009-2010 QLogic Corporation | 3 | * Copyright (c) 2009-2013 QLogic Corporation |
4 | * | 4 | * |
5 | * See LICENSE.qlcnic for copyright and licensing details. | 5 | * See LICENSE.qlcnic for copyright and licensing details. |
6 | */ | 6 | */ |
@@ -11,6 +11,8 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | 13 | ||
14 | #include "qlcnic_hw.h" | ||
15 | |||
14 | /* | 16 | /* |
15 | * The basic unit of access when reading/writing control registers. | 17 | * The basic unit of access when reading/writing control registers. |
16 | */ | 18 | */ |
@@ -387,9 +389,6 @@ enum { | |||
387 | #define QLCNIC_ROMUSB_ROM_DUMMY_BYTE_CNT (ROMUSB_ROM + 0x0014) | 389 | #define QLCNIC_ROMUSB_ROM_DUMMY_BYTE_CNT (ROMUSB_ROM + 0x0014) |
388 | #define QLCNIC_ROMUSB_ROM_RDATA (ROMUSB_ROM + 0x0018) | 390 | #define QLCNIC_ROMUSB_ROM_RDATA (ROMUSB_ROM + 0x0018) |
389 | 391 | ||
390 | /* Lock IDs for ROM lock */ | ||
391 | #define ROM_LOCK_DRIVER 0x0d417340 | ||
392 | |||
393 | /****************************************************************************** | 392 | /****************************************************************************** |
394 | * | 393 | * |
395 | * Definitions specific to M25P flash | 394 | * Definitions specific to M25P flash |
@@ -449,13 +448,10 @@ enum { | |||
449 | #define ISR_INT_TARGET_STATUS_F7 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_STATUS_F7)) | 448 | #define ISR_INT_TARGET_STATUS_F7 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_STATUS_F7)) |
450 | #define ISR_INT_TARGET_MASK_F7 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_MASK_F7)) | 449 | #define ISR_INT_TARGET_MASK_F7 (QLCNIC_PCIX_PS_REG(PCIX_TARGET_MASK_F7)) |
451 | 450 | ||
452 | #define QLCNIC_PCI_MN_2M (0) | ||
453 | #define QLCNIC_PCI_MS_2M (0x80000) | ||
454 | #define QLCNIC_PCI_OCM0_2M (0x000c0000UL) | 451 | #define QLCNIC_PCI_OCM0_2M (0x000c0000UL) |
455 | #define QLCNIC_PCI_CRBSPACE (0x06000000UL) | 452 | #define QLCNIC_PCI_CRBSPACE (0x06000000UL) |
456 | #define QLCNIC_PCI_CAMQM (0x04800000UL) | 453 | #define QLCNIC_PCI_CAMQM (0x04800000UL) |
457 | #define QLCNIC_PCI_CAMQM_END (0x04800800UL) | 454 | #define QLCNIC_PCI_CAMQM_END (0x04800800UL) |
458 | #define QLCNIC_PCI_2MB_SIZE (0x00200000UL) | ||
459 | #define QLCNIC_PCI_CAMQM_2M_BASE (0x000ff800UL) | 455 | #define QLCNIC_PCI_CAMQM_2M_BASE (0x000ff800UL) |
460 | 456 | ||
461 | #define QLCNIC_CRB_CAM QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_CAM) | 457 | #define QLCNIC_CRB_CAM QLCNIC_PCI_CRB_WINDOW(QLCNIC_HW_PX_MAP_CRB_CAM) |
@@ -491,7 +487,7 @@ enum { | |||
491 | #define QLCNIC_NIU_GB_MAC_CONFIG_1(I) \ | 487 | #define QLCNIC_NIU_GB_MAC_CONFIG_1(I) \ |
492 | (QLCNIC_CRB_NIU + 0x30004 + (I)*0x10000) | 488 | (QLCNIC_CRB_NIU + 0x30004 + (I)*0x10000) |
493 | 489 | ||
494 | 490 | #define MAX_CTL_CHECK 1000 | |
495 | #define TEST_AGT_CTRL (0x00) | 491 | #define TEST_AGT_CTRL (0x00) |
496 | 492 | ||
497 | #define TA_CTL_START BIT_0 | 493 | #define TA_CTL_START BIT_0 |
@@ -499,44 +495,6 @@ enum { | |||
499 | #define TA_CTL_WRITE BIT_2 | 495 | #define TA_CTL_WRITE BIT_2 |
500 | #define TA_CTL_BUSY BIT_3 | 496 | #define TA_CTL_BUSY BIT_3 |
501 | 497 | ||
502 | /* | ||
503 | * Register offsets for MN | ||
504 | */ | ||
505 | #define MIU_TEST_AGT_BASE (0x90) | ||
506 | |||
507 | #define MIU_TEST_AGT_ADDR_LO (0x04) | ||
508 | #define MIU_TEST_AGT_ADDR_HI (0x08) | ||
509 | #define MIU_TEST_AGT_WRDATA_LO (0x10) | ||
510 | #define MIU_TEST_AGT_WRDATA_HI (0x14) | ||
511 | #define MIU_TEST_AGT_WRDATA_UPPER_LO (0x20) | ||
512 | #define MIU_TEST_AGT_WRDATA_UPPER_HI (0x24) | ||
513 | #define MIU_TEST_AGT_WRDATA(i) (0x10+(0x10*((i)>>1))+(4*((i)&1))) | ||
514 | #define MIU_TEST_AGT_RDDATA_LO (0x18) | ||
515 | #define MIU_TEST_AGT_RDDATA_HI (0x1c) | ||
516 | #define MIU_TEST_AGT_RDDATA_UPPER_LO (0x28) | ||
517 | #define MIU_TEST_AGT_RDDATA_UPPER_HI (0x2c) | ||
518 | #define MIU_TEST_AGT_RDDATA(i) (0x18+(0x10*((i)>>1))+(4*((i)&1))) | ||
519 | |||
520 | #define MIU_TEST_AGT_ADDR_MASK 0xfffffff8 | ||
521 | #define MIU_TEST_AGT_UPPER_ADDR(off) (0) | ||
522 | |||
523 | /* | ||
524 | * Register offsets for MS | ||
525 | */ | ||
526 | #define SIU_TEST_AGT_BASE (0x60) | ||
527 | |||
528 | #define SIU_TEST_AGT_ADDR_LO (0x04) | ||
529 | #define SIU_TEST_AGT_ADDR_HI (0x18) | ||
530 | #define SIU_TEST_AGT_WRDATA_LO (0x08) | ||
531 | #define SIU_TEST_AGT_WRDATA_HI (0x0c) | ||
532 | #define SIU_TEST_AGT_WRDATA(i) (0x08+(4*(i))) | ||
533 | #define SIU_TEST_AGT_RDDATA_LO (0x10) | ||
534 | #define SIU_TEST_AGT_RDDATA_HI (0x14) | ||
535 | #define SIU_TEST_AGT_RDDATA(i) (0x10+(4*(i))) | ||
536 | |||
537 | #define SIU_TEST_AGT_ADDR_MASK 0x3ffff8 | ||
538 | #define SIU_TEST_AGT_UPPER_ADDR(off) ((off)>>22) | ||
539 | |||
540 | /* XG Link status */ | 498 | /* XG Link status */ |
541 | #define XG_LINK_UP 0x10 | 499 | #define XG_LINK_UP 0x10 |
542 | #define XG_LINK_DOWN 0x20 | 500 | #define XG_LINK_DOWN 0x20 |
@@ -556,9 +514,6 @@ enum { | |||
556 | 514 | ||
557 | #define QLCNIC_CAM_RAM_BASE (QLCNIC_CRB_CAM + 0x02000) | 515 | #define QLCNIC_CAM_RAM_BASE (QLCNIC_CRB_CAM + 0x02000) |
558 | #define QLCNIC_CAM_RAM(reg) (QLCNIC_CAM_RAM_BASE + (reg)) | 516 | #define QLCNIC_CAM_RAM(reg) (QLCNIC_CAM_RAM_BASE + (reg)) |
559 | #define QLCNIC_FW_VERSION_MAJOR (QLCNIC_CAM_RAM(0x150)) | ||
560 | #define QLCNIC_FW_VERSION_MINOR (QLCNIC_CAM_RAM(0x154)) | ||
561 | #define QLCNIC_FW_VERSION_SUB (QLCNIC_CAM_RAM(0x158)) | ||
562 | #define QLCNIC_ROM_LOCK_ID (QLCNIC_CAM_RAM(0x100)) | 517 | #define QLCNIC_ROM_LOCK_ID (QLCNIC_CAM_RAM(0x100)) |
563 | #define QLCNIC_PHY_LOCK_ID (QLCNIC_CAM_RAM(0x120)) | 518 | #define QLCNIC_PHY_LOCK_ID (QLCNIC_CAM_RAM(0x120)) |
564 | #define QLCNIC_CRB_WIN_LOCK_ID (QLCNIC_CAM_RAM(0x124)) | 519 | #define QLCNIC_CRB_WIN_LOCK_ID (QLCNIC_CAM_RAM(0x124)) |
@@ -568,28 +523,17 @@ enum { | |||
568 | #define QLCNIC_REG(X) (NIC_CRB_BASE+(X)) | 523 | #define QLCNIC_REG(X) (NIC_CRB_BASE+(X)) |
569 | #define QLCNIC_REG_2(X) (NIC_CRB_BASE_2+(X)) | 524 | #define QLCNIC_REG_2(X) (NIC_CRB_BASE_2+(X)) |
570 | 525 | ||
526 | #define QLCNIC_CDRP_MAX_ARGS 4 | ||
527 | #define QLCNIC_CDRP_ARG(i) (QLCNIC_REG(0x18 + ((i) * 4))) | ||
528 | |||
571 | #define QLCNIC_CDRP_CRB_OFFSET (QLCNIC_REG(0x18)) | 529 | #define QLCNIC_CDRP_CRB_OFFSET (QLCNIC_REG(0x18)) |
572 | #define QLCNIC_ARG1_CRB_OFFSET (QLCNIC_REG(0x1c)) | ||
573 | #define QLCNIC_ARG2_CRB_OFFSET (QLCNIC_REG(0x20)) | ||
574 | #define QLCNIC_ARG3_CRB_OFFSET (QLCNIC_REG(0x24)) | ||
575 | #define QLCNIC_SIGN_CRB_OFFSET (QLCNIC_REG(0x28)) | 530 | #define QLCNIC_SIGN_CRB_OFFSET (QLCNIC_REG(0x28)) |
576 | 531 | ||
577 | #define CRB_CMDPEG_STATE (QLCNIC_REG(0x50)) | ||
578 | #define CRB_RCVPEG_STATE (QLCNIC_REG(0x13c)) | ||
579 | |||
580 | #define CRB_XG_STATE_P3P (QLCNIC_REG(0x98)) | 532 | #define CRB_XG_STATE_P3P (QLCNIC_REG(0x98)) |
581 | #define CRB_PF_LINK_SPEED_1 (QLCNIC_REG(0xe8)) | 533 | #define CRB_PF_LINK_SPEED_1 (QLCNIC_REG(0xe8)) |
582 | #define CRB_PF_LINK_SPEED_2 (QLCNIC_REG(0xec)) | ||
583 | |||
584 | #define CRB_TEMP_STATE (QLCNIC_REG(0x1b4)) | ||
585 | |||
586 | #define CRB_V2P_0 (QLCNIC_REG(0x290)) | ||
587 | #define CRB_V2P(port) (CRB_V2P_0+((port)*4)) | ||
588 | #define CRB_DRIVER_VERSION (QLCNIC_REG(0x2a0)) | 534 | #define CRB_DRIVER_VERSION (QLCNIC_REG(0x2a0)) |
589 | 535 | ||
590 | #define CRB_FW_CAPABILITIES_1 (QLCNIC_CAM_RAM(0x128)) | ||
591 | #define CRB_FW_CAPABILITIES_2 (QLCNIC_CAM_RAM(0x12c)) | 536 | #define CRB_FW_CAPABILITIES_2 (QLCNIC_CAM_RAM(0x12c)) |
592 | #define CRB_MAC_BLOCK_START (QLCNIC_CAM_RAM(0x1c0)) | ||
593 | 537 | ||
594 | /* | 538 | /* |
595 | * CrbPortPhanCntrHi/Lo is used to pass the address of HostPhantomIndex address | 539 | * CrbPortPhanCntrHi/Lo is used to pass the address of HostPhantomIndex address |
@@ -616,11 +560,6 @@ enum { | |||
616 | /* Lock IDs for PHY lock */ | 560 | /* Lock IDs for PHY lock */ |
617 | #define PHY_LOCK_DRIVER 0x44524956 | 561 | #define PHY_LOCK_DRIVER 0x44524956 |
618 | 562 | ||
619 | /* Used for PS PCI Memory access */ | ||
620 | #define PCIX_PS_OP_ADDR_LO (0x10000) | ||
621 | /* via CRB (PS side only) */ | ||
622 | #define PCIX_PS_OP_ADDR_HI (0x10004) | ||
623 | |||
624 | #define PCIX_INT_VECTOR (0x10100) | 563 | #define PCIX_INT_VECTOR (0x10100) |
625 | #define PCIX_INT_MASK (0x10104) | 564 | #define PCIX_INT_MASK (0x10104) |
626 | 565 | ||
@@ -682,17 +621,6 @@ enum { | |||
682 | #define QLCNIC_PEG_TUNE_CAPABILITY (QLCNIC_CAM_RAM(0x02c)) | 621 | #define QLCNIC_PEG_TUNE_CAPABILITY (QLCNIC_CAM_RAM(0x02c)) |
683 | 622 | ||
684 | #define QLCNIC_DMA_WATCHDOG_CTRL (QLCNIC_CAM_RAM(0x14)) | 623 | #define QLCNIC_DMA_WATCHDOG_CTRL (QLCNIC_CAM_RAM(0x14)) |
685 | #define QLCNIC_PEG_ALIVE_COUNTER (QLCNIC_CAM_RAM(0xb0)) | ||
686 | #define QLCNIC_PEG_HALT_STATUS1 (QLCNIC_CAM_RAM(0xa8)) | ||
687 | #define QLCNIC_PEG_HALT_STATUS2 (QLCNIC_CAM_RAM(0xac)) | ||
688 | #define QLCNIC_CRB_DRV_ACTIVE (QLCNIC_CAM_RAM(0x138)) | ||
689 | #define QLCNIC_CRB_DEV_STATE (QLCNIC_CAM_RAM(0x140)) | ||
690 | |||
691 | #define QLCNIC_CRB_DRV_STATE (QLCNIC_CAM_RAM(0x144)) | ||
692 | #define QLCNIC_CRB_DRV_SCRATCH (QLCNIC_CAM_RAM(0x148)) | ||
693 | #define QLCNIC_CRB_DEV_PARTITION_INFO (QLCNIC_CAM_RAM(0x14c)) | ||
694 | #define QLCNIC_CRB_DRV_IDC_VER (QLCNIC_CAM_RAM(0x174)) | ||
695 | #define QLCNIC_CRB_DEV_NPAR_STATE (QLCNIC_CAM_RAM(0x19c)) | ||
696 | #define QLCNIC_ROM_DEV_INIT_TIMEOUT (0x3e885c) | 624 | #define QLCNIC_ROM_DEV_INIT_TIMEOUT (0x3e885c) |
697 | #define QLCNIC_ROM_DRV_RESET_TIMEOUT (0x3e8860) | 625 | #define QLCNIC_ROM_DRV_RESET_TIMEOUT (0x3e8860) |
698 | 626 | ||
@@ -711,7 +639,6 @@ enum { | |||
711 | #define QLCNIC_DEV_NPAR_OPER 1 /* NPAR Operational */ | 639 | #define QLCNIC_DEV_NPAR_OPER 1 /* NPAR Operational */ |
712 | #define QLCNIC_DEV_NPAR_OPER_TIMEO 30 /* Operational time out */ | 640 | #define QLCNIC_DEV_NPAR_OPER_TIMEO 30 /* Operational time out */ |
713 | 641 | ||
714 | #define QLC_DEV_CHECK_ACTIVE(VAL, FN) ((VAL) & (1 << (FN * 4))) | ||
715 | #define QLC_DEV_SET_REF_CNT(VAL, FN) ((VAL) |= (1 << (FN * 4))) | 642 | #define QLC_DEV_SET_REF_CNT(VAL, FN) ((VAL) |= (1 << (FN * 4))) |
716 | #define QLC_DEV_CLR_REF_CNT(VAL, FN) ((VAL) &= ~(1 << (FN * 4))) | 643 | #define QLC_DEV_CLR_REF_CNT(VAL, FN) ((VAL) &= ~(1 << (FN * 4))) |
717 | #define QLC_DEV_SET_RST_RDY(VAL, FN) ((VAL) |= (1 << (FN * 4))) | 644 | #define QLC_DEV_SET_RST_RDY(VAL, FN) ((VAL) |= (1 << (FN * 4))) |
@@ -744,6 +671,9 @@ enum { | |||
744 | #define QLCNIC_HEARTBEAT_PERIOD_MSECS 200 | 671 | #define QLCNIC_HEARTBEAT_PERIOD_MSECS 200 |
745 | #define QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT 45 | 672 | #define QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT 45 |
746 | 673 | ||
674 | #define QLCNIC_MAX_MC_COUNT 38 | ||
675 | #define QLCNIC_WATCHDOG_TIMEOUTVALUE 5 | ||
676 | |||
747 | #define ISR_MSI_INT_TRIGGER(FUNC) (QLCNIC_PCIX_PS_REG(PCIX_MSI_F(FUNC))) | 677 | #define ISR_MSI_INT_TRIGGER(FUNC) (QLCNIC_PCIX_PS_REG(PCIX_MSI_F(FUNC))) |
748 | #define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) | 678 | #define ISR_LEGACY_INT_TRIGGERED(VAL) (((VAL) & 0x300) == 0x200) |
749 | 679 | ||
@@ -766,26 +696,13 @@ struct qlcnic_legacy_intr_set { | |||
766 | u32 pci_int_reg; | 696 | u32 pci_int_reg; |
767 | }; | 697 | }; |
768 | 698 | ||
769 | #define QLCNIC_FW_API 0x1b216c | ||
770 | #define QLCNIC_DRV_OP_MODE 0x1b2170 | ||
771 | #define QLCNIC_MSIX_BASE 0x132110 | 699 | #define QLCNIC_MSIX_BASE 0x132110 |
772 | #define QLCNIC_MAX_PCI_FUNC 8 | 700 | #define QLCNIC_MAX_PCI_FUNC 8 |
773 | #define QLCNIC_MAX_VLAN_FILTERS 64 | 701 | #define QLCNIC_MAX_VLAN_FILTERS 64 |
774 | 702 | ||
775 | /* FW dump defines */ | ||
776 | #define MIU_TEST_CTR 0x41000090 | ||
777 | #define MIU_TEST_ADDR_LO 0x41000094 | ||
778 | #define MIU_TEST_ADDR_HI 0x41000098 | ||
779 | #define FLASH_ROM_WINDOW 0x42110030 | 703 | #define FLASH_ROM_WINDOW 0x42110030 |
780 | #define FLASH_ROM_DATA 0x42150000 | 704 | #define FLASH_ROM_DATA 0x42150000 |
781 | 705 | ||
782 | |||
783 | static const u32 FW_DUMP_LEVELS[] = { | ||
784 | 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff }; | ||
785 | |||
786 | static const u32 MIU_TEST_READ_DATA[] = { | ||
787 | 0x410000A8, 0x410000AC, 0x410000B8, 0x410000BC, }; | ||
788 | |||
789 | #define QLCNIC_FW_DUMP_REG1 0x00130060 | 706 | #define QLCNIC_FW_DUMP_REG1 0x00130060 |
790 | #define QLCNIC_FW_DUMP_REG2 0x001e0000 | 707 | #define QLCNIC_FW_DUMP_REG2 0x001e0000 |
791 | #define QLCNIC_FLASH_SEM2_LK 0x0013C010 | 708 | #define QLCNIC_FLASH_SEM2_LK 0x0013C010 |
@@ -796,7 +713,8 @@ static const u32 MIU_TEST_READ_DATA[] = { | |||
796 | enum { | 713 | enum { |
797 | QLCNIC_MGMT_FUNC = 0, | 714 | QLCNIC_MGMT_FUNC = 0, |
798 | QLCNIC_PRIV_FUNC = 1, | 715 | QLCNIC_PRIV_FUNC = 1, |
799 | QLCNIC_NON_PRIV_FUNC = 2 | 716 | QLCNIC_NON_PRIV_FUNC = 2, |
717 | QLCNIC_UNKNOWN_FUNC_MODE = 3 | ||
800 | }; | 718 | }; |
801 | 719 | ||
802 | enum { | 720 | enum { |
@@ -1013,6 +931,8 @@ enum { | |||
1013 | #define QLCNIC_NIU_PROMISC_MODE 1 | 931 | #define QLCNIC_NIU_PROMISC_MODE 1 |
1014 | #define QLCNIC_NIU_ALLMULTI_MODE 2 | 932 | #define QLCNIC_NIU_ALLMULTI_MODE 2 |
1015 | 933 | ||
934 | #define QLCNIC_PCIE_SEM_TIMEOUT 10000 | ||
935 | |||
1016 | struct crb_128M_2M_sub_block_map { | 936 | struct crb_128M_2M_sub_block_map { |
1017 | unsigned valid; | 937 | unsigned valid; |
1018 | unsigned start_128M; | 938 | unsigned start_128M; |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c index 7a6d5ebe4e0f..f89cc7a3fe6c 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * QLogic qlcnic NIC Driver | 2 | * QLogic qlcnic NIC Driver |
3 | * Copyright (c) 2009-2010 QLogic Corporation | 3 | * Copyright (c) 2009-2013 QLogic Corporation |
4 | * | 4 | * |
5 | * See LICENSE.qlcnic for copyright and licensing details. | 5 | * See LICENSE.qlcnic for copyright and licensing details. |
6 | */ | 6 | */ |
@@ -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 |
@@ -417,9 +422,8 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter, | |||
417 | return 0; | 422 | return 0; |
418 | } | 423 | } |
419 | 424 | ||
420 | static int | 425 | int qlcnic_82xx_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, |
421 | qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, | 426 | __le16 vlan_id, u8 op) |
422 | __le16 vlan_id, unsigned op) | ||
423 | { | 427 | { |
424 | struct qlcnic_nic_req req; | 428 | struct qlcnic_nic_req req; |
425 | struct qlcnic_mac_req *mac_req; | 429 | struct qlcnic_mac_req *mac_req; |
@@ -442,7 +446,29 @@ qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, | |||
442 | return qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); | 446 | return qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); |
443 | } | 447 | } |
444 | 448 | ||
445 | static int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr) | 449 | int qlcnic_nic_del_mac(struct qlcnic_adapter *adapter, const u8 *addr) |
450 | { | ||
451 | struct list_head *head; | ||
452 | struct qlcnic_mac_list_s *cur; | ||
453 | int err = -EINVAL; | ||
454 | |||
455 | /* Delete MAC from the existing list */ | ||
456 | list_for_each(head, &adapter->mac_list) { | ||
457 | cur = list_entry(head, struct qlcnic_mac_list_s, list); | ||
458 | if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) { | ||
459 | err = qlcnic_sre_macaddr_change(adapter, cur->mac_addr, | ||
460 | 0, QLCNIC_MAC_DEL); | ||
461 | if (err) | ||
462 | return err; | ||
463 | list_del(&cur->list); | ||
464 | kfree(cur); | ||
465 | return err; | ||
466 | } | ||
467 | } | ||
468 | return err; | ||
469 | } | ||
470 | |||
471 | int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr) | ||
446 | { | 472 | { |
447 | struct list_head *head; | 473 | struct list_head *head; |
448 | struct qlcnic_mac_list_s *cur; | 474 | struct qlcnic_mac_list_s *cur; |
@@ -455,11 +481,9 @@ static int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, const u8 *addr) | |||
455 | } | 481 | } |
456 | 482 | ||
457 | cur = kzalloc(sizeof(struct qlcnic_mac_list_s), GFP_ATOMIC); | 483 | cur = kzalloc(sizeof(struct qlcnic_mac_list_s), GFP_ATOMIC); |
458 | if (cur == NULL) { | 484 | if (cur == NULL) |
459 | dev_err(&adapter->netdev->dev, | ||
460 | "failed to add mac address filter\n"); | ||
461 | return -ENOMEM; | 485 | return -ENOMEM; |
462 | } | 486 | |
463 | memcpy(cur->mac_addr, addr, ETH_ALEN); | 487 | memcpy(cur->mac_addr, addr, ETH_ALEN); |
464 | 488 | ||
465 | if (qlcnic_sre_macaddr_change(adapter, | 489 | if (qlcnic_sre_macaddr_change(adapter, |
@@ -506,17 +530,17 @@ void qlcnic_set_multi(struct net_device *netdev) | |||
506 | } | 530 | } |
507 | 531 | ||
508 | send_fw_cmd: | 532 | send_fw_cmd: |
509 | if (mode == VPORT_MISS_MODE_ACCEPT_ALL) { | 533 | if (mode == VPORT_MISS_MODE_ACCEPT_ALL && !adapter->fdb_mac_learn) { |
510 | qlcnic_alloc_lb_filters_mem(adapter); | 534 | qlcnic_alloc_lb_filters_mem(adapter); |
511 | adapter->mac_learn = 1; | 535 | adapter->drv_mac_learn = true; |
512 | } else { | 536 | } else { |
513 | adapter->mac_learn = 0; | 537 | adapter->drv_mac_learn = false; |
514 | } | 538 | } |
515 | 539 | ||
516 | qlcnic_nic_set_promisc(adapter, mode); | 540 | qlcnic_nic_set_promisc(adapter, mode); |
517 | } | 541 | } |
518 | 542 | ||
519 | int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) | 543 | int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) |
520 | { | 544 | { |
521 | struct qlcnic_nic_req req; | 545 | struct qlcnic_nic_req req; |
522 | u64 word; | 546 | u64 word; |
@@ -552,21 +576,23 @@ void qlcnic_free_mac_list(struct qlcnic_adapter *adapter) | |||
552 | void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter) | 576 | void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter) |
553 | { | 577 | { |
554 | struct qlcnic_filter *tmp_fil; | 578 | struct qlcnic_filter *tmp_fil; |
555 | struct hlist_node *tmp_hnode, *n; | 579 | struct hlist_node *n; |
556 | struct hlist_head *head; | 580 | struct hlist_head *head; |
557 | int i; | 581 | int i; |
582 | unsigned long time; | ||
583 | u8 cmd; | ||
558 | 584 | ||
559 | for (i = 0; i < adapter->fhash.fmax; i++) { | 585 | for (i = 0; i < adapter->fhash.fbucket_size; i++) { |
560 | head = &(adapter->fhash.fhead[i]); | 586 | head = &(adapter->fhash.fhead[i]); |
561 | 587 | hlist_for_each_entry_safe(tmp_fil, n, head, fnode) { | |
562 | hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) | 588 | cmd = tmp_fil->vlan_id ? QLCNIC_MAC_VLAN_DEL : |
563 | { | 589 | QLCNIC_MAC_DEL; |
564 | if (jiffies > | 590 | time = tmp_fil->ftime; |
565 | (QLCNIC_FILTER_AGE * HZ + tmp_fil->ftime)) { | 591 | if (jiffies > (QLCNIC_FILTER_AGE * HZ + time)) { |
566 | qlcnic_sre_macaddr_change(adapter, | 592 | qlcnic_sre_macaddr_change(adapter, |
567 | tmp_fil->faddr, tmp_fil->vlan_id, | 593 | tmp_fil->faddr, |
568 | tmp_fil->vlan_id ? QLCNIC_MAC_VLAN_DEL : | 594 | tmp_fil->vlan_id, |
569 | QLCNIC_MAC_DEL); | 595 | cmd); |
570 | spin_lock_bh(&adapter->mac_learn_lock); | 596 | spin_lock_bh(&adapter->mac_learn_lock); |
571 | adapter->fhash.fnum--; | 597 | adapter->fhash.fnum--; |
572 | hlist_del(&tmp_fil->fnode); | 598 | hlist_del(&tmp_fil->fnode); |
@@ -575,22 +601,40 @@ void qlcnic_prune_lb_filters(struct qlcnic_adapter *adapter) | |||
575 | } | 601 | } |
576 | } | 602 | } |
577 | } | 603 | } |
604 | for (i = 0; i < adapter->rx_fhash.fbucket_size; i++) { | ||
605 | head = &(adapter->rx_fhash.fhead[i]); | ||
606 | |||
607 | hlist_for_each_entry_safe(tmp_fil, n, head, fnode) | ||
608 | { | ||
609 | time = tmp_fil->ftime; | ||
610 | if (jiffies > (QLCNIC_FILTER_AGE * HZ + time)) { | ||
611 | spin_lock_bh(&adapter->rx_mac_learn_lock); | ||
612 | adapter->rx_fhash.fnum--; | ||
613 | hlist_del(&tmp_fil->fnode); | ||
614 | spin_unlock_bh(&adapter->rx_mac_learn_lock); | ||
615 | kfree(tmp_fil); | ||
616 | } | ||
617 | } | ||
618 | } | ||
578 | } | 619 | } |
579 | 620 | ||
580 | void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter) | 621 | void qlcnic_delete_lb_filters(struct qlcnic_adapter *adapter) |
581 | { | 622 | { |
582 | struct qlcnic_filter *tmp_fil; | 623 | struct qlcnic_filter *tmp_fil; |
583 | struct hlist_node *tmp_hnode, *n; | 624 | struct hlist_node *n; |
584 | struct hlist_head *head; | 625 | struct hlist_head *head; |
585 | int i; | 626 | int i; |
627 | u8 cmd; | ||
586 | 628 | ||
587 | for (i = 0; i < adapter->fhash.fmax; i++) { | 629 | for (i = 0; i < adapter->fhash.fbucket_size; i++) { |
588 | head = &(adapter->fhash.fhead[i]); | 630 | head = &(adapter->fhash.fhead[i]); |
589 | 631 | hlist_for_each_entry_safe(tmp_fil, n, head, fnode) { | |
590 | hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) { | 632 | cmd = tmp_fil->vlan_id ? QLCNIC_MAC_VLAN_DEL : |
591 | qlcnic_sre_macaddr_change(adapter, tmp_fil->faddr, | 633 | QLCNIC_MAC_DEL; |
592 | tmp_fil->vlan_id, tmp_fil->vlan_id ? | 634 | qlcnic_sre_macaddr_change(adapter, |
593 | QLCNIC_MAC_VLAN_DEL : QLCNIC_MAC_DEL); | 635 | tmp_fil->faddr, |
636 | tmp_fil->vlan_id, | ||
637 | cmd); | ||
594 | spin_lock_bh(&adapter->mac_learn_lock); | 638 | spin_lock_bh(&adapter->mac_learn_lock); |
595 | adapter->fhash.fnum--; | 639 | adapter->fhash.fnum--; |
596 | hlist_del(&tmp_fil->fnode); | 640 | hlist_del(&tmp_fil->fnode); |
@@ -620,12 +664,13 @@ static int qlcnic_set_fw_loopback(struct qlcnic_adapter *adapter, u8 flag) | |||
620 | return rv; | 664 | return rv; |
621 | } | 665 | } |
622 | 666 | ||
623 | int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode) | 667 | int qlcnic_82xx_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode) |
624 | { | 668 | { |
625 | if (qlcnic_set_fw_loopback(adapter, mode)) | 669 | if (qlcnic_set_fw_loopback(adapter, mode)) |
626 | return -EIO; | 670 | return -EIO; |
627 | 671 | ||
628 | if (qlcnic_nic_set_promisc(adapter, VPORT_MISS_MODE_ACCEPT_ALL)) { | 672 | if (qlcnic_nic_set_promisc(adapter, |
673 | VPORT_MISS_MODE_ACCEPT_ALL)) { | ||
629 | qlcnic_set_fw_loopback(adapter, 0); | 674 | qlcnic_set_fw_loopback(adapter, 0); |
630 | return -EIO; | 675 | return -EIO; |
631 | } | 676 | } |
@@ -634,11 +679,11 @@ int qlcnic_set_lb_mode(struct qlcnic_adapter *adapter, u8 mode) | |||
634 | return 0; | 679 | return 0; |
635 | } | 680 | } |
636 | 681 | ||
637 | void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter) | 682 | int qlcnic_82xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8 mode) |
638 | { | 683 | { |
639 | int mode = VPORT_MISS_MODE_DROP; | ||
640 | struct net_device *netdev = adapter->netdev; | 684 | struct net_device *netdev = adapter->netdev; |
641 | 685 | ||
686 | mode = VPORT_MISS_MODE_DROP; | ||
642 | qlcnic_set_fw_loopback(adapter, 0); | 687 | qlcnic_set_fw_loopback(adapter, 0); |
643 | 688 | ||
644 | if (netdev->flags & IFF_PROMISC) | 689 | if (netdev->flags & IFF_PROMISC) |
@@ -648,12 +693,13 @@ void qlcnic_clear_lb_mode(struct qlcnic_adapter *adapter) | |||
648 | 693 | ||
649 | qlcnic_nic_set_promisc(adapter, mode); | 694 | qlcnic_nic_set_promisc(adapter, mode); |
650 | msleep(1000); | 695 | msleep(1000); |
696 | return 0; | ||
651 | } | 697 | } |
652 | 698 | ||
653 | /* | 699 | /* |
654 | * Send the interrupt coalescing parameter set by ethtool to the card. | 700 | * Send the interrupt coalescing parameter set by ethtool to the card. |
655 | */ | 701 | */ |
656 | int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter) | 702 | void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter) |
657 | { | 703 | { |
658 | struct qlcnic_nic_req req; | 704 | struct qlcnic_nic_req req; |
659 | int rv; | 705 | int rv; |
@@ -675,10 +721,14 @@ int qlcnic_config_intr_coalesce(struct qlcnic_adapter *adapter) | |||
675 | if (rv != 0) | 721 | if (rv != 0) |
676 | dev_err(&adapter->netdev->dev, | 722 | dev_err(&adapter->netdev->dev, |
677 | "Could not send interrupt coalescing parameters\n"); | 723 | "Could not send interrupt coalescing parameters\n"); |
678 | return rv; | ||
679 | } | 724 | } |
680 | 725 | ||
681 | int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable) | 726 | #define QLCNIC_ENABLE_IPV4_LRO 1 |
727 | #define QLCNIC_ENABLE_IPV6_LRO 2 | ||
728 | #define QLCNIC_NO_DEST_IPV4_CHECK (1 << 8) | ||
729 | #define QLCNIC_NO_DEST_IPV6_CHECK (2 << 8) | ||
730 | |||
731 | int qlcnic_82xx_config_hw_lro(struct qlcnic_adapter *adapter, int enable) | ||
682 | { | 732 | { |
683 | struct qlcnic_nic_req req; | 733 | struct qlcnic_nic_req req; |
684 | u64 word; | 734 | u64 word; |
@@ -694,7 +744,15 @@ int qlcnic_config_hw_lro(struct qlcnic_adapter *adapter, int enable) | |||
694 | word = QLCNIC_H2C_OPCODE_CONFIG_HW_LRO | ((u64)adapter->portnum << 16); | 744 | word = QLCNIC_H2C_OPCODE_CONFIG_HW_LRO | ((u64)adapter->portnum << 16); |
695 | req.req_hdr = cpu_to_le64(word); | 745 | req.req_hdr = cpu_to_le64(word); |
696 | 746 | ||
697 | req.words[0] = cpu_to_le64(enable); | 747 | word = 0; |
748 | if (enable) { | ||
749 | word = QLCNIC_ENABLE_IPV4_LRO | QLCNIC_NO_DEST_IPV4_CHECK; | ||
750 | if (adapter->ahw->capabilities2 & QLCNIC_FW_CAP2_HW_LRO_IPV6) | ||
751 | word |= QLCNIC_ENABLE_IPV6_LRO | | ||
752 | QLCNIC_NO_DEST_IPV6_CHECK; | ||
753 | } | ||
754 | |||
755 | req.words[0] = cpu_to_le64(word); | ||
698 | 756 | ||
699 | rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); | 757 | rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); |
700 | if (rv != 0) | 758 | if (rv != 0) |
@@ -734,9 +792,12 @@ int qlcnic_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable) | |||
734 | } | 792 | } |
735 | 793 | ||
736 | 794 | ||
737 | #define RSS_HASHTYPE_IP_TCP 0x3 | 795 | #define QLCNIC_RSS_HASHTYPE_IP_TCP 0x3 |
796 | #define QLCNIC_ENABLE_TYPE_C_RSS BIT_10 | ||
797 | #define QLCNIC_RSS_FEATURE_FLAG (1ULL << 63) | ||
798 | #define QLCNIC_RSS_IND_TABLE_MASK 0x7ULL | ||
738 | 799 | ||
739 | int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable) | 800 | int qlcnic_82xx_config_rss(struct qlcnic_adapter *adapter, int enable) |
740 | { | 801 | { |
741 | struct qlcnic_nic_req req; | 802 | struct qlcnic_nic_req req; |
742 | u64 word; | 803 | u64 word; |
@@ -761,13 +822,19 @@ int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable) | |||
761 | * 7-6: hash_type_ipv6 | 822 | * 7-6: hash_type_ipv6 |
762 | * 8: enable | 823 | * 8: enable |
763 | * 9: use indirection table | 824 | * 9: use indirection table |
764 | * 47-10: reserved | 825 | * 10: type-c rss |
765 | * 63-48: indirection table mask | 826 | * 11: udp rss |
827 | * 47-12: reserved | ||
828 | * 62-48: indirection table mask | ||
829 | * 63: feature flag | ||
766 | */ | 830 | */ |
767 | word = ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 4) | | 831 | word = ((u64)(QLCNIC_RSS_HASHTYPE_IP_TCP & 0x3) << 4) | |
768 | ((u64)(RSS_HASHTYPE_IP_TCP & 0x3) << 6) | | 832 | ((u64)(QLCNIC_RSS_HASHTYPE_IP_TCP & 0x3) << 6) | |
769 | ((u64)(enable & 0x1) << 8) | | 833 | ((u64)(enable & 0x1) << 8) | |
770 | ((0x7ULL) << 48); | 834 | ((u64)QLCNIC_RSS_IND_TABLE_MASK << 48) | |
835 | (u64)QLCNIC_ENABLE_TYPE_C_RSS | | ||
836 | (u64)QLCNIC_RSS_FEATURE_FLAG; | ||
837 | |||
771 | req.words[0] = cpu_to_le64(word); | 838 | req.words[0] = cpu_to_le64(word); |
772 | for (i = 0; i < 5; i++) | 839 | for (i = 0; i < 5; i++) |
773 | req.words[i+1] = cpu_to_le64(key[i]); | 840 | req.words[i+1] = cpu_to_le64(key[i]); |
@@ -779,7 +846,8 @@ int qlcnic_config_rss(struct qlcnic_adapter *adapter, int enable) | |||
779 | return rv; | 846 | return rv; |
780 | } | 847 | } |
781 | 848 | ||
782 | int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd) | 849 | void qlcnic_82xx_config_ipaddr(struct qlcnic_adapter *adapter, |
850 | __be32 ip, int cmd) | ||
783 | { | 851 | { |
784 | struct qlcnic_nic_req req; | 852 | struct qlcnic_nic_req req; |
785 | struct qlcnic_ipaddr *ipa; | 853 | struct qlcnic_ipaddr *ipa; |
@@ -801,23 +869,19 @@ int qlcnic_config_ipaddr(struct qlcnic_adapter *adapter, __be32 ip, int cmd) | |||
801 | dev_err(&adapter->netdev->dev, | 869 | dev_err(&adapter->netdev->dev, |
802 | "could not notify %s IP 0x%x reuqest\n", | 870 | "could not notify %s IP 0x%x reuqest\n", |
803 | (cmd == QLCNIC_IP_UP) ? "Add" : "Remove", ip); | 871 | (cmd == QLCNIC_IP_UP) ? "Add" : "Remove", ip); |
804 | |||
805 | return rv; | ||
806 | } | 872 | } |
807 | 873 | ||
808 | int qlcnic_linkevent_request(struct qlcnic_adapter *adapter, int enable) | 874 | int qlcnic_82xx_linkevent_request(struct qlcnic_adapter *adapter, int enable) |
809 | { | 875 | { |
810 | struct qlcnic_nic_req req; | 876 | struct qlcnic_nic_req req; |
811 | u64 word; | 877 | u64 word; |
812 | int rv; | 878 | int rv; |
813 | |||
814 | memset(&req, 0, sizeof(struct qlcnic_nic_req)); | 879 | memset(&req, 0, sizeof(struct qlcnic_nic_req)); |
815 | req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23); | 880 | req.qhdr = cpu_to_le64(QLCNIC_HOST_REQUEST << 23); |
816 | 881 | ||
817 | word = QLCNIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16); | 882 | word = QLCNIC_H2C_OPCODE_GET_LINKEVENT | ((u64)adapter->portnum << 16); |
818 | req.req_hdr = cpu_to_le64(word); | 883 | req.req_hdr = cpu_to_le64(word); |
819 | req.words[0] = cpu_to_le64(enable | (enable << 8)); | 884 | req.words[0] = cpu_to_le64(enable | (enable << 8)); |
820 | |||
821 | rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); | 885 | rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); |
822 | if (rv != 0) | 886 | if (rv != 0) |
823 | dev_err(&adapter->netdev->dev, | 887 | dev_err(&adapter->netdev->dev, |
@@ -882,7 +946,8 @@ netdev_features_t qlcnic_fix_features(struct net_device *netdev, | |||
882 | { | 946 | { |
883 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 947 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
884 | 948 | ||
885 | if ((adapter->flags & QLCNIC_ESWITCH_ENABLED)) { | 949 | if ((adapter->flags & QLCNIC_ESWITCH_ENABLED) && |
950 | qlcnic_82xx_check(adapter)) { | ||
886 | netdev_features_t changed = features ^ netdev->features; | 951 | netdev_features_t changed = features ^ netdev->features; |
887 | features ^= changed & (NETIF_F_ALL_CSUM | NETIF_F_RXCSUM); | 952 | features ^= changed & (NETIF_F_ALL_CSUM | NETIF_F_RXCSUM); |
888 | } | 953 | } |
@@ -903,13 +968,15 @@ int qlcnic_set_features(struct net_device *netdev, netdev_features_t features) | |||
903 | if (!(changed & NETIF_F_LRO)) | 968 | if (!(changed & NETIF_F_LRO)) |
904 | return 0; | 969 | return 0; |
905 | 970 | ||
906 | netdev->features = features ^ NETIF_F_LRO; | 971 | netdev->features ^= NETIF_F_LRO; |
907 | 972 | ||
908 | if (qlcnic_config_hw_lro(adapter, hw_lro)) | 973 | if (qlcnic_config_hw_lro(adapter, hw_lro)) |
909 | return -EIO; | 974 | return -EIO; |
910 | 975 | ||
911 | if ((hw_lro == 0) && qlcnic_send_lro_cleanup(adapter)) | 976 | if (!hw_lro && qlcnic_82xx_check(adapter)) { |
912 | return -EIO; | 977 | if (qlcnic_send_lro_cleanup(adapter)) |
978 | return -EIO; | ||
979 | } | ||
913 | 980 | ||
914 | return 0; | 981 | return 0; |
915 | } | 982 | } |
@@ -981,8 +1048,8 @@ qlcnic_pci_set_crbwindow_2M(struct qlcnic_adapter *adapter, ulong off) | |||
981 | return 0; | 1048 | return 0; |
982 | } | 1049 | } |
983 | 1050 | ||
984 | int | 1051 | int qlcnic_82xx_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, |
985 | qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data) | 1052 | u32 data) |
986 | { | 1053 | { |
987 | unsigned long flags; | 1054 | unsigned long flags; |
988 | int rv; | 1055 | int rv; |
@@ -1013,7 +1080,7 @@ qlcnic_hw_write_wx_2M(struct qlcnic_adapter *adapter, ulong off, u32 data) | |||
1013 | return -EIO; | 1080 | return -EIO; |
1014 | } | 1081 | } |
1015 | 1082 | ||
1016 | int qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off) | 1083 | int qlcnic_82xx_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off) |
1017 | { | 1084 | { |
1018 | unsigned long flags; | 1085 | unsigned long flags; |
1019 | int rv; | 1086 | int rv; |
@@ -1042,7 +1109,6 @@ int qlcnic_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong off) | |||
1042 | return -1; | 1109 | return -1; |
1043 | } | 1110 | } |
1044 | 1111 | ||
1045 | |||
1046 | void __iomem *qlcnic_get_ioaddr(struct qlcnic_hardware_context *ahw, | 1112 | void __iomem *qlcnic_get_ioaddr(struct qlcnic_hardware_context *ahw, |
1047 | u32 offset) | 1113 | u32 offset) |
1048 | { | 1114 | { |
@@ -1268,7 +1334,7 @@ int qlcnic_pci_mem_read_2M(struct qlcnic_adapter *adapter, u64 off, u64 *data) | |||
1268 | return ret; | 1334 | return ret; |
1269 | } | 1335 | } |
1270 | 1336 | ||
1271 | int qlcnic_get_board_info(struct qlcnic_adapter *adapter) | 1337 | int qlcnic_82xx_get_board_info(struct qlcnic_adapter *adapter) |
1272 | { | 1338 | { |
1273 | int offset, board_type, magic; | 1339 | int offset, board_type, magic; |
1274 | struct pci_dev *pdev = adapter->pdev; | 1340 | struct pci_dev *pdev = adapter->pdev; |
@@ -1341,7 +1407,7 @@ qlcnic_wol_supported(struct qlcnic_adapter *adapter) | |||
1341 | return 0; | 1407 | return 0; |
1342 | } | 1408 | } |
1343 | 1409 | ||
1344 | int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) | 1410 | int qlcnic_82xx_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) |
1345 | { | 1411 | { |
1346 | struct qlcnic_nic_req req; | 1412 | struct qlcnic_nic_req req; |
1347 | int rv; | 1413 | int rv; |
@@ -1353,7 +1419,7 @@ int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) | |||
1353 | word = QLCNIC_H2C_OPCODE_CONFIG_LED | ((u64)adapter->portnum << 16); | 1419 | word = QLCNIC_H2C_OPCODE_CONFIG_LED | ((u64)adapter->portnum << 16); |
1354 | req.req_hdr = cpu_to_le64(word); | 1420 | req.req_hdr = cpu_to_le64(word); |
1355 | 1421 | ||
1356 | req.words[0] = cpu_to_le64((u64)rate << 32); | 1422 | req.words[0] = cpu_to_le64(((u64)rate << 32) | adapter->portnum); |
1357 | req.words[1] = cpu_to_le64(state); | 1423 | req.words[1] = cpu_to_le64(state); |
1358 | 1424 | ||
1359 | rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); | 1425 | rv = qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); |
@@ -1362,3 +1428,56 @@ int qlcnic_config_led(struct qlcnic_adapter *adapter, u32 state, u32 rate) | |||
1362 | 1428 | ||
1363 | return rv; | 1429 | return rv; |
1364 | } | 1430 | } |
1431 | |||
1432 | void qlcnic_82xx_get_func_no(struct qlcnic_adapter *adapter) | ||
1433 | { | ||
1434 | void __iomem *msix_base_addr; | ||
1435 | u32 func; | ||
1436 | u32 msix_base; | ||
1437 | |||
1438 | pci_read_config_dword(adapter->pdev, QLCNIC_MSIX_TABLE_OFFSET, &func); | ||
1439 | msix_base_addr = adapter->ahw->pci_base0 + QLCNIC_MSIX_BASE; | ||
1440 | msix_base = readl(msix_base_addr); | ||
1441 | func = (func - msix_base) / QLCNIC_MSIX_TBL_PGSIZE; | ||
1442 | adapter->ahw->pci_func = func; | ||
1443 | } | ||
1444 | |||
1445 | void qlcnic_82xx_read_crb(struct qlcnic_adapter *adapter, char *buf, | ||
1446 | loff_t offset, size_t size) | ||
1447 | { | ||
1448 | u32 data; | ||
1449 | u64 qmdata; | ||
1450 | |||
1451 | if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) { | ||
1452 | qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata); | ||
1453 | memcpy(buf, &qmdata, size); | ||
1454 | } else { | ||
1455 | data = QLCRD32(adapter, offset); | ||
1456 | memcpy(buf, &data, size); | ||
1457 | } | ||
1458 | } | ||
1459 | |||
1460 | void qlcnic_82xx_write_crb(struct qlcnic_adapter *adapter, char *buf, | ||
1461 | loff_t offset, size_t size) | ||
1462 | { | ||
1463 | u32 data; | ||
1464 | u64 qmdata; | ||
1465 | |||
1466 | if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) { | ||
1467 | memcpy(&qmdata, buf, size); | ||
1468 | qlcnic_pci_camqm_write_2M(adapter, offset, qmdata); | ||
1469 | } else { | ||
1470 | memcpy(&data, buf, size); | ||
1471 | QLCWR32(adapter, offset, data); | ||
1472 | } | ||
1473 | } | ||
1474 | |||
1475 | int qlcnic_82xx_api_lock(struct qlcnic_adapter *adapter) | ||
1476 | { | ||
1477 | return qlcnic_pcie_sem_lock(adapter, 5, 0); | ||
1478 | } | ||
1479 | |||
1480 | void qlcnic_82xx_api_unlock(struct qlcnic_adapter *adapter) | ||
1481 | { | ||
1482 | qlcnic_pcie_sem_unlock(adapter, 5); | ||
1483 | } | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h new file mode 100644 index 000000000000..5b8749eda11f --- /dev/null +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_hw.h | |||
@@ -0,0 +1,194 @@ | |||
1 | /* | ||
2 | * QLogic qlcnic NIC Driver | ||
3 | * Copyright (c) 2009-2013 QLogic Corporation | ||
4 | * | ||
5 | * See LICENSE.qlcnic for copyright and licensing details. | ||
6 | */ | ||
7 | |||
8 | #ifndef __QLCNIC_HW_H | ||
9 | #define __QLCNIC_HW_H | ||
10 | |||
11 | /* Common registers in 83xx and 82xx */ | ||
12 | enum qlcnic_regs { | ||
13 | QLCNIC_PEG_HALT_STATUS1 = 0, | ||
14 | QLCNIC_PEG_HALT_STATUS2, | ||
15 | QLCNIC_PEG_ALIVE_COUNTER, | ||
16 | QLCNIC_FLASH_LOCK_OWNER, | ||
17 | QLCNIC_FW_CAPABILITIES, | ||
18 | QLCNIC_CRB_DRV_ACTIVE, | ||
19 | QLCNIC_CRB_DEV_STATE, | ||
20 | QLCNIC_CRB_DRV_STATE, | ||
21 | QLCNIC_CRB_DRV_SCRATCH, | ||
22 | QLCNIC_CRB_DEV_PARTITION_INFO, | ||
23 | QLCNIC_CRB_DRV_IDC_VER, | ||
24 | QLCNIC_FW_VERSION_MAJOR, | ||
25 | QLCNIC_FW_VERSION_MINOR, | ||
26 | QLCNIC_FW_VERSION_SUB, | ||
27 | QLCNIC_CRB_DEV_NPAR_STATE, | ||
28 | QLCNIC_FW_IMG_VALID, | ||
29 | QLCNIC_CMDPEG_STATE, | ||
30 | QLCNIC_RCVPEG_STATE, | ||
31 | QLCNIC_ASIC_TEMP, | ||
32 | QLCNIC_FW_API, | ||
33 | QLCNIC_DRV_OP_MODE, | ||
34 | QLCNIC_FLASH_LOCK, | ||
35 | QLCNIC_FLASH_UNLOCK, | ||
36 | }; | ||
37 | |||
38 | /* Read from an address offset from BAR0, existing registers */ | ||
39 | #define QLC_SHARED_REG_RD32(a, addr) \ | ||
40 | readl(((a)->ahw->pci_base0) + ((a)->ahw->reg_tbl[addr])) | ||
41 | |||
42 | /* Write to an address offset from BAR0, existing registers */ | ||
43 | #define QLC_SHARED_REG_WR32(a, addr, value) \ | ||
44 | writel(value, ((a)->ahw->pci_base0) + ((a)->ahw->reg_tbl[addr])) | ||
45 | |||
46 | /* Read from a direct address offset from BAR0, additional registers */ | ||
47 | #define QLCRDX(ahw, addr) \ | ||
48 | readl(((ahw)->pci_base0) + ((ahw)->ext_reg_tbl[addr])) | ||
49 | |||
50 | /* Write to a direct address offset from BAR0, additional registers */ | ||
51 | #define QLCWRX(ahw, addr, value) \ | ||
52 | writel(value, (((ahw)->pci_base0) + ((ahw)->ext_reg_tbl[addr]))) | ||
53 | |||
54 | #define QLCNIC_CMD_CONFIGURE_IP_ADDR 0x1 | ||
55 | #define QLCNIC_CMD_CONFIG_INTRPT 0x2 | ||
56 | #define QLCNIC_CMD_CREATE_RX_CTX 0x7 | ||
57 | #define QLCNIC_CMD_DESTROY_RX_CTX 0x8 | ||
58 | #define QLCNIC_CMD_CREATE_TX_CTX 0x9 | ||
59 | #define QLCNIC_CMD_DESTROY_TX_CTX 0xa | ||
60 | #define QLCNIC_CMD_CONFIGURE_LRO 0xC | ||
61 | #define QLCNIC_CMD_CONFIGURE_MAC_LEARNING 0xD | ||
62 | #define QLCNIC_CMD_GET_STATISTICS 0xF | ||
63 | #define QLCNIC_CMD_INTRPT_TEST 0x11 | ||
64 | #define QLCNIC_CMD_SET_MTU 0x12 | ||
65 | #define QLCNIC_CMD_READ_PHY 0x13 | ||
66 | #define QLCNIC_CMD_WRITE_PHY 0x14 | ||
67 | #define QLCNIC_CMD_READ_HW_REG 0x15 | ||
68 | #define QLCNIC_CMD_GET_FLOW_CTL 0x16 | ||
69 | #define QLCNIC_CMD_SET_FLOW_CTL 0x17 | ||
70 | #define QLCNIC_CMD_READ_MAX_MTU 0x18 | ||
71 | #define QLCNIC_CMD_READ_MAX_LRO 0x19 | ||
72 | #define QLCNIC_CMD_MAC_ADDRESS 0x1f | ||
73 | #define QLCNIC_CMD_GET_PCI_INFO 0x20 | ||
74 | #define QLCNIC_CMD_GET_NIC_INFO 0x21 | ||
75 | #define QLCNIC_CMD_SET_NIC_INFO 0x22 | ||
76 | #define QLCNIC_CMD_GET_ESWITCH_CAPABILITY 0x24 | ||
77 | #define QLCNIC_CMD_TOGGLE_ESWITCH 0x25 | ||
78 | #define QLCNIC_CMD_GET_ESWITCH_STATUS 0x26 | ||
79 | #define QLCNIC_CMD_SET_PORTMIRRORING 0x27 | ||
80 | #define QLCNIC_CMD_CONFIGURE_ESWITCH 0x28 | ||
81 | #define QLCNIC_CMD_GET_ESWITCH_PORT_CONFIG 0x29 | ||
82 | #define QLCNIC_CMD_GET_ESWITCH_STATS 0x2a | ||
83 | #define QLCNIC_CMD_CONFIG_PORT 0x2e | ||
84 | #define QLCNIC_CMD_TEMP_SIZE 0x2f | ||
85 | #define QLCNIC_CMD_GET_TEMP_HDR 0x30 | ||
86 | #define QLCNIC_CMD_GET_MAC_STATS 0x37 | ||
87 | #define QLCNIC_CMD_SET_DRV_VER 0x38 | ||
88 | #define QLCNIC_CMD_CONFIGURE_RSS 0x41 | ||
89 | #define QLCNIC_CMD_CONFIG_INTR_COAL 0x43 | ||
90 | #define QLCNIC_CMD_CONFIGURE_LED 0x44 | ||
91 | #define QLCNIC_CMD_CONFIG_MAC_VLAN 0x45 | ||
92 | #define QLCNIC_CMD_GET_LINK_EVENT 0x48 | ||
93 | #define QLCNIC_CMD_CONFIGURE_MAC_RX_MODE 0x49 | ||
94 | #define QLCNIC_CMD_CONFIGURE_HW_LRO 0x4A | ||
95 | #define QLCNIC_CMD_INIT_NIC_FUNC 0x60 | ||
96 | #define QLCNIC_CMD_STOP_NIC_FUNC 0x61 | ||
97 | #define QLCNIC_CMD_IDC_ACK 0x63 | ||
98 | #define QLCNIC_CMD_SET_PORT_CONFIG 0x66 | ||
99 | #define QLCNIC_CMD_GET_PORT_CONFIG 0x67 | ||
100 | #define QLCNIC_CMD_GET_LINK_STATUS 0x68 | ||
101 | #define QLCNIC_CMD_SET_LED_CONFIG 0x69 | ||
102 | #define QLCNIC_CMD_GET_LED_CONFIG 0x6A | ||
103 | #define QLCNIC_CMD_ADD_RCV_RINGS 0x0B | ||
104 | |||
105 | #define QLCNIC_INTRPT_INTX 1 | ||
106 | #define QLCNIC_INTRPT_MSIX 3 | ||
107 | #define QLCNIC_INTRPT_ADD 1 | ||
108 | #define QLCNIC_INTRPT_DEL 2 | ||
109 | |||
110 | #define QLCNIC_GET_CURRENT_MAC 1 | ||
111 | #define QLCNIC_SET_STATION_MAC 2 | ||
112 | #define QLCNIC_GET_DEFAULT_MAC 3 | ||
113 | #define QLCNIC_GET_FAC_DEF_MAC 4 | ||
114 | #define QLCNIC_SET_FAC_DEF_MAC 5 | ||
115 | |||
116 | #define QLCNIC_MBX_LINK_EVENT 0x8001 | ||
117 | #define QLCNIC_MBX_COMP_EVENT 0x8100 | ||
118 | #define QLCNIC_MBX_REQUEST_EVENT 0x8101 | ||
119 | #define QLCNIC_MBX_TIME_EXTEND_EVENT 0x8102 | ||
120 | #define QLCNIC_MBX_SFP_INSERT_EVENT 0x8130 | ||
121 | #define QLCNIC_MBX_SFP_REMOVE_EVENT 0x8131 | ||
122 | |||
123 | struct qlcnic_mailbox_metadata { | ||
124 | u32 cmd; | ||
125 | u32 in_args; | ||
126 | u32 out_args; | ||
127 | }; | ||
128 | |||
129 | /* Mailbox ownership */ | ||
130 | #define QLCNIC_GET_OWNER(val) ((val) & (BIT_0 | BIT_1)) | ||
131 | |||
132 | #define QLCNIC_SET_OWNER 1 | ||
133 | #define QLCNIC_CLR_OWNER 0 | ||
134 | #define QLCNIC_MBX_TIMEOUT 10000 | ||
135 | |||
136 | #define QLCNIC_MBX_RSP_OK 1 | ||
137 | #define QLCNIC_MBX_PORT_RSP_OK 0x1a | ||
138 | #define QLCNIC_MBX_ASYNC_EVENT BIT_15 | ||
139 | |||
140 | struct qlcnic_pci_info; | ||
141 | struct qlcnic_info; | ||
142 | struct qlcnic_cmd_args; | ||
143 | struct ethtool_stats; | ||
144 | struct pci_device_id; | ||
145 | struct qlcnic_host_sds_ring; | ||
146 | struct qlcnic_host_tx_ring; | ||
147 | struct qlcnic_host_tx_ring; | ||
148 | struct qlcnic_hardware_context; | ||
149 | struct qlcnic_adapter; | ||
150 | |||
151 | int qlcnic_82xx_start_firmware(struct qlcnic_adapter *); | ||
152 | int qlcnic_82xx_hw_read_wx_2M(struct qlcnic_adapter *adapter, ulong); | ||
153 | int qlcnic_82xx_hw_write_wx_2M(struct qlcnic_adapter *, ulong, u32); | ||
154 | int qlcnic_82xx_config_hw_lro(struct qlcnic_adapter *adapter, int); | ||
155 | int qlcnic_82xx_nic_set_promisc(struct qlcnic_adapter *adapter, u32); | ||
156 | int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter, | ||
157 | struct net_device *netdev); | ||
158 | void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter, | ||
159 | u64 *uaddr, __le16 vlan_id); | ||
160 | void qlcnic_82xx_config_intr_coalesce(struct qlcnic_adapter *adapter); | ||
161 | int qlcnic_82xx_config_rss(struct qlcnic_adapter *adapter, int); | ||
162 | void qlcnic_82xx_config_ipaddr(struct qlcnic_adapter *adapter, | ||
163 | __be32, int); | ||
164 | int qlcnic_82xx_linkevent_request(struct qlcnic_adapter *adapter, int); | ||
165 | void qlcnic_82xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring); | ||
166 | int qlcnic_82xx_clear_lb_mode(struct qlcnic_adapter *adapter, u8); | ||
167 | int qlcnic_82xx_set_lb_mode(struct qlcnic_adapter *, u8); | ||
168 | void qlcnic_82xx_write_crb(struct qlcnic_adapter *, char *, loff_t, size_t); | ||
169 | void qlcnic_82xx_read_crb(struct qlcnic_adapter *, char *, loff_t, size_t); | ||
170 | void qlcnic_82xx_dev_request_reset(struct qlcnic_adapter *, u32); | ||
171 | int qlcnic_82xx_setup_intr(struct qlcnic_adapter *, u8); | ||
172 | irqreturn_t qlcnic_82xx_clear_legacy_intr(struct qlcnic_adapter *); | ||
173 | int qlcnic_82xx_issue_cmd(struct qlcnic_adapter *adapter, | ||
174 | struct qlcnic_cmd_args *); | ||
175 | int qlcnic_82xx_fw_cmd_create_rx_ctx(struct qlcnic_adapter *); | ||
176 | int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *, | ||
177 | struct qlcnic_host_tx_ring *tx_ring, int); | ||
178 | int qlcnic_82xx_sre_macaddr_change(struct qlcnic_adapter *, u8 *, __le16, u8); | ||
179 | int qlcnic_82xx_get_mac_address(struct qlcnic_adapter *, u8*); | ||
180 | int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *, struct qlcnic_info *, u8); | ||
181 | int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *, struct qlcnic_info *); | ||
182 | int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *, struct qlcnic_pci_info*); | ||
183 | int qlcnic_82xx_alloc_mbx_args(struct qlcnic_cmd_args *, | ||
184 | struct qlcnic_adapter *, u32); | ||
185 | int qlcnic_82xx_hw_write_wx_2M(struct qlcnic_adapter *, ulong, u32); | ||
186 | int qlcnic_82xx_get_board_info(struct qlcnic_adapter *); | ||
187 | int qlcnic_82xx_config_led(struct qlcnic_adapter *, u32, u32); | ||
188 | void qlcnic_82xx_get_func_no(struct qlcnic_adapter *); | ||
189 | int qlcnic_82xx_api_lock(struct qlcnic_adapter *); | ||
190 | void qlcnic_82xx_api_unlock(struct qlcnic_adapter *); | ||
191 | void qlcnic_82xx_napi_enable(struct qlcnic_adapter *); | ||
192 | void qlcnic_82xx_napi_disable(struct qlcnic_adapter *); | ||
193 | void qlcnic_82xx_napi_del(struct qlcnic_adapter *); | ||
194 | #endif /* __QLCNIC_HW_H_ */ | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c index de79cde233de..d28336fc65ab 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_init.c | |||
@@ -1,15 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * QLogic qlcnic NIC Driver | 2 | * QLogic qlcnic NIC Driver |
3 | * Copyright (c) 2009-2010 QLogic Corporation | 3 | * Copyright (c) 2009-2013 QLogic Corporation |
4 | * | 4 | * |
5 | * See LICENSE.qlcnic for copyright and licensing details. | 5 | * See LICENSE.qlcnic for copyright and licensing details. |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/netdevice.h> | ||
9 | #include <linux/delay.h> | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/if_vlan.h> | ||
12 | #include "qlcnic.h" | 8 | #include "qlcnic.h" |
9 | #include "qlcnic_hw.h" | ||
13 | 10 | ||
14 | struct crb_addr_pair { | 11 | struct crb_addr_pair { |
15 | u32 addr; | 12 | u32 addr; |
@@ -166,13 +163,12 @@ void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter) | |||
166 | { | 163 | { |
167 | struct qlcnic_recv_context *recv_ctx; | 164 | struct qlcnic_recv_context *recv_ctx; |
168 | struct qlcnic_host_rds_ring *rds_ring; | 165 | struct qlcnic_host_rds_ring *rds_ring; |
169 | struct qlcnic_host_tx_ring *tx_ring; | ||
170 | int ring; | 166 | int ring; |
171 | 167 | ||
172 | recv_ctx = adapter->recv_ctx; | 168 | recv_ctx = adapter->recv_ctx; |
173 | 169 | ||
174 | if (recv_ctx->rds_rings == NULL) | 170 | if (recv_ctx->rds_rings == NULL) |
175 | goto skip_rds; | 171 | return; |
176 | 172 | ||
177 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | 173 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { |
178 | rds_ring = &recv_ctx->rds_rings[ring]; | 174 | rds_ring = &recv_ctx->rds_rings[ring]; |
@@ -180,16 +176,6 @@ void qlcnic_free_sw_resources(struct qlcnic_adapter *adapter) | |||
180 | rds_ring->rx_buf_arr = NULL; | 176 | rds_ring->rx_buf_arr = NULL; |
181 | } | 177 | } |
182 | kfree(recv_ctx->rds_rings); | 178 | kfree(recv_ctx->rds_rings); |
183 | |||
184 | skip_rds: | ||
185 | if (adapter->tx_ring == NULL) | ||
186 | return; | ||
187 | |||
188 | tx_ring = adapter->tx_ring; | ||
189 | vfree(tx_ring->cmd_buf_arr); | ||
190 | tx_ring->cmd_buf_arr = NULL; | ||
191 | kfree(adapter->tx_ring); | ||
192 | adapter->tx_ring = NULL; | ||
193 | } | 179 | } |
194 | 180 | ||
195 | int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) | 181 | int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) |
@@ -197,39 +183,16 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) | |||
197 | struct qlcnic_recv_context *recv_ctx; | 183 | struct qlcnic_recv_context *recv_ctx; |
198 | struct qlcnic_host_rds_ring *rds_ring; | 184 | struct qlcnic_host_rds_ring *rds_ring; |
199 | struct qlcnic_host_sds_ring *sds_ring; | 185 | struct qlcnic_host_sds_ring *sds_ring; |
200 | struct qlcnic_host_tx_ring *tx_ring; | ||
201 | struct qlcnic_rx_buffer *rx_buf; | 186 | struct qlcnic_rx_buffer *rx_buf; |
202 | int ring, i, size; | 187 | int ring, i; |
203 | |||
204 | struct qlcnic_cmd_buffer *cmd_buf_arr; | ||
205 | struct net_device *netdev = adapter->netdev; | ||
206 | |||
207 | size = sizeof(struct qlcnic_host_tx_ring); | ||
208 | tx_ring = kzalloc(size, GFP_KERNEL); | ||
209 | if (tx_ring == NULL) { | ||
210 | dev_err(&netdev->dev, "failed to allocate tx ring struct\n"); | ||
211 | return -ENOMEM; | ||
212 | } | ||
213 | adapter->tx_ring = tx_ring; | ||
214 | |||
215 | tx_ring->num_desc = adapter->num_txd; | ||
216 | tx_ring->txq = netdev_get_tx_queue(netdev, 0); | ||
217 | |||
218 | cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring)); | ||
219 | if (cmd_buf_arr == NULL) { | ||
220 | dev_err(&netdev->dev, "failed to allocate cmd buffer ring\n"); | ||
221 | goto err_out; | ||
222 | } | ||
223 | tx_ring->cmd_buf_arr = cmd_buf_arr; | ||
224 | 188 | ||
225 | recv_ctx = adapter->recv_ctx; | 189 | recv_ctx = adapter->recv_ctx; |
226 | 190 | ||
227 | size = adapter->max_rds_rings * sizeof(struct qlcnic_host_rds_ring); | 191 | rds_ring = kcalloc(adapter->max_rds_rings, |
228 | rds_ring = kzalloc(size, GFP_KERNEL); | 192 | sizeof(struct qlcnic_host_rds_ring), GFP_KERNEL); |
229 | if (rds_ring == NULL) { | 193 | if (rds_ring == NULL) |
230 | dev_err(&netdev->dev, "failed to allocate rds ring struct\n"); | ||
231 | goto err_out; | 194 | goto err_out; |
232 | } | 195 | |
233 | recv_ctx->rds_rings = rds_ring; | 196 | recv_ctx->rds_rings = rds_ring; |
234 | 197 | ||
235 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | 198 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { |
@@ -255,11 +218,9 @@ int qlcnic_alloc_sw_resources(struct qlcnic_adapter *adapter) | |||
255 | break; | 218 | break; |
256 | } | 219 | } |
257 | rds_ring->rx_buf_arr = vzalloc(RCV_BUFF_RINGSIZE(rds_ring)); | 220 | rds_ring->rx_buf_arr = vzalloc(RCV_BUFF_RINGSIZE(rds_ring)); |
258 | if (rds_ring->rx_buf_arr == NULL) { | 221 | if (rds_ring->rx_buf_arr == NULL) |
259 | dev_err(&netdev->dev, "Failed to allocate " | ||
260 | "rx buffer ring %d\n", ring); | ||
261 | goto err_out; | 222 | goto err_out; |
262 | } | 223 | |
263 | INIT_LIST_HEAD(&rds_ring->free_list); | 224 | INIT_LIST_HEAD(&rds_ring->free_list); |
264 | /* | 225 | /* |
265 | * Now go through all of them, set reference handles | 226 | * Now go through all of them, set reference handles |
@@ -327,7 +288,6 @@ static int qlcnic_wait_rom_done(struct qlcnic_adapter *adapter) | |||
327 | long done = 0; | 288 | long done = 0; |
328 | 289 | ||
329 | cond_resched(); | 290 | cond_resched(); |
330 | |||
331 | while (done == 0) { | 291 | while (done == 0) { |
332 | done = QLCRD32(adapter, QLCNIC_ROMUSB_GLB_STATUS); | 292 | done = QLCRD32(adapter, QLCNIC_ROMUSB_GLB_STATUS); |
333 | done &= 2; | 293 | done &= 2; |
@@ -416,8 +376,8 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter) | |||
416 | u32 off; | 376 | u32 off; |
417 | struct pci_dev *pdev = adapter->pdev; | 377 | struct pci_dev *pdev = adapter->pdev; |
418 | 378 | ||
419 | QLCWR32(adapter, CRB_CMDPEG_STATE, 0); | 379 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CMDPEG_STATE, 0); |
420 | QLCWR32(adapter, CRB_RCVPEG_STATE, 0); | 380 | QLC_SHARED_REG_WR32(adapter, QLCNIC_RCVPEG_STATE, 0); |
421 | 381 | ||
422 | /* Halt all the indiviual PEGs and other blocks */ | 382 | /* Halt all the indiviual PEGs and other blocks */ |
423 | /* disable all I2Q */ | 383 | /* disable all I2Q */ |
@@ -482,10 +442,8 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter) | |||
482 | } | 442 | } |
483 | 443 | ||
484 | buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL); | 444 | buf = kcalloc(n, sizeof(struct crb_addr_pair), GFP_KERNEL); |
485 | if (buf == NULL) { | 445 | if (buf == NULL) |
486 | dev_err(&pdev->dev, "Unable to calloc memory for rom read.\n"); | ||
487 | return -ENOMEM; | 446 | return -ENOMEM; |
488 | } | ||
489 | 447 | ||
490 | for (i = 0; i < n; i++) { | 448 | for (i = 0; i < n; i++) { |
491 | if (qlcnic_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 || | 449 | if (qlcnic_rom_fast_read(adapter, 8*i + 4*offset, &val) != 0 || |
@@ -564,8 +522,8 @@ int qlcnic_pinit_from_rom(struct qlcnic_adapter *adapter) | |||
564 | QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0xc, 0); | 522 | QLCWR32(adapter, QLCNIC_CRB_PEG_NET_4 + 0xc, 0); |
565 | msleep(1); | 523 | msleep(1); |
566 | 524 | ||
567 | QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS1, 0); | 525 | QLC_SHARED_REG_WR32(adapter, QLCNIC_PEG_HALT_STATUS1, 0); |
568 | QLCWR32(adapter, QLCNIC_PEG_HALT_STATUS2, 0); | 526 | QLC_SHARED_REG_WR32(adapter, QLCNIC_PEG_HALT_STATUS2, 0); |
569 | 527 | ||
570 | return 0; | 528 | return 0; |
571 | } | 529 | } |
@@ -576,7 +534,7 @@ static int qlcnic_cmd_peg_ready(struct qlcnic_adapter *adapter) | |||
576 | int retries = QLCNIC_CMDPEG_CHECK_RETRY_COUNT; | 534 | int retries = QLCNIC_CMDPEG_CHECK_RETRY_COUNT; |
577 | 535 | ||
578 | do { | 536 | do { |
579 | val = QLCRD32(adapter, CRB_CMDPEG_STATE); | 537 | val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CMDPEG_STATE); |
580 | 538 | ||
581 | switch (val) { | 539 | switch (val) { |
582 | case PHAN_INITIALIZE_COMPLETE: | 540 | case PHAN_INITIALIZE_COMPLETE: |
@@ -592,7 +550,8 @@ static int qlcnic_cmd_peg_ready(struct qlcnic_adapter *adapter) | |||
592 | 550 | ||
593 | } while (--retries); | 551 | } while (--retries); |
594 | 552 | ||
595 | QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_FAILED); | 553 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CMDPEG_STATE, |
554 | PHAN_INITIALIZE_FAILED); | ||
596 | 555 | ||
597 | out_err: | 556 | out_err: |
598 | dev_err(&adapter->pdev->dev, "Command Peg initialization not " | 557 | dev_err(&adapter->pdev->dev, "Command Peg initialization not " |
@@ -607,7 +566,7 @@ qlcnic_receive_peg_ready(struct qlcnic_adapter *adapter) | |||
607 | int retries = QLCNIC_RCVPEG_CHECK_RETRY_COUNT; | 566 | int retries = QLCNIC_RCVPEG_CHECK_RETRY_COUNT; |
608 | 567 | ||
609 | do { | 568 | do { |
610 | val = QLCRD32(adapter, CRB_RCVPEG_STATE); | 569 | val = QLC_SHARED_REG_RD32(adapter, QLCNIC_RCVPEG_STATE); |
611 | 570 | ||
612 | if (val == PHAN_PEG_RCV_INITIALIZED) | 571 | if (val == PHAN_PEG_RCV_INITIALIZED) |
613 | return 0; | 572 | return 0; |
@@ -638,7 +597,7 @@ qlcnic_check_fw_status(struct qlcnic_adapter *adapter) | |||
638 | if (err) | 597 | if (err) |
639 | return err; | 598 | return err; |
640 | 599 | ||
641 | QLCWR32(adapter, CRB_CMDPEG_STATE, PHAN_INITIALIZE_ACK); | 600 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CMDPEG_STATE, PHAN_INITIALIZE_ACK); |
642 | 601 | ||
643 | return err; | 602 | return err; |
644 | } | 603 | } |
@@ -649,7 +608,7 @@ qlcnic_setup_idc_param(struct qlcnic_adapter *adapter) { | |||
649 | int timeo; | 608 | int timeo; |
650 | u32 val; | 609 | u32 val; |
651 | 610 | ||
652 | val = QLCRD32(adapter, QLCNIC_CRB_DEV_PARTITION_INFO); | 611 | val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_PARTITION_INFO); |
653 | val = QLC_DEV_GET_DRV(val, adapter->portnum); | 612 | val = QLC_DEV_GET_DRV(val, adapter->portnum); |
654 | if ((val & 0x3) != QLCNIC_TYPE_NIC) { | 613 | if ((val & 0x3) != QLCNIC_TYPE_NIC) { |
655 | dev_err(&adapter->pdev->dev, | 614 | dev_err(&adapter->pdev->dev, |
@@ -689,11 +648,9 @@ static int qlcnic_get_flt_entry(struct qlcnic_adapter *adapter, u8 region, | |||
689 | } | 648 | } |
690 | 649 | ||
691 | entry_size = flt_hdr.len - sizeof(struct qlcnic_flt_header); | 650 | entry_size = flt_hdr.len - sizeof(struct qlcnic_flt_header); |
692 | flt_entry = (struct qlcnic_flt_entry *)vzalloc(entry_size); | 651 | flt_entry = vzalloc(entry_size); |
693 | if (flt_entry == NULL) { | 652 | if (flt_entry == NULL) |
694 | dev_warn(&adapter->pdev->dev, "error allocating memory\n"); | ||
695 | return -EIO; | 653 | return -EIO; |
696 | } | ||
697 | 654 | ||
698 | ret = qlcnic_rom_fast_read_words(adapter, QLCNIC_FLT_LOCATION + | 655 | ret = qlcnic_rom_fast_read_words(adapter, QLCNIC_FLT_LOCATION + |
699 | sizeof(struct qlcnic_flt_header), | 656 | sizeof(struct qlcnic_flt_header), |
@@ -1096,11 +1053,13 @@ qlcnic_check_fw_hearbeat(struct qlcnic_adapter *adapter) | |||
1096 | u32 heartbeat, ret = -EIO; | 1053 | u32 heartbeat, ret = -EIO; |
1097 | int retries = QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT; | 1054 | int retries = QLCNIC_HEARTBEAT_CHECK_RETRY_COUNT; |
1098 | 1055 | ||
1099 | adapter->heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER); | 1056 | adapter->heartbeat = QLC_SHARED_REG_RD32(adapter, |
1057 | QLCNIC_PEG_ALIVE_COUNTER); | ||
1100 | 1058 | ||
1101 | do { | 1059 | do { |
1102 | msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS); | 1060 | msleep(QLCNIC_HEARTBEAT_PERIOD_MSECS); |
1103 | heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER); | 1061 | heartbeat = QLC_SHARED_REG_RD32(adapter, |
1062 | QLCNIC_PEG_ALIVE_COUNTER); | ||
1104 | if (heartbeat != adapter->heartbeat) { | 1063 | if (heartbeat != adapter->heartbeat) { |
1105 | ret = QLCNIC_RCODE_SUCCESS; | 1064 | ret = QLCNIC_RCODE_SUCCESS; |
1106 | break; | 1065 | break; |
@@ -1270,7 +1229,7 @@ qlcnic_validate_firmware(struct qlcnic_adapter *adapter) | |||
1270 | return -EINVAL; | 1229 | return -EINVAL; |
1271 | } | 1230 | } |
1272 | 1231 | ||
1273 | QLCWR32(adapter, QLCNIC_CAM_RAM(0x1fc), QLCNIC_BDINFO_MAGIC); | 1232 | QLC_SHARED_REG_WR32(adapter, QLCNIC_FW_IMG_VALID, QLCNIC_BDINFO_MAGIC); |
1274 | return 0; | 1233 | return 0; |
1275 | } | 1234 | } |
1276 | 1235 | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c index 6f82812d0fab..0e630061bff3 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | |||
@@ -1,3 +1,10 @@ | |||
1 | /* | ||
2 | * QLogic qlcnic NIC Driver | ||
3 | * Copyright (c) 2009-2013 QLogic Corporation | ||
4 | * | ||
5 | * See LICENSE.qlcnic for copyright and licensing details. | ||
6 | */ | ||
7 | |||
1 | #include <linux/netdevice.h> | 8 | #include <linux/netdevice.h> |
2 | #include <linux/if_vlan.h> | 9 | #include <linux/if_vlan.h> |
3 | #include <net/ip.h> | 10 | #include <net/ip.h> |
@@ -5,9 +12,6 @@ | |||
5 | 12 | ||
6 | #include "qlcnic.h" | 13 | #include "qlcnic.h" |
7 | 14 | ||
8 | #define QLCNIC_MAC_HASH(MAC)\ | ||
9 | ((((MAC) & 0x70000) >> 0x10) | (((MAC) & 0x70000000000ULL) >> 0x25)) | ||
10 | |||
11 | #define TX_ETHER_PKT 0x01 | 15 | #define TX_ETHER_PKT 0x01 |
12 | #define TX_TCP_PKT 0x02 | 16 | #define TX_TCP_PKT 0x02 |
13 | #define TX_UDP_PKT 0x03 | 17 | #define TX_UDP_PKT 0x03 |
@@ -84,6 +88,8 @@ | |||
84 | #define qlcnic_get_lro_sts_mss(sts_data1) \ | 88 | #define qlcnic_get_lro_sts_mss(sts_data1) \ |
85 | ((sts_data1 >> 32) & 0x0FFFF) | 89 | ((sts_data1 >> 32) & 0x0FFFF) |
86 | 90 | ||
91 | #define qlcnic_83xx_get_lro_sts_mss(sts) ((sts) & 0xffff) | ||
92 | |||
87 | /* opcode field in status_desc */ | 93 | /* opcode field in status_desc */ |
88 | #define QLCNIC_SYN_OFFLOAD 0x03 | 94 | #define QLCNIC_SYN_OFFLOAD 0x03 |
89 | #define QLCNIC_RXPKT_DESC 0x04 | 95 | #define QLCNIC_RXPKT_DESC 0x04 |
@@ -91,18 +97,152 @@ | |||
91 | #define QLCNIC_RESPONSE_DESC 0x05 | 97 | #define QLCNIC_RESPONSE_DESC 0x05 |
92 | #define QLCNIC_LRO_DESC 0x12 | 98 | #define QLCNIC_LRO_DESC 0x12 |
93 | 99 | ||
100 | #define QLCNIC_TX_POLL_BUDGET 128 | ||
101 | #define QLCNIC_TCP_HDR_SIZE 20 | ||
102 | #define QLCNIC_TCP_TS_OPTION_SIZE 12 | ||
103 | #define QLCNIC_FETCH_RING_ID(handle) ((handle) >> 63) | ||
104 | #define QLCNIC_DESC_OWNER_FW cpu_to_le64(STATUS_OWNER_PHANTOM) | ||
105 | |||
106 | #define QLCNIC_TCP_TS_HDR_SIZE (QLCNIC_TCP_HDR_SIZE + QLCNIC_TCP_TS_OPTION_SIZE) | ||
107 | |||
94 | /* for status field in status_desc */ | 108 | /* for status field in status_desc */ |
95 | #define STATUS_CKSUM_LOOP 0 | 109 | #define STATUS_CKSUM_LOOP 0 |
96 | #define STATUS_CKSUM_OK 2 | 110 | #define STATUS_CKSUM_OK 2 |
97 | 111 | ||
98 | static void qlcnic_change_filter(struct qlcnic_adapter *adapter, | 112 | #define qlcnic_83xx_pktln(sts) ((sts >> 32) & 0x3FFF) |
99 | u64 uaddr, __le16 vlan_id, | 113 | #define qlcnic_83xx_hndl(sts) ((sts >> 48) & 0x7FFF) |
100 | struct qlcnic_host_tx_ring *tx_ring) | 114 | #define qlcnic_83xx_csum_status(sts) ((sts >> 39) & 7) |
115 | #define qlcnic_83xx_opcode(sts) ((sts >> 42) & 0xF) | ||
116 | #define qlcnic_83xx_vlan_tag(sts) (((sts) >> 48) & 0xFFFF) | ||
117 | #define qlcnic_83xx_lro_pktln(sts) (((sts) >> 32) & 0x3FFF) | ||
118 | #define qlcnic_83xx_l2_hdr_off(sts) (((sts) >> 16) & 0xFF) | ||
119 | #define qlcnic_83xx_l4_hdr_off(sts) (((sts) >> 24) & 0xFF) | ||
120 | #define qlcnic_83xx_pkt_cnt(sts) (((sts) >> 16) & 0x7) | ||
121 | #define qlcnic_83xx_is_tstamp(sts) (((sts) >> 40) & 1) | ||
122 | #define qlcnic_83xx_is_psh_bit(sts) (((sts) >> 41) & 1) | ||
123 | #define qlcnic_83xx_is_ip_align(sts) (((sts) >> 46) & 1) | ||
124 | #define qlcnic_83xx_has_vlan_tag(sts) (((sts) >> 47) & 1) | ||
125 | |||
126 | struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *, | ||
127 | struct qlcnic_host_rds_ring *, u16, u16); | ||
128 | |||
129 | inline void qlcnic_83xx_enable_tx_intr(struct qlcnic_adapter *adapter, | ||
130 | struct qlcnic_host_tx_ring *tx_ring) | ||
131 | { | ||
132 | writel(0, tx_ring->crb_intr_mask); | ||
133 | } | ||
134 | |||
135 | inline void qlcnic_83xx_disable_tx_intr(struct qlcnic_adapter *adapter, | ||
136 | struct qlcnic_host_tx_ring *tx_ring) | ||
137 | { | ||
138 | writel(1, tx_ring->crb_intr_mask); | ||
139 | } | ||
140 | |||
141 | static inline u8 qlcnic_mac_hash(u64 mac) | ||
142 | { | ||
143 | return (u8)((mac & 0xff) ^ ((mac >> 40) & 0xff)); | ||
144 | } | ||
145 | |||
146 | static inline u32 qlcnic_get_ref_handle(struct qlcnic_adapter *adapter, | ||
147 | u16 handle, u8 ring_id) | ||
148 | { | ||
149 | if (adapter->pdev->device == PCI_DEVICE_ID_QLOGIC_QLE834X) | ||
150 | return handle | (ring_id << 15); | ||
151 | else | ||
152 | return handle; | ||
153 | } | ||
154 | |||
155 | static inline int qlcnic_82xx_is_lb_pkt(u64 sts_data) | ||
156 | { | ||
157 | return (qlcnic_get_sts_status(sts_data) == STATUS_CKSUM_LOOP) ? 1 : 0; | ||
158 | } | ||
159 | |||
160 | void qlcnic_add_lb_filter(struct qlcnic_adapter *adapter, struct sk_buff *skb, | ||
161 | int loopback_pkt, __le16 vlan_id) | ||
162 | { | ||
163 | struct ethhdr *phdr = (struct ethhdr *)(skb->data); | ||
164 | struct qlcnic_filter *fil, *tmp_fil; | ||
165 | struct hlist_node *n; | ||
166 | struct hlist_head *head; | ||
167 | unsigned long time; | ||
168 | u64 src_addr = 0; | ||
169 | u8 hindex, found = 0, op; | ||
170 | int ret; | ||
171 | |||
172 | memcpy(&src_addr, phdr->h_source, ETH_ALEN); | ||
173 | |||
174 | if (loopback_pkt) { | ||
175 | if (adapter->rx_fhash.fnum >= adapter->rx_fhash.fmax) | ||
176 | return; | ||
177 | |||
178 | hindex = qlcnic_mac_hash(src_addr) & | ||
179 | (adapter->fhash.fbucket_size - 1); | ||
180 | head = &(adapter->rx_fhash.fhead[hindex]); | ||
181 | |||
182 | hlist_for_each_entry_safe(tmp_fil, n, head, fnode) { | ||
183 | if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) && | ||
184 | tmp_fil->vlan_id == vlan_id) { | ||
185 | time = tmp_fil->ftime; | ||
186 | if (jiffies > (QLCNIC_READD_AGE * HZ + time)) | ||
187 | tmp_fil->ftime = jiffies; | ||
188 | return; | ||
189 | } | ||
190 | } | ||
191 | |||
192 | fil = kzalloc(sizeof(struct qlcnic_filter), GFP_ATOMIC); | ||
193 | if (!fil) | ||
194 | return; | ||
195 | |||
196 | fil->ftime = jiffies; | ||
197 | memcpy(fil->faddr, &src_addr, ETH_ALEN); | ||
198 | fil->vlan_id = vlan_id; | ||
199 | spin_lock(&adapter->rx_mac_learn_lock); | ||
200 | hlist_add_head(&(fil->fnode), head); | ||
201 | adapter->rx_fhash.fnum++; | ||
202 | spin_unlock(&adapter->rx_mac_learn_lock); | ||
203 | } else { | ||
204 | hindex = qlcnic_mac_hash(src_addr) & | ||
205 | (adapter->fhash.fbucket_size - 1); | ||
206 | head = &(adapter->rx_fhash.fhead[hindex]); | ||
207 | spin_lock(&adapter->rx_mac_learn_lock); | ||
208 | hlist_for_each_entry_safe(tmp_fil, n, head, fnode) { | ||
209 | if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) && | ||
210 | tmp_fil->vlan_id == vlan_id) { | ||
211 | found = 1; | ||
212 | break; | ||
213 | } | ||
214 | } | ||
215 | |||
216 | if (!found) { | ||
217 | spin_unlock(&adapter->rx_mac_learn_lock); | ||
218 | return; | ||
219 | } | ||
220 | |||
221 | op = vlan_id ? QLCNIC_MAC_VLAN_ADD : QLCNIC_MAC_ADD; | ||
222 | ret = qlcnic_sre_macaddr_change(adapter, (u8 *)&src_addr, | ||
223 | vlan_id, op); | ||
224 | if (!ret) { | ||
225 | op = vlan_id ? QLCNIC_MAC_VLAN_DEL : QLCNIC_MAC_DEL; | ||
226 | ret = qlcnic_sre_macaddr_change(adapter, | ||
227 | (u8 *)&src_addr, | ||
228 | vlan_id, op); | ||
229 | if (!ret) { | ||
230 | hlist_del(&(tmp_fil->fnode)); | ||
231 | adapter->rx_fhash.fnum--; | ||
232 | } | ||
233 | } | ||
234 | spin_unlock(&adapter->rx_mac_learn_lock); | ||
235 | } | ||
236 | } | ||
237 | |||
238 | void qlcnic_82xx_change_filter(struct qlcnic_adapter *adapter, u64 *uaddr, | ||
239 | __le16 vlan_id) | ||
101 | { | 240 | { |
102 | struct cmd_desc_type0 *hwdesc; | 241 | struct cmd_desc_type0 *hwdesc; |
103 | struct qlcnic_nic_req *req; | 242 | struct qlcnic_nic_req *req; |
104 | struct qlcnic_mac_req *mac_req; | 243 | struct qlcnic_mac_req *mac_req; |
105 | struct qlcnic_vlan_req *vlan_req; | 244 | struct qlcnic_vlan_req *vlan_req; |
245 | struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; | ||
106 | u32 producer; | 246 | u32 producer; |
107 | u64 word; | 247 | u64 word; |
108 | 248 | ||
@@ -128,14 +268,14 @@ static void qlcnic_change_filter(struct qlcnic_adapter *adapter, | |||
128 | } | 268 | } |
129 | 269 | ||
130 | static void qlcnic_send_filter(struct qlcnic_adapter *adapter, | 270 | static void qlcnic_send_filter(struct qlcnic_adapter *adapter, |
131 | struct qlcnic_host_tx_ring *tx_ring, | ||
132 | struct cmd_desc_type0 *first_desc, | 271 | struct cmd_desc_type0 *first_desc, |
133 | struct sk_buff *skb) | 272 | struct sk_buff *skb) |
134 | { | 273 | { |
135 | struct ethhdr *phdr = (struct ethhdr *)(skb->data); | ||
136 | struct qlcnic_filter *fil, *tmp_fil; | 274 | struct qlcnic_filter *fil, *tmp_fil; |
137 | struct hlist_node *tmp_hnode, *n; | 275 | struct hlist_node *n; |
138 | struct hlist_head *head; | 276 | struct hlist_head *head; |
277 | struct net_device *netdev = adapter->netdev; | ||
278 | struct ethhdr *phdr = (struct ethhdr *)(skb->data); | ||
139 | u64 src_addr = 0; | 279 | u64 src_addr = 0; |
140 | __le16 vlan_id = 0; | 280 | __le16 vlan_id = 0; |
141 | u8 hindex; | 281 | u8 hindex; |
@@ -143,23 +283,23 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter, | |||
143 | if (ether_addr_equal(phdr->h_source, adapter->mac_addr)) | 283 | if (ether_addr_equal(phdr->h_source, adapter->mac_addr)) |
144 | return; | 284 | return; |
145 | 285 | ||
146 | if (adapter->fhash.fnum >= adapter->fhash.fmax) | 286 | if (adapter->fhash.fnum >= adapter->fhash.fmax) { |
287 | adapter->stats.mac_filter_limit_overrun++; | ||
288 | netdev_info(netdev, "Can not add more than %d mac addresses\n", | ||
289 | adapter->fhash.fmax); | ||
147 | return; | 290 | return; |
291 | } | ||
148 | 292 | ||
149 | /* Only NPAR capable devices support vlan based learning*/ | ||
150 | if (adapter->flags & QLCNIC_ESWITCH_ENABLED) | ||
151 | vlan_id = first_desc->vlan_TCI; | ||
152 | memcpy(&src_addr, phdr->h_source, ETH_ALEN); | 293 | memcpy(&src_addr, phdr->h_source, ETH_ALEN); |
153 | hindex = QLCNIC_MAC_HASH(src_addr) & (QLCNIC_LB_MAX_FILTERS - 1); | 294 | hindex = qlcnic_mac_hash(src_addr) & (adapter->fhash.fbucket_size - 1); |
154 | head = &(adapter->fhash.fhead[hindex]); | 295 | head = &(adapter->fhash.fhead[hindex]); |
155 | 296 | ||
156 | hlist_for_each_entry_safe(tmp_fil, tmp_hnode, n, head, fnode) { | 297 | hlist_for_each_entry_safe(tmp_fil, n, head, fnode) { |
157 | if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) && | 298 | if (!memcmp(tmp_fil->faddr, &src_addr, ETH_ALEN) && |
158 | tmp_fil->vlan_id == vlan_id) { | 299 | tmp_fil->vlan_id == vlan_id) { |
159 | |||
160 | if (jiffies > (QLCNIC_READD_AGE * HZ + tmp_fil->ftime)) | 300 | if (jiffies > (QLCNIC_READD_AGE * HZ + tmp_fil->ftime)) |
161 | qlcnic_change_filter(adapter, src_addr, vlan_id, | 301 | qlcnic_change_filter(adapter, &src_addr, |
162 | tx_ring); | 302 | vlan_id); |
163 | tmp_fil->ftime = jiffies; | 303 | tmp_fil->ftime = jiffies; |
164 | return; | 304 | return; |
165 | } | 305 | } |
@@ -169,17 +309,13 @@ static void qlcnic_send_filter(struct qlcnic_adapter *adapter, | |||
169 | if (!fil) | 309 | if (!fil) |
170 | return; | 310 | return; |
171 | 311 | ||
172 | qlcnic_change_filter(adapter, src_addr, vlan_id, tx_ring); | 312 | qlcnic_change_filter(adapter, &src_addr, vlan_id); |
173 | |||
174 | fil->ftime = jiffies; | 313 | fil->ftime = jiffies; |
175 | fil->vlan_id = vlan_id; | 314 | fil->vlan_id = vlan_id; |
176 | memcpy(fil->faddr, &src_addr, ETH_ALEN); | 315 | memcpy(fil->faddr, &src_addr, ETH_ALEN); |
177 | |||
178 | spin_lock(&adapter->mac_learn_lock); | 316 | spin_lock(&adapter->mac_learn_lock); |
179 | |||
180 | hlist_add_head(&(fil->fnode), head); | 317 | hlist_add_head(&(fil->fnode), head); |
181 | adapter->fhash.fnum++; | 318 | adapter->fhash.fnum++; |
182 | |||
183 | spin_unlock(&adapter->mac_learn_lock); | 319 | spin_unlock(&adapter->mac_learn_lock); |
184 | } | 320 | } |
185 | 321 | ||
@@ -474,8 +610,8 @@ netdev_tx_t qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
474 | if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb))) | 610 | if (unlikely(qlcnic_tx_pkt(adapter, first_desc, skb))) |
475 | goto unwind_buff; | 611 | goto unwind_buff; |
476 | 612 | ||
477 | if (adapter->mac_learn) | 613 | if (adapter->drv_mac_learn) |
478 | qlcnic_send_filter(adapter, tx_ring, first_desc, skb); | 614 | qlcnic_send_filter(adapter, first_desc, skb); |
479 | 615 | ||
480 | adapter->stats.txbytes += skb->len; | 616 | adapter->stats.txbytes += skb->len; |
481 | adapter->stats.xmitcalled++; | 617 | adapter->stats.xmitcalled++; |
@@ -528,8 +664,8 @@ static int qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, | |||
528 | } | 664 | } |
529 | 665 | ||
530 | skb_reserve(skb, NET_IP_ALIGN); | 666 | skb_reserve(skb, NET_IP_ALIGN); |
531 | dma = pci_map_single(pdev, skb->data, rds_ring->dma_size, | 667 | dma = pci_map_single(pdev, skb->data, |
532 | PCI_DMA_FROMDEVICE); | 668 | rds_ring->dma_size, PCI_DMA_FROMDEVICE); |
533 | 669 | ||
534 | if (pci_dma_mapping_error(pdev, dma)) { | 670 | if (pci_dma_mapping_error(pdev, dma)) { |
535 | adapter->stats.rx_dma_map_error++; | 671 | adapter->stats.rx_dma_map_error++; |
@@ -544,12 +680,13 @@ static int qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, | |||
544 | } | 680 | } |
545 | 681 | ||
546 | static void qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, | 682 | static void qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, |
547 | struct qlcnic_host_rds_ring *rds_ring) | 683 | struct qlcnic_host_rds_ring *rds_ring, |
684 | u8 ring_id) | ||
548 | { | 685 | { |
549 | struct rcv_desc *pdesc; | 686 | struct rcv_desc *pdesc; |
550 | struct qlcnic_rx_buffer *buffer; | 687 | struct qlcnic_rx_buffer *buffer; |
551 | int count = 0; | 688 | int count = 0; |
552 | uint32_t producer; | 689 | uint32_t producer, handle; |
553 | struct list_head *head; | 690 | struct list_head *head; |
554 | 691 | ||
555 | if (!spin_trylock(&rds_ring->lock)) | 692 | if (!spin_trylock(&rds_ring->lock)) |
@@ -557,7 +694,6 @@ static void qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, | |||
557 | 694 | ||
558 | producer = rds_ring->producer; | 695 | producer = rds_ring->producer; |
559 | head = &rds_ring->free_list; | 696 | head = &rds_ring->free_list; |
560 | |||
561 | while (!list_empty(head)) { | 697 | while (!list_empty(head)) { |
562 | buffer = list_entry(head->next, struct qlcnic_rx_buffer, list); | 698 | buffer = list_entry(head->next, struct qlcnic_rx_buffer, list); |
563 | 699 | ||
@@ -565,28 +701,29 @@ static void qlcnic_post_rx_buffers_nodb(struct qlcnic_adapter *adapter, | |||
565 | if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer)) | 701 | if (qlcnic_alloc_rx_skb(adapter, rds_ring, buffer)) |
566 | break; | 702 | break; |
567 | } | 703 | } |
568 | |||
569 | count++; | 704 | count++; |
570 | list_del(&buffer->list); | 705 | list_del(&buffer->list); |
571 | 706 | ||
572 | /* make a rcv descriptor */ | 707 | /* make a rcv descriptor */ |
573 | pdesc = &rds_ring->desc_head[producer]; | 708 | pdesc = &rds_ring->desc_head[producer]; |
574 | pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); | 709 | handle = qlcnic_get_ref_handle(adapter, |
710 | buffer->ref_handle, ring_id); | ||
711 | pdesc->reference_handle = cpu_to_le16(handle); | ||
575 | pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); | 712 | pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); |
576 | pdesc->addr_buffer = cpu_to_le64(buffer->dma); | 713 | pdesc->addr_buffer = cpu_to_le64(buffer->dma); |
577 | producer = get_next_index(producer, rds_ring->num_desc); | 714 | producer = get_next_index(producer, rds_ring->num_desc); |
578 | } | 715 | } |
579 | |||
580 | if (count) { | 716 | if (count) { |
581 | rds_ring->producer = producer; | 717 | rds_ring->producer = producer; |
582 | writel((producer - 1) & (rds_ring->num_desc - 1), | 718 | writel((producer - 1) & (rds_ring->num_desc - 1), |
583 | rds_ring->crb_rcv_producer); | 719 | rds_ring->crb_rcv_producer); |
584 | } | 720 | } |
585 | |||
586 | spin_unlock(&rds_ring->lock); | 721 | spin_unlock(&rds_ring->lock); |
587 | } | 722 | } |
588 | 723 | ||
589 | static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter) | 724 | static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter, |
725 | struct qlcnic_host_tx_ring *tx_ring, | ||
726 | int budget) | ||
590 | { | 727 | { |
591 | u32 sw_consumer, hw_consumer; | 728 | u32 sw_consumer, hw_consumer; |
592 | int i, done, count = 0; | 729 | int i, done, count = 0; |
@@ -594,7 +731,6 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter) | |||
594 | struct pci_dev *pdev = adapter->pdev; | 731 | struct pci_dev *pdev = adapter->pdev; |
595 | struct net_device *netdev = adapter->netdev; | 732 | struct net_device *netdev = adapter->netdev; |
596 | struct qlcnic_skb_frag *frag; | 733 | struct qlcnic_skb_frag *frag; |
597 | struct qlcnic_host_tx_ring *tx_ring = adapter->tx_ring; | ||
598 | 734 | ||
599 | if (!spin_trylock(&adapter->tx_clean_lock)) | 735 | if (!spin_trylock(&adapter->tx_clean_lock)) |
600 | return 1; | 736 | return 1; |
@@ -615,22 +751,19 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter) | |||
615 | PCI_DMA_TODEVICE); | 751 | PCI_DMA_TODEVICE); |
616 | frag->dma = 0ULL; | 752 | frag->dma = 0ULL; |
617 | } | 753 | } |
618 | |||
619 | adapter->stats.xmitfinished++; | 754 | adapter->stats.xmitfinished++; |
620 | dev_kfree_skb_any(buffer->skb); | 755 | dev_kfree_skb_any(buffer->skb); |
621 | buffer->skb = NULL; | 756 | buffer->skb = NULL; |
622 | } | 757 | } |
623 | 758 | ||
624 | sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc); | 759 | sw_consumer = get_next_index(sw_consumer, tx_ring->num_desc); |
625 | if (++count >= MAX_STATUS_HANDLE) | 760 | if (++count >= budget) |
626 | break; | 761 | break; |
627 | } | 762 | } |
628 | 763 | ||
629 | if (count && netif_running(netdev)) { | 764 | if (count && netif_running(netdev)) { |
630 | tx_ring->sw_consumer = sw_consumer; | 765 | tx_ring->sw_consumer = sw_consumer; |
631 | |||
632 | smp_mb(); | 766 | smp_mb(); |
633 | |||
634 | if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { | 767 | if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { |
635 | if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) { | 768 | if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) { |
636 | netif_wake_queue(netdev); | 769 | netif_wake_queue(netdev); |
@@ -654,7 +787,6 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter) | |||
654 | */ | 787 | */ |
655 | hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); | 788 | hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer)); |
656 | done = (sw_consumer == hw_consumer); | 789 | done = (sw_consumer == hw_consumer); |
657 | |||
658 | spin_unlock(&adapter->tx_clean_lock); | 790 | spin_unlock(&adapter->tx_clean_lock); |
659 | 791 | ||
660 | return done; | 792 | return done; |
@@ -662,16 +794,15 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter) | |||
662 | 794 | ||
663 | static int qlcnic_poll(struct napi_struct *napi, int budget) | 795 | static int qlcnic_poll(struct napi_struct *napi, int budget) |
664 | { | 796 | { |
797 | int tx_complete, work_done; | ||
665 | struct qlcnic_host_sds_ring *sds_ring; | 798 | struct qlcnic_host_sds_ring *sds_ring; |
666 | struct qlcnic_adapter *adapter; | 799 | struct qlcnic_adapter *adapter; |
667 | int tx_complete, work_done; | ||
668 | 800 | ||
669 | sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi); | 801 | sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi); |
670 | adapter = sds_ring->adapter; | 802 | adapter = sds_ring->adapter; |
671 | 803 | tx_complete = qlcnic_process_cmd_ring(adapter, adapter->tx_ring, | |
672 | tx_complete = qlcnic_process_cmd_ring(adapter); | 804 | budget); |
673 | work_done = qlcnic_process_rcv_ring(sds_ring, budget); | 805 | work_done = qlcnic_process_rcv_ring(sds_ring, budget); |
674 | |||
675 | if ((work_done < budget) && tx_complete) { | 806 | if ((work_done < budget) && tx_complete) { |
676 | napi_complete(&sds_ring->napi); | 807 | napi_complete(&sds_ring->napi); |
677 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) | 808 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) |
@@ -804,26 +935,23 @@ static void qlcnic_handle_fw_message(int desc_cnt, int index, | |||
804 | } | 935 | } |
805 | } | 936 | } |
806 | 937 | ||
807 | static struct sk_buff * | 938 | struct sk_buff *qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, |
808 | qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, | 939 | struct qlcnic_host_rds_ring *ring, |
809 | struct qlcnic_host_rds_ring *rds_ring, u16 index, | 940 | u16 index, u16 cksum) |
810 | u16 cksum) | ||
811 | { | 941 | { |
812 | struct qlcnic_rx_buffer *buffer; | 942 | struct qlcnic_rx_buffer *buffer; |
813 | struct sk_buff *skb; | 943 | struct sk_buff *skb; |
814 | 944 | ||
815 | buffer = &rds_ring->rx_buf_arr[index]; | 945 | buffer = &ring->rx_buf_arr[index]; |
816 | |||
817 | if (unlikely(buffer->skb == NULL)) { | 946 | if (unlikely(buffer->skb == NULL)) { |
818 | WARN_ON(1); | 947 | WARN_ON(1); |
819 | return NULL; | 948 | return NULL; |
820 | } | 949 | } |
821 | 950 | ||
822 | pci_unmap_single(adapter->pdev, buffer->dma, rds_ring->dma_size, | 951 | pci_unmap_single(adapter->pdev, buffer->dma, ring->dma_size, |
823 | PCI_DMA_FROMDEVICE); | 952 | PCI_DMA_FROMDEVICE); |
824 | 953 | ||
825 | skb = buffer->skb; | 954 | skb = buffer->skb; |
826 | |||
827 | if (likely((adapter->netdev->features & NETIF_F_RXCSUM) && | 955 | if (likely((adapter->netdev->features & NETIF_F_RXCSUM) && |
828 | (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) { | 956 | (cksum == STATUS_CKSUM_OK || cksum == STATUS_CKSUM_LOOP))) { |
829 | adapter->stats.csummed++; | 957 | adapter->stats.csummed++; |
@@ -832,6 +960,7 @@ qlcnic_process_rxbuf(struct qlcnic_adapter *adapter, | |||
832 | skb_checksum_none_assert(skb); | 960 | skb_checksum_none_assert(skb); |
833 | } | 961 | } |
834 | 962 | ||
963 | |||
835 | buffer->skb = NULL; | 964 | buffer->skb = NULL; |
836 | 965 | ||
837 | return skb; | 966 | return skb; |
@@ -871,8 +1000,8 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter, | |||
871 | struct qlcnic_rx_buffer *buffer; | 1000 | struct qlcnic_rx_buffer *buffer; |
872 | struct sk_buff *skb; | 1001 | struct sk_buff *skb; |
873 | struct qlcnic_host_rds_ring *rds_ring; | 1002 | struct qlcnic_host_rds_ring *rds_ring; |
874 | int index, length, cksum, pkt_offset; | 1003 | int index, length, cksum, pkt_offset, is_lb_pkt; |
875 | u16 vid = 0xffff; | 1004 | u16 vid = 0xffff, t_vid; |
876 | 1005 | ||
877 | if (unlikely(ring >= adapter->max_rds_rings)) | 1006 | if (unlikely(ring >= adapter->max_rds_rings)) |
878 | return NULL; | 1007 | return NULL; |
@@ -892,6 +1021,14 @@ qlcnic_process_rcv(struct qlcnic_adapter *adapter, | |||
892 | if (!skb) | 1021 | if (!skb) |
893 | return buffer; | 1022 | return buffer; |
894 | 1023 | ||
1024 | if (adapter->drv_mac_learn && | ||
1025 | (adapter->flags & QLCNIC_ESWITCH_ENABLED)) { | ||
1026 | t_vid = 0; | ||
1027 | is_lb_pkt = qlcnic_82xx_is_lb_pkt(sts_data0); | ||
1028 | qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, | ||
1029 | cpu_to_le16(t_vid)); | ||
1030 | } | ||
1031 | |||
895 | if (length > rds_ring->skb_size) | 1032 | if (length > rds_ring->skb_size) |
896 | skb_put(skb, rds_ring->skb_size); | 1033 | skb_put(skb, rds_ring->skb_size); |
897 | else | 1034 | else |
@@ -933,10 +1070,11 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, | |||
933 | struct sk_buff *skb; | 1070 | struct sk_buff *skb; |
934 | struct qlcnic_host_rds_ring *rds_ring; | 1071 | struct qlcnic_host_rds_ring *rds_ring; |
935 | struct iphdr *iph; | 1072 | struct iphdr *iph; |
1073 | struct ipv6hdr *ipv6h; | ||
936 | struct tcphdr *th; | 1074 | struct tcphdr *th; |
937 | bool push, timestamp; | 1075 | bool push, timestamp; |
938 | int index, l2_hdr_offset, l4_hdr_offset; | 1076 | int index, l2_hdr_offset, l4_hdr_offset, is_lb_pkt; |
939 | u16 lro_length, length, data_offset, vid = 0xffff; | 1077 | u16 lro_length, length, data_offset, t_vid, vid = 0xffff; |
940 | u32 seq_number; | 1078 | u32 seq_number; |
941 | 1079 | ||
942 | if (unlikely(ring > adapter->max_rds_rings)) | 1080 | if (unlikely(ring > adapter->max_rds_rings)) |
@@ -961,6 +1099,14 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, | |||
961 | if (!skb) | 1099 | if (!skb) |
962 | return buffer; | 1100 | return buffer; |
963 | 1101 | ||
1102 | if (adapter->drv_mac_learn && | ||
1103 | (adapter->flags & QLCNIC_ESWITCH_ENABLED)) { | ||
1104 | t_vid = 0; | ||
1105 | is_lb_pkt = qlcnic_82xx_is_lb_pkt(sts_data0); | ||
1106 | qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, | ||
1107 | cpu_to_le16(t_vid)); | ||
1108 | } | ||
1109 | |||
964 | if (timestamp) | 1110 | if (timestamp) |
965 | data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE; | 1111 | data_offset = l4_hdr_offset + QLC_TCP_TS_HDR_SIZE; |
966 | else | 1112 | else |
@@ -976,18 +1122,32 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, | |||
976 | } | 1122 | } |
977 | 1123 | ||
978 | skb->protocol = eth_type_trans(skb, netdev); | 1124 | skb->protocol = eth_type_trans(skb, netdev); |
979 | iph = (struct iphdr *)skb->data; | 1125 | |
980 | th = (struct tcphdr *)(skb->data + (iph->ihl << 2)); | 1126 | if (ntohs(skb->protocol) == ETH_P_IPV6) { |
981 | length = (iph->ihl << 2) + (th->doff << 2) + lro_length; | 1127 | ipv6h = (struct ipv6hdr *)skb->data; |
982 | iph->tot_len = htons(length); | 1128 | th = (struct tcphdr *)(skb->data + sizeof(struct ipv6hdr)); |
983 | iph->check = 0; | 1129 | length = (th->doff << 2) + lro_length; |
984 | iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); | 1130 | ipv6h->payload_len = htons(length); |
1131 | } else { | ||
1132 | iph = (struct iphdr *)skb->data; | ||
1133 | th = (struct tcphdr *)(skb->data + (iph->ihl << 2)); | ||
1134 | length = (iph->ihl << 2) + (th->doff << 2) + lro_length; | ||
1135 | iph->tot_len = htons(length); | ||
1136 | iph->check = 0; | ||
1137 | iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); | ||
1138 | } | ||
1139 | |||
985 | th->psh = push; | 1140 | th->psh = push; |
986 | th->seq = htonl(seq_number); | 1141 | th->seq = htonl(seq_number); |
987 | length = skb->len; | 1142 | length = skb->len; |
988 | 1143 | ||
989 | if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) | 1144 | if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) { |
990 | skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1); | 1145 | skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1); |
1146 | if (skb->protocol == htons(ETH_P_IPV6)) | ||
1147 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; | ||
1148 | else | ||
1149 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; | ||
1150 | } | ||
991 | 1151 | ||
992 | if (vid != 0xffff) | 1152 | if (vid != 0xffff) |
993 | __vlan_hwaccel_put_tag(skb, vid); | 1153 | __vlan_hwaccel_put_tag(skb, vid); |
@@ -1006,9 +1166,9 @@ int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max) | |||
1006 | struct list_head *cur; | 1166 | struct list_head *cur; |
1007 | struct status_desc *desc; | 1167 | struct status_desc *desc; |
1008 | struct qlcnic_rx_buffer *rxbuf; | 1168 | struct qlcnic_rx_buffer *rxbuf; |
1169 | int opcode, desc_cnt, count = 0; | ||
1009 | u64 sts_data0, sts_data1; | 1170 | u64 sts_data0, sts_data1; |
1010 | __le64 owner_phantom = cpu_to_le64(STATUS_OWNER_PHANTOM); | 1171 | u8 ring; |
1011 | int opcode, ring, desc_cnt, count = 0; | ||
1012 | u32 consumer = sds_ring->consumer; | 1172 | u32 consumer = sds_ring->consumer; |
1013 | 1173 | ||
1014 | while (count < max) { | 1174 | while (count < max) { |
@@ -1020,7 +1180,6 @@ int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max) | |||
1020 | 1180 | ||
1021 | desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0); | 1181 | desc_cnt = qlcnic_get_sts_desc_cnt(sts_data0); |
1022 | opcode = qlcnic_get_sts_opcode(sts_data0); | 1182 | opcode = qlcnic_get_sts_opcode(sts_data0); |
1023 | |||
1024 | switch (opcode) { | 1183 | switch (opcode) { |
1025 | case QLCNIC_RXPKT_DESC: | 1184 | case QLCNIC_RXPKT_DESC: |
1026 | case QLCNIC_OLD_RXPKT_DESC: | 1185 | case QLCNIC_OLD_RXPKT_DESC: |
@@ -1040,18 +1199,16 @@ int qlcnic_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, int max) | |||
1040 | default: | 1199 | default: |
1041 | goto skip; | 1200 | goto skip; |
1042 | } | 1201 | } |
1043 | |||
1044 | WARN_ON(desc_cnt > 1); | 1202 | WARN_ON(desc_cnt > 1); |
1045 | 1203 | ||
1046 | if (likely(rxbuf)) | 1204 | if (likely(rxbuf)) |
1047 | list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); | 1205 | list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); |
1048 | else | 1206 | else |
1049 | adapter->stats.null_rxbuf++; | 1207 | adapter->stats.null_rxbuf++; |
1050 | |||
1051 | skip: | 1208 | skip: |
1052 | for (; desc_cnt > 0; desc_cnt--) { | 1209 | for (; desc_cnt > 0; desc_cnt--) { |
1053 | desc = &sds_ring->desc_head[consumer]; | 1210 | desc = &sds_ring->desc_head[consumer]; |
1054 | desc->status_desc_data[0] = owner_phantom; | 1211 | desc->status_desc_data[0] = QLCNIC_DESC_OWNER_FW; |
1055 | consumer = get_next_index(consumer, sds_ring->num_desc); | 1212 | consumer = get_next_index(consumer, sds_ring->num_desc); |
1056 | } | 1213 | } |
1057 | count++; | 1214 | count++; |
@@ -1059,7 +1216,6 @@ skip: | |||
1059 | 1216 | ||
1060 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | 1217 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { |
1061 | rds_ring = &adapter->recv_ctx->rds_rings[ring]; | 1218 | rds_ring = &adapter->recv_ctx->rds_rings[ring]; |
1062 | |||
1063 | if (!list_empty(&sds_ring->free_list[ring])) { | 1219 | if (!list_empty(&sds_ring->free_list[ring])) { |
1064 | list_for_each(cur, &sds_ring->free_list[ring]) { | 1220 | list_for_each(cur, &sds_ring->free_list[ring]) { |
1065 | rxbuf = list_entry(cur, struct qlcnic_rx_buffer, | 1221 | rxbuf = list_entry(cur, struct qlcnic_rx_buffer, |
@@ -1072,7 +1228,7 @@ skip: | |||
1072 | spin_unlock(&rds_ring->lock); | 1228 | spin_unlock(&rds_ring->lock); |
1073 | } | 1229 | } |
1074 | 1230 | ||
1075 | qlcnic_post_rx_buffers_nodb(adapter, rds_ring); | 1231 | qlcnic_post_rx_buffers_nodb(adapter, rds_ring, ring); |
1076 | } | 1232 | } |
1077 | 1233 | ||
1078 | if (count) { | 1234 | if (count) { |
@@ -1084,12 +1240,12 @@ skip: | |||
1084 | } | 1240 | } |
1085 | 1241 | ||
1086 | void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, | 1242 | void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, |
1087 | struct qlcnic_host_rds_ring *rds_ring) | 1243 | struct qlcnic_host_rds_ring *rds_ring, u8 ring_id) |
1088 | { | 1244 | { |
1089 | struct rcv_desc *pdesc; | 1245 | struct rcv_desc *pdesc; |
1090 | struct qlcnic_rx_buffer *buffer; | 1246 | struct qlcnic_rx_buffer *buffer; |
1091 | int count = 0; | 1247 | int count = 0; |
1092 | u32 producer; | 1248 | u32 producer, handle; |
1093 | struct list_head *head; | 1249 | struct list_head *head; |
1094 | 1250 | ||
1095 | producer = rds_ring->producer; | 1251 | producer = rds_ring->producer; |
@@ -1110,7 +1266,9 @@ void qlcnic_post_rx_buffers(struct qlcnic_adapter *adapter, | |||
1110 | /* make a rcv descriptor */ | 1266 | /* make a rcv descriptor */ |
1111 | pdesc = &rds_ring->desc_head[producer]; | 1267 | pdesc = &rds_ring->desc_head[producer]; |
1112 | pdesc->addr_buffer = cpu_to_le64(buffer->dma); | 1268 | pdesc->addr_buffer = cpu_to_le64(buffer->dma); |
1113 | pdesc->reference_handle = cpu_to_le16(buffer->ref_handle); | 1269 | handle = qlcnic_get_ref_handle(adapter, buffer->ref_handle, |
1270 | ring_id); | ||
1271 | pdesc->reference_handle = cpu_to_le16(handle); | ||
1114 | pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); | 1272 | pdesc->buffer_length = cpu_to_le32(rds_ring->dma_size); |
1115 | producer = get_next_index(producer, rds_ring->num_desc); | 1273 | producer = get_next_index(producer, rds_ring->num_desc); |
1116 | } | 1274 | } |
@@ -1180,7 +1338,7 @@ static void qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, int ring, | |||
1180 | return; | 1338 | return; |
1181 | } | 1339 | } |
1182 | 1340 | ||
1183 | void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring) | 1341 | void qlcnic_82xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring) |
1184 | { | 1342 | { |
1185 | struct qlcnic_adapter *adapter = sds_ring->adapter; | 1343 | struct qlcnic_adapter *adapter = sds_ring->adapter; |
1186 | struct status_desc *desc; | 1344 | struct status_desc *desc; |
@@ -1217,26 +1375,8 @@ void qlcnic_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring) | |||
1217 | writel(consumer, sds_ring->crb_sts_consumer); | 1375 | writel(consumer, sds_ring->crb_sts_consumer); |
1218 | } | 1376 | } |
1219 | 1377 | ||
1220 | void qlcnic_fetch_mac(u32 off1, u32 off2, u8 alt_mac, u8 *mac) | 1378 | int qlcnic_82xx_napi_add(struct qlcnic_adapter *adapter, |
1221 | { | 1379 | struct net_device *netdev) |
1222 | u32 mac_low, mac_high; | ||
1223 | int i; | ||
1224 | |||
1225 | mac_low = off1; | ||
1226 | mac_high = off2; | ||
1227 | |||
1228 | if (alt_mac) { | ||
1229 | mac_low |= (mac_low >> 16) | (mac_high << 16); | ||
1230 | mac_high >>= 16; | ||
1231 | } | ||
1232 | |||
1233 | for (i = 0; i < 2; i++) | ||
1234 | mac[i] = (u8)(mac_high >> ((1 - i) * 8)); | ||
1235 | for (i = 2; i < 6; i++) | ||
1236 | mac[i] = (u8)(mac_low >> ((5 - i) * 8)); | ||
1237 | } | ||
1238 | |||
1239 | int qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev) | ||
1240 | { | 1380 | { |
1241 | int ring, max_sds_rings; | 1381 | int ring, max_sds_rings; |
1242 | struct qlcnic_host_sds_ring *sds_ring; | 1382 | struct qlcnic_host_sds_ring *sds_ring; |
@@ -1249,8 +1389,7 @@ int qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev) | |||
1249 | 1389 | ||
1250 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | 1390 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
1251 | sds_ring = &recv_ctx->sds_rings[ring]; | 1391 | sds_ring = &recv_ctx->sds_rings[ring]; |
1252 | 1392 | if (ring == adapter->max_sds_rings - 1) | |
1253 | if (ring == max_sds_rings - 1) | ||
1254 | netif_napi_add(netdev, &sds_ring->napi, qlcnic_poll, | 1393 | netif_napi_add(netdev, &sds_ring->napi, qlcnic_poll, |
1255 | QLCNIC_NETDEV_WEIGHT / max_sds_rings); | 1394 | QLCNIC_NETDEV_WEIGHT / max_sds_rings); |
1256 | else | 1395 | else |
@@ -1258,10 +1397,15 @@ int qlcnic_napi_add(struct qlcnic_adapter *adapter, struct net_device *netdev) | |||
1258 | QLCNIC_NETDEV_WEIGHT*2); | 1397 | QLCNIC_NETDEV_WEIGHT*2); |
1259 | } | 1398 | } |
1260 | 1399 | ||
1400 | if (qlcnic_alloc_tx_rings(adapter, netdev)) { | ||
1401 | qlcnic_free_sds_rings(recv_ctx); | ||
1402 | return -ENOMEM; | ||
1403 | } | ||
1404 | |||
1261 | return 0; | 1405 | return 0; |
1262 | } | 1406 | } |
1263 | 1407 | ||
1264 | void qlcnic_napi_del(struct qlcnic_adapter *adapter) | 1408 | void qlcnic_82xx_napi_del(struct qlcnic_adapter *adapter) |
1265 | { | 1409 | { |
1266 | int ring; | 1410 | int ring; |
1267 | struct qlcnic_host_sds_ring *sds_ring; | 1411 | struct qlcnic_host_sds_ring *sds_ring; |
@@ -1273,9 +1417,10 @@ void qlcnic_napi_del(struct qlcnic_adapter *adapter) | |||
1273 | } | 1417 | } |
1274 | 1418 | ||
1275 | qlcnic_free_sds_rings(adapter->recv_ctx); | 1419 | qlcnic_free_sds_rings(adapter->recv_ctx); |
1420 | qlcnic_free_tx_rings(adapter); | ||
1276 | } | 1421 | } |
1277 | 1422 | ||
1278 | void qlcnic_napi_enable(struct qlcnic_adapter *adapter) | 1423 | void qlcnic_82xx_napi_enable(struct qlcnic_adapter *adapter) |
1279 | { | 1424 | { |
1280 | int ring; | 1425 | int ring; |
1281 | struct qlcnic_host_sds_ring *sds_ring; | 1426 | struct qlcnic_host_sds_ring *sds_ring; |
@@ -1291,7 +1436,7 @@ void qlcnic_napi_enable(struct qlcnic_adapter *adapter) | |||
1291 | } | 1436 | } |
1292 | } | 1437 | } |
1293 | 1438 | ||
1294 | void qlcnic_napi_disable(struct qlcnic_adapter *adapter) | 1439 | void qlcnic_82xx_napi_disable(struct qlcnic_adapter *adapter) |
1295 | { | 1440 | { |
1296 | int ring; | 1441 | int ring; |
1297 | struct qlcnic_host_sds_ring *sds_ring; | 1442 | struct qlcnic_host_sds_ring *sds_ring; |
@@ -1307,3 +1452,481 @@ void qlcnic_napi_disable(struct qlcnic_adapter *adapter) | |||
1307 | napi_disable(&sds_ring->napi); | 1452 | napi_disable(&sds_ring->napi); |
1308 | } | 1453 | } |
1309 | } | 1454 | } |
1455 | |||
1456 | #define QLC_83XX_NORMAL_LB_PKT (1ULL << 36) | ||
1457 | #define QLC_83XX_LRO_LB_PKT (1ULL << 46) | ||
1458 | |||
1459 | static inline int qlcnic_83xx_is_lb_pkt(u64 sts_data, int lro_pkt) | ||
1460 | { | ||
1461 | if (lro_pkt) | ||
1462 | return (sts_data & QLC_83XX_LRO_LB_PKT) ? 1 : 0; | ||
1463 | else | ||
1464 | return (sts_data & QLC_83XX_NORMAL_LB_PKT) ? 1 : 0; | ||
1465 | } | ||
1466 | |||
1467 | static struct qlcnic_rx_buffer * | ||
1468 | qlcnic_83xx_process_rcv(struct qlcnic_adapter *adapter, | ||
1469 | struct qlcnic_host_sds_ring *sds_ring, | ||
1470 | u8 ring, u64 sts_data[]) | ||
1471 | { | ||
1472 | struct net_device *netdev = adapter->netdev; | ||
1473 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
1474 | struct qlcnic_rx_buffer *buffer; | ||
1475 | struct sk_buff *skb; | ||
1476 | struct qlcnic_host_rds_ring *rds_ring; | ||
1477 | int index, length, cksum, is_lb_pkt; | ||
1478 | u16 vid = 0xffff, t_vid; | ||
1479 | |||
1480 | if (unlikely(ring >= adapter->max_rds_rings)) | ||
1481 | return NULL; | ||
1482 | |||
1483 | rds_ring = &recv_ctx->rds_rings[ring]; | ||
1484 | |||
1485 | index = qlcnic_83xx_hndl(sts_data[0]); | ||
1486 | if (unlikely(index >= rds_ring->num_desc)) | ||
1487 | return NULL; | ||
1488 | |||
1489 | buffer = &rds_ring->rx_buf_arr[index]; | ||
1490 | length = qlcnic_83xx_pktln(sts_data[0]); | ||
1491 | cksum = qlcnic_83xx_csum_status(sts_data[1]); | ||
1492 | skb = qlcnic_process_rxbuf(adapter, rds_ring, index, cksum); | ||
1493 | if (!skb) | ||
1494 | return buffer; | ||
1495 | |||
1496 | if (adapter->drv_mac_learn && | ||
1497 | (adapter->flags & QLCNIC_ESWITCH_ENABLED)) { | ||
1498 | t_vid = 0; | ||
1499 | is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 0); | ||
1500 | qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, | ||
1501 | cpu_to_le16(t_vid)); | ||
1502 | } | ||
1503 | |||
1504 | if (length > rds_ring->skb_size) | ||
1505 | skb_put(skb, rds_ring->skb_size); | ||
1506 | else | ||
1507 | skb_put(skb, length); | ||
1508 | |||
1509 | if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) { | ||
1510 | adapter->stats.rxdropped++; | ||
1511 | dev_kfree_skb(skb); | ||
1512 | return buffer; | ||
1513 | } | ||
1514 | |||
1515 | skb->protocol = eth_type_trans(skb, netdev); | ||
1516 | |||
1517 | if (vid != 0xffff) | ||
1518 | __vlan_hwaccel_put_tag(skb, vid); | ||
1519 | |||
1520 | napi_gro_receive(&sds_ring->napi, skb); | ||
1521 | |||
1522 | adapter->stats.rx_pkts++; | ||
1523 | adapter->stats.rxbytes += length; | ||
1524 | |||
1525 | return buffer; | ||
1526 | } | ||
1527 | |||
1528 | static struct qlcnic_rx_buffer * | ||
1529 | qlcnic_83xx_process_lro(struct qlcnic_adapter *adapter, | ||
1530 | u8 ring, u64 sts_data[]) | ||
1531 | { | ||
1532 | struct net_device *netdev = adapter->netdev; | ||
1533 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
1534 | struct qlcnic_rx_buffer *buffer; | ||
1535 | struct sk_buff *skb; | ||
1536 | struct qlcnic_host_rds_ring *rds_ring; | ||
1537 | struct iphdr *iph; | ||
1538 | struct ipv6hdr *ipv6h; | ||
1539 | struct tcphdr *th; | ||
1540 | bool push; | ||
1541 | int l2_hdr_offset, l4_hdr_offset; | ||
1542 | int index, is_lb_pkt; | ||
1543 | u16 lro_length, length, data_offset, gso_size; | ||
1544 | u16 vid = 0xffff, t_vid; | ||
1545 | |||
1546 | if (unlikely(ring > adapter->max_rds_rings)) | ||
1547 | return NULL; | ||
1548 | |||
1549 | rds_ring = &recv_ctx->rds_rings[ring]; | ||
1550 | |||
1551 | index = qlcnic_83xx_hndl(sts_data[0]); | ||
1552 | if (unlikely(index > rds_ring->num_desc)) | ||
1553 | return NULL; | ||
1554 | |||
1555 | buffer = &rds_ring->rx_buf_arr[index]; | ||
1556 | |||
1557 | lro_length = qlcnic_83xx_lro_pktln(sts_data[0]); | ||
1558 | l2_hdr_offset = qlcnic_83xx_l2_hdr_off(sts_data[1]); | ||
1559 | l4_hdr_offset = qlcnic_83xx_l4_hdr_off(sts_data[1]); | ||
1560 | push = qlcnic_83xx_is_psh_bit(sts_data[1]); | ||
1561 | |||
1562 | skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK); | ||
1563 | if (!skb) | ||
1564 | return buffer; | ||
1565 | |||
1566 | if (adapter->drv_mac_learn && | ||
1567 | (adapter->flags & QLCNIC_ESWITCH_ENABLED)) { | ||
1568 | t_vid = 0; | ||
1569 | is_lb_pkt = qlcnic_83xx_is_lb_pkt(sts_data[1], 1); | ||
1570 | qlcnic_add_lb_filter(adapter, skb, is_lb_pkt, | ||
1571 | cpu_to_le16(t_vid)); | ||
1572 | } | ||
1573 | if (qlcnic_83xx_is_tstamp(sts_data[1])) | ||
1574 | data_offset = l4_hdr_offset + QLCNIC_TCP_TS_HDR_SIZE; | ||
1575 | else | ||
1576 | data_offset = l4_hdr_offset + QLCNIC_TCP_HDR_SIZE; | ||
1577 | |||
1578 | skb_put(skb, lro_length + data_offset); | ||
1579 | skb_pull(skb, l2_hdr_offset); | ||
1580 | |||
1581 | if (unlikely(qlcnic_check_rx_tagging(adapter, skb, &vid))) { | ||
1582 | adapter->stats.rxdropped++; | ||
1583 | dev_kfree_skb(skb); | ||
1584 | return buffer; | ||
1585 | } | ||
1586 | |||
1587 | skb->protocol = eth_type_trans(skb, netdev); | ||
1588 | if (ntohs(skb->protocol) == ETH_P_IPV6) { | ||
1589 | ipv6h = (struct ipv6hdr *)skb->data; | ||
1590 | th = (struct tcphdr *)(skb->data + sizeof(struct ipv6hdr)); | ||
1591 | |||
1592 | length = (th->doff << 2) + lro_length; | ||
1593 | ipv6h->payload_len = htons(length); | ||
1594 | } else { | ||
1595 | iph = (struct iphdr *)skb->data; | ||
1596 | th = (struct tcphdr *)(skb->data + (iph->ihl << 2)); | ||
1597 | length = (iph->ihl << 2) + (th->doff << 2) + lro_length; | ||
1598 | iph->tot_len = htons(length); | ||
1599 | iph->check = 0; | ||
1600 | iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); | ||
1601 | } | ||
1602 | |||
1603 | th->psh = push; | ||
1604 | length = skb->len; | ||
1605 | |||
1606 | if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) { | ||
1607 | gso_size = qlcnic_83xx_get_lro_sts_mss(sts_data[0]); | ||
1608 | skb_shinfo(skb)->gso_size = gso_size; | ||
1609 | if (skb->protocol == htons(ETH_P_IPV6)) | ||
1610 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; | ||
1611 | else | ||
1612 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; | ||
1613 | } | ||
1614 | |||
1615 | if (vid != 0xffff) | ||
1616 | __vlan_hwaccel_put_tag(skb, vid); | ||
1617 | |||
1618 | netif_receive_skb(skb); | ||
1619 | |||
1620 | adapter->stats.lro_pkts++; | ||
1621 | adapter->stats.lrobytes += length; | ||
1622 | return buffer; | ||
1623 | } | ||
1624 | |||
1625 | static int qlcnic_83xx_process_rcv_ring(struct qlcnic_host_sds_ring *sds_ring, | ||
1626 | int max) | ||
1627 | { | ||
1628 | struct qlcnic_host_rds_ring *rds_ring; | ||
1629 | struct qlcnic_adapter *adapter = sds_ring->adapter; | ||
1630 | struct list_head *cur; | ||
1631 | struct status_desc *desc; | ||
1632 | struct qlcnic_rx_buffer *rxbuf = NULL; | ||
1633 | u8 ring; | ||
1634 | u64 sts_data[2]; | ||
1635 | int count = 0, opcode; | ||
1636 | u32 consumer = sds_ring->consumer; | ||
1637 | |||
1638 | while (count < max) { | ||
1639 | desc = &sds_ring->desc_head[consumer]; | ||
1640 | sts_data[1] = le64_to_cpu(desc->status_desc_data[1]); | ||
1641 | opcode = qlcnic_83xx_opcode(sts_data[1]); | ||
1642 | if (!opcode) | ||
1643 | break; | ||
1644 | sts_data[0] = le64_to_cpu(desc->status_desc_data[0]); | ||
1645 | ring = QLCNIC_FETCH_RING_ID(sts_data[0]); | ||
1646 | |||
1647 | switch (opcode) { | ||
1648 | case QLC_83XX_REG_DESC: | ||
1649 | rxbuf = qlcnic_83xx_process_rcv(adapter, sds_ring, | ||
1650 | ring, sts_data); | ||
1651 | break; | ||
1652 | case QLC_83XX_LRO_DESC: | ||
1653 | rxbuf = qlcnic_83xx_process_lro(adapter, ring, | ||
1654 | sts_data); | ||
1655 | break; | ||
1656 | default: | ||
1657 | dev_info(&adapter->pdev->dev, | ||
1658 | "Unkonwn opcode: 0x%x\n", opcode); | ||
1659 | goto skip; | ||
1660 | } | ||
1661 | |||
1662 | if (likely(rxbuf)) | ||
1663 | list_add_tail(&rxbuf->list, &sds_ring->free_list[ring]); | ||
1664 | else | ||
1665 | adapter->stats.null_rxbuf++; | ||
1666 | skip: | ||
1667 | desc = &sds_ring->desc_head[consumer]; | ||
1668 | /* Reset the descriptor */ | ||
1669 | desc->status_desc_data[1] = 0; | ||
1670 | consumer = get_next_index(consumer, sds_ring->num_desc); | ||
1671 | count++; | ||
1672 | } | ||
1673 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | ||
1674 | rds_ring = &adapter->recv_ctx->rds_rings[ring]; | ||
1675 | if (!list_empty(&sds_ring->free_list[ring])) { | ||
1676 | list_for_each(cur, &sds_ring->free_list[ring]) { | ||
1677 | rxbuf = list_entry(cur, struct qlcnic_rx_buffer, | ||
1678 | list); | ||
1679 | qlcnic_alloc_rx_skb(adapter, rds_ring, rxbuf); | ||
1680 | } | ||
1681 | spin_lock(&rds_ring->lock); | ||
1682 | list_splice_tail_init(&sds_ring->free_list[ring], | ||
1683 | &rds_ring->free_list); | ||
1684 | spin_unlock(&rds_ring->lock); | ||
1685 | } | ||
1686 | qlcnic_post_rx_buffers_nodb(adapter, rds_ring, ring); | ||
1687 | } | ||
1688 | if (count) { | ||
1689 | sds_ring->consumer = consumer; | ||
1690 | writel(consumer, sds_ring->crb_sts_consumer); | ||
1691 | } | ||
1692 | return count; | ||
1693 | } | ||
1694 | |||
1695 | static int qlcnic_83xx_poll(struct napi_struct *napi, int budget) | ||
1696 | { | ||
1697 | int tx_complete; | ||
1698 | int work_done; | ||
1699 | struct qlcnic_host_sds_ring *sds_ring; | ||
1700 | struct qlcnic_adapter *adapter; | ||
1701 | struct qlcnic_host_tx_ring *tx_ring; | ||
1702 | |||
1703 | sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi); | ||
1704 | adapter = sds_ring->adapter; | ||
1705 | /* tx ring count = 1 */ | ||
1706 | tx_ring = adapter->tx_ring; | ||
1707 | |||
1708 | tx_complete = qlcnic_process_cmd_ring(adapter, tx_ring, budget); | ||
1709 | work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget); | ||
1710 | if ((work_done < budget) && tx_complete) { | ||
1711 | napi_complete(&sds_ring->napi); | ||
1712 | qlcnic_83xx_enable_intr(adapter, sds_ring); | ||
1713 | } | ||
1714 | |||
1715 | return work_done; | ||
1716 | } | ||
1717 | |||
1718 | static int qlcnic_83xx_msix_tx_poll(struct napi_struct *napi, int budget) | ||
1719 | { | ||
1720 | int work_done; | ||
1721 | struct qlcnic_host_tx_ring *tx_ring; | ||
1722 | struct qlcnic_adapter *adapter; | ||
1723 | |||
1724 | budget = QLCNIC_TX_POLL_BUDGET; | ||
1725 | tx_ring = container_of(napi, struct qlcnic_host_tx_ring, napi); | ||
1726 | adapter = tx_ring->adapter; | ||
1727 | work_done = qlcnic_process_cmd_ring(adapter, tx_ring, budget); | ||
1728 | if (work_done) { | ||
1729 | napi_complete(&tx_ring->napi); | ||
1730 | if (test_bit(__QLCNIC_DEV_UP , &adapter->state)) | ||
1731 | qlcnic_83xx_enable_tx_intr(adapter, tx_ring); | ||
1732 | } | ||
1733 | |||
1734 | return work_done; | ||
1735 | } | ||
1736 | |||
1737 | static int qlcnic_83xx_rx_poll(struct napi_struct *napi, int budget) | ||
1738 | { | ||
1739 | int work_done; | ||
1740 | struct qlcnic_host_sds_ring *sds_ring; | ||
1741 | struct qlcnic_adapter *adapter; | ||
1742 | |||
1743 | sds_ring = container_of(napi, struct qlcnic_host_sds_ring, napi); | ||
1744 | adapter = sds_ring->adapter; | ||
1745 | work_done = qlcnic_83xx_process_rcv_ring(sds_ring, budget); | ||
1746 | if (work_done < budget) { | ||
1747 | napi_complete(&sds_ring->napi); | ||
1748 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) | ||
1749 | qlcnic_83xx_enable_intr(adapter, sds_ring); | ||
1750 | } | ||
1751 | |||
1752 | return work_done; | ||
1753 | } | ||
1754 | |||
1755 | void qlcnic_83xx_napi_enable(struct qlcnic_adapter *adapter) | ||
1756 | { | ||
1757 | int ring; | ||
1758 | struct qlcnic_host_sds_ring *sds_ring; | ||
1759 | struct qlcnic_host_tx_ring *tx_ring; | ||
1760 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
1761 | |||
1762 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) | ||
1763 | return; | ||
1764 | |||
1765 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | ||
1766 | sds_ring = &recv_ctx->sds_rings[ring]; | ||
1767 | napi_enable(&sds_ring->napi); | ||
1768 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
1769 | qlcnic_83xx_enable_intr(adapter, sds_ring); | ||
1770 | } | ||
1771 | |||
1772 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { | ||
1773 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | ||
1774 | tx_ring = &adapter->tx_ring[ring]; | ||
1775 | napi_enable(&tx_ring->napi); | ||
1776 | qlcnic_83xx_enable_tx_intr(adapter, tx_ring); | ||
1777 | } | ||
1778 | } | ||
1779 | } | ||
1780 | |||
1781 | void qlcnic_83xx_napi_disable(struct qlcnic_adapter *adapter) | ||
1782 | { | ||
1783 | int ring; | ||
1784 | struct qlcnic_host_sds_ring *sds_ring; | ||
1785 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
1786 | struct qlcnic_host_tx_ring *tx_ring; | ||
1787 | |||
1788 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) | ||
1789 | return; | ||
1790 | |||
1791 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | ||
1792 | sds_ring = &recv_ctx->sds_rings[ring]; | ||
1793 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
1794 | qlcnic_83xx_disable_intr(adapter, sds_ring); | ||
1795 | napi_synchronize(&sds_ring->napi); | ||
1796 | napi_disable(&sds_ring->napi); | ||
1797 | } | ||
1798 | |||
1799 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { | ||
1800 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | ||
1801 | tx_ring = &adapter->tx_ring[ring]; | ||
1802 | qlcnic_83xx_disable_tx_intr(adapter, tx_ring); | ||
1803 | napi_synchronize(&tx_ring->napi); | ||
1804 | napi_disable(&tx_ring->napi); | ||
1805 | } | ||
1806 | } | ||
1807 | } | ||
1808 | |||
1809 | int qlcnic_83xx_napi_add(struct qlcnic_adapter *adapter, | ||
1810 | struct net_device *netdev) | ||
1811 | { | ||
1812 | int ring, max_sds_rings; | ||
1813 | struct qlcnic_host_sds_ring *sds_ring; | ||
1814 | struct qlcnic_host_tx_ring *tx_ring; | ||
1815 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
1816 | |||
1817 | if (qlcnic_alloc_sds_rings(recv_ctx, adapter->max_sds_rings)) | ||
1818 | return -ENOMEM; | ||
1819 | |||
1820 | max_sds_rings = adapter->max_sds_rings; | ||
1821 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | ||
1822 | sds_ring = &recv_ctx->sds_rings[ring]; | ||
1823 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | ||
1824 | netif_napi_add(netdev, &sds_ring->napi, | ||
1825 | qlcnic_83xx_rx_poll, | ||
1826 | QLCNIC_NETDEV_WEIGHT * 2); | ||
1827 | else | ||
1828 | netif_napi_add(netdev, &sds_ring->napi, | ||
1829 | qlcnic_83xx_poll, | ||
1830 | QLCNIC_NETDEV_WEIGHT / max_sds_rings); | ||
1831 | } | ||
1832 | |||
1833 | if (qlcnic_alloc_tx_rings(adapter, netdev)) { | ||
1834 | qlcnic_free_sds_rings(recv_ctx); | ||
1835 | return -ENOMEM; | ||
1836 | } | ||
1837 | |||
1838 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { | ||
1839 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | ||
1840 | tx_ring = &adapter->tx_ring[ring]; | ||
1841 | netif_napi_add(netdev, &tx_ring->napi, | ||
1842 | qlcnic_83xx_msix_tx_poll, | ||
1843 | QLCNIC_NETDEV_WEIGHT); | ||
1844 | } | ||
1845 | } | ||
1846 | |||
1847 | return 0; | ||
1848 | } | ||
1849 | |||
1850 | void qlcnic_83xx_napi_del(struct qlcnic_adapter *adapter) | ||
1851 | { | ||
1852 | int ring; | ||
1853 | struct qlcnic_host_sds_ring *sds_ring; | ||
1854 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
1855 | struct qlcnic_host_tx_ring *tx_ring; | ||
1856 | |||
1857 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | ||
1858 | sds_ring = &recv_ctx->sds_rings[ring]; | ||
1859 | netif_napi_del(&sds_ring->napi); | ||
1860 | } | ||
1861 | |||
1862 | qlcnic_free_sds_rings(adapter->recv_ctx); | ||
1863 | |||
1864 | if ((adapter->flags & QLCNIC_MSIX_ENABLED)) { | ||
1865 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | ||
1866 | tx_ring = &adapter->tx_ring[ring]; | ||
1867 | netif_napi_del(&tx_ring->napi); | ||
1868 | } | ||
1869 | } | ||
1870 | |||
1871 | qlcnic_free_tx_rings(adapter); | ||
1872 | } | ||
1873 | |||
1874 | void qlcnic_83xx_process_rcv_diag(struct qlcnic_adapter *adapter, | ||
1875 | int ring, u64 sts_data[]) | ||
1876 | { | ||
1877 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | ||
1878 | struct sk_buff *skb; | ||
1879 | struct qlcnic_host_rds_ring *rds_ring; | ||
1880 | int index, length; | ||
1881 | |||
1882 | if (unlikely(ring >= adapter->max_rds_rings)) | ||
1883 | return; | ||
1884 | |||
1885 | rds_ring = &recv_ctx->rds_rings[ring]; | ||
1886 | index = qlcnic_83xx_hndl(sts_data[0]); | ||
1887 | if (unlikely(index >= rds_ring->num_desc)) | ||
1888 | return; | ||
1889 | |||
1890 | length = qlcnic_83xx_pktln(sts_data[0]); | ||
1891 | |||
1892 | skb = qlcnic_process_rxbuf(adapter, rds_ring, index, STATUS_CKSUM_OK); | ||
1893 | if (!skb) | ||
1894 | return; | ||
1895 | |||
1896 | if (length > rds_ring->skb_size) | ||
1897 | skb_put(skb, rds_ring->skb_size); | ||
1898 | else | ||
1899 | skb_put(skb, length); | ||
1900 | |||
1901 | if (!qlcnic_check_loopback_buff(skb->data, adapter->mac_addr)) | ||
1902 | adapter->ahw->diag_cnt++; | ||
1903 | else | ||
1904 | dump_skb(skb, adapter); | ||
1905 | |||
1906 | dev_kfree_skb_any(skb); | ||
1907 | return; | ||
1908 | } | ||
1909 | |||
1910 | void qlcnic_83xx_process_rcv_ring_diag(struct qlcnic_host_sds_ring *sds_ring) | ||
1911 | { | ||
1912 | struct qlcnic_adapter *adapter = sds_ring->adapter; | ||
1913 | struct status_desc *desc; | ||
1914 | u64 sts_data[2]; | ||
1915 | int ring, opcode; | ||
1916 | u32 consumer = sds_ring->consumer; | ||
1917 | |||
1918 | desc = &sds_ring->desc_head[consumer]; | ||
1919 | sts_data[0] = le64_to_cpu(desc->status_desc_data[0]); | ||
1920 | sts_data[1] = le64_to_cpu(desc->status_desc_data[1]); | ||
1921 | opcode = qlcnic_83xx_opcode(sts_data[1]); | ||
1922 | if (!opcode) | ||
1923 | return; | ||
1924 | |||
1925 | ring = QLCNIC_FETCH_RING_ID(qlcnic_83xx_hndl(sts_data[0])); | ||
1926 | qlcnic_83xx_process_rcv_diag(adapter, ring, sts_data); | ||
1927 | desc = &sds_ring->desc_head[consumer]; | ||
1928 | desc->status_desc_data[0] = cpu_to_le64(STATUS_OWNER_PHANTOM); | ||
1929 | consumer = get_next_index(consumer, sds_ring->num_desc); | ||
1930 | sds_ring->consumer = consumer; | ||
1931 | writel(consumer, sds_ring->crb_sts_consumer); | ||
1932 | } | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index d833f5927891..28a6d4838364 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | |||
@@ -1,24 +1,25 @@ | |||
1 | /* | 1 | /* |
2 | * QLogic qlcnic NIC Driver | 2 | * QLogic qlcnic NIC Driver |
3 | * Copyright (c) 2009-2010 QLogic Corporation | 3 | * Copyright (c) 2009-2013 QLogic Corporation |
4 | * | 4 | * |
5 | * See LICENSE.qlcnic for copyright and licensing details. | 5 | * See LICENSE.qlcnic for copyright and licensing details. |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/slab.h> | ||
9 | #include <linux/vmalloc.h> | 8 | #include <linux/vmalloc.h> |
10 | #include <linux/interrupt.h> | 9 | #include <linux/interrupt.h> |
11 | 10 | ||
12 | #include "qlcnic.h" | 11 | #include "qlcnic.h" |
12 | #include "qlcnic_hw.h" | ||
13 | 13 | ||
14 | #include <linux/swab.h> | 14 | #include <linux/swab.h> |
15 | #include <linux/dma-mapping.h> | 15 | #include <linux/dma-mapping.h> |
16 | #include <linux/if_vlan.h> | ||
16 | #include <net/ip.h> | 17 | #include <net/ip.h> |
17 | #include <linux/ipv6.h> | 18 | #include <linux/ipv6.h> |
18 | #include <linux/inetdevice.h> | 19 | #include <linux/inetdevice.h> |
19 | #include <linux/sysfs.h> | ||
20 | #include <linux/aer.h> | 20 | #include <linux/aer.h> |
21 | #include <linux/log2.h> | 21 | #include <linux/log2.h> |
22 | #include <linux/pci.h> | ||
22 | 23 | ||
23 | MODULE_DESCRIPTION("QLogic 1/10 GbE Converged/Intelligent Ethernet Driver"); | 24 | MODULE_DESCRIPTION("QLogic 1/10 GbE Converged/Intelligent Ethernet Driver"); |
24 | MODULE_LICENSE("GPL"); | 25 | MODULE_LICENSE("GPL"); |
@@ -29,28 +30,28 @@ char qlcnic_driver_name[] = "qlcnic"; | |||
29 | static const char qlcnic_driver_string[] = "QLogic 1/10 GbE " | 30 | static const char qlcnic_driver_string[] = "QLogic 1/10 GbE " |
30 | "Converged/Intelligent Ethernet Driver v" QLCNIC_LINUX_VERSIONID; | 31 | "Converged/Intelligent Ethernet Driver v" QLCNIC_LINUX_VERSIONID; |
31 | 32 | ||
32 | static struct workqueue_struct *qlcnic_wq; | ||
33 | static int qlcnic_mac_learn; | 33 | static int qlcnic_mac_learn; |
34 | module_param(qlcnic_mac_learn, int, 0444); | 34 | module_param(qlcnic_mac_learn, int, 0444); |
35 | MODULE_PARM_DESC(qlcnic_mac_learn, "Mac Filter (0=disabled, 1=enabled)"); | 35 | MODULE_PARM_DESC(qlcnic_mac_learn, |
36 | "Mac Filter (0=learning is disabled, 1=Driver learning is enabled, 2=FDB learning is enabled)"); | ||
36 | 37 | ||
37 | static int qlcnic_use_msi = 1; | 38 | int qlcnic_use_msi = 1; |
38 | MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled"); | 39 | MODULE_PARM_DESC(use_msi, "MSI interrupt (0=disabled, 1=enabled"); |
39 | module_param_named(use_msi, qlcnic_use_msi, int, 0444); | 40 | module_param_named(use_msi, qlcnic_use_msi, int, 0444); |
40 | 41 | ||
41 | static int qlcnic_use_msi_x = 1; | 42 | int qlcnic_use_msi_x = 1; |
42 | MODULE_PARM_DESC(use_msi_x, "MSI-X interrupt (0=disabled, 1=enabled"); | 43 | MODULE_PARM_DESC(use_msi_x, "MSI-X interrupt (0=disabled, 1=enabled"); |
43 | module_param_named(use_msi_x, qlcnic_use_msi_x, int, 0444); | 44 | module_param_named(use_msi_x, qlcnic_use_msi_x, int, 0444); |
44 | 45 | ||
45 | static int qlcnic_auto_fw_reset = 1; | 46 | int qlcnic_auto_fw_reset = 1; |
46 | MODULE_PARM_DESC(auto_fw_reset, "Auto firmware reset (0=disabled, 1=enabled"); | 47 | MODULE_PARM_DESC(auto_fw_reset, "Auto firmware reset (0=disabled, 1=enabled"); |
47 | module_param_named(auto_fw_reset, qlcnic_auto_fw_reset, int, 0644); | 48 | module_param_named(auto_fw_reset, qlcnic_auto_fw_reset, int, 0644); |
48 | 49 | ||
49 | static int qlcnic_load_fw_file; | 50 | int qlcnic_load_fw_file; |
50 | MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file"); | 51 | MODULE_PARM_DESC(load_fw_file, "Load firmware from (0=flash, 1=file"); |
51 | module_param_named(load_fw_file, qlcnic_load_fw_file, int, 0444); | 52 | module_param_named(load_fw_file, qlcnic_load_fw_file, int, 0444); |
52 | 53 | ||
53 | static int qlcnic_config_npars; | 54 | int qlcnic_config_npars; |
54 | module_param(qlcnic_config_npars, int, 0444); | 55 | module_param(qlcnic_config_npars, int, 0444); |
55 | MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled"); | 56 | MODULE_PARM_DESC(qlcnic_config_npars, "Configure NPARs (0=disabled, 1=enabled"); |
56 | 57 | ||
@@ -62,9 +63,6 @@ static void qlcnic_tx_timeout(struct net_device *netdev); | |||
62 | static void qlcnic_attach_work(struct work_struct *work); | 63 | static void qlcnic_attach_work(struct work_struct *work); |
63 | static void qlcnic_fwinit_work(struct work_struct *work); | 64 | static void qlcnic_fwinit_work(struct work_struct *work); |
64 | static void qlcnic_fw_poll_work(struct work_struct *work); | 65 | static void qlcnic_fw_poll_work(struct work_struct *work); |
65 | static void qlcnic_schedule_work(struct qlcnic_adapter *adapter, | ||
66 | work_func_t func, int delay); | ||
67 | static void qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter); | ||
68 | #ifdef CONFIG_NET_POLL_CONTROLLER | 66 | #ifdef CONFIG_NET_POLL_CONTROLLER |
69 | static void qlcnic_poll_controller(struct net_device *netdev); | 67 | static void qlcnic_poll_controller(struct net_device *netdev); |
70 | #endif | 68 | #endif |
@@ -77,9 +75,9 @@ static irqreturn_t qlcnic_tmp_intr(int irq, void *data); | |||
77 | static irqreturn_t qlcnic_intr(int irq, void *data); | 75 | static irqreturn_t qlcnic_intr(int irq, void *data); |
78 | static irqreturn_t qlcnic_msi_intr(int irq, void *data); | 76 | static irqreturn_t qlcnic_msi_intr(int irq, void *data); |
79 | static irqreturn_t qlcnic_msix_intr(int irq, void *data); | 77 | static irqreturn_t qlcnic_msix_intr(int irq, void *data); |
78 | static irqreturn_t qlcnic_msix_tx_intr(int irq, void *data); | ||
80 | 79 | ||
81 | static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev); | 80 | static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev); |
82 | static void qlcnic_restore_indev_addr(struct net_device *dev, unsigned long); | ||
83 | static int qlcnic_start_firmware(struct qlcnic_adapter *); | 81 | static int qlcnic_start_firmware(struct qlcnic_adapter *); |
84 | 82 | ||
85 | static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter); | 83 | static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter); |
@@ -93,15 +91,24 @@ static int qlcnic_vlan_rx_del(struct net_device *, u16); | |||
93 | #define QLCNIC_IS_TSO_CAPABLE(adapter) \ | 91 | #define QLCNIC_IS_TSO_CAPABLE(adapter) \ |
94 | ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) | 92 | ((adapter)->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) |
95 | 93 | ||
94 | static u32 qlcnic_vlan_tx_check(struct qlcnic_adapter *adapter) | ||
95 | { | ||
96 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
97 | |||
98 | if (adapter->pdev->device == PCI_DEVICE_ID_QLOGIC_QLE824X) | ||
99 | return ahw->capabilities & QLCNIC_FW_CAPABILITY_FVLANTX; | ||
100 | else | ||
101 | return 1; | ||
102 | } | ||
103 | |||
96 | /* PCI Device ID Table */ | 104 | /* PCI Device ID Table */ |
97 | #define ENTRY(device) \ | 105 | #define ENTRY(device) \ |
98 | {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \ | 106 | {PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, (device)), \ |
99 | .class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0} | 107 | .class = PCI_CLASS_NETWORK_ETHERNET << 8, .class_mask = ~0} |
100 | 108 | ||
101 | #define PCI_DEVICE_ID_QLOGIC_QLE824X 0x8020 | ||
102 | |||
103 | static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = { | 109 | static DEFINE_PCI_DEVICE_TABLE(qlcnic_pci_tbl) = { |
104 | ENTRY(PCI_DEVICE_ID_QLOGIC_QLE824X), | 110 | ENTRY(PCI_DEVICE_ID_QLOGIC_QLE824X), |
111 | ENTRY(PCI_DEVICE_ID_QLOGIC_QLE834X), | ||
105 | {0,} | 112 | {0,} |
106 | }; | 113 | }; |
107 | 114 | ||
@@ -120,6 +127,32 @@ static const u32 msi_tgt_status[8] = { | |||
120 | ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7 | 127 | ISR_INT_TARGET_STATUS_F6, ISR_INT_TARGET_STATUS_F7 |
121 | }; | 128 | }; |
122 | 129 | ||
130 | static const u32 qlcnic_reg_tbl[] = { | ||
131 | 0x1B20A8, /* PEG_HALT_STAT1 */ | ||
132 | 0x1B20AC, /* PEG_HALT_STAT2 */ | ||
133 | 0x1B20B0, /* FW_HEARTBEAT */ | ||
134 | 0x1B2100, /* LOCK ID */ | ||
135 | 0x1B2128, /* FW_CAPABILITIES */ | ||
136 | 0x1B2138, /* drv active */ | ||
137 | 0x1B2140, /* dev state */ | ||
138 | 0x1B2144, /* drv state */ | ||
139 | 0x1B2148, /* drv scratch */ | ||
140 | 0x1B214C, /* dev partition info */ | ||
141 | 0x1B2174, /* drv idc ver */ | ||
142 | 0x1B2150, /* fw version major */ | ||
143 | 0x1B2154, /* fw version minor */ | ||
144 | 0x1B2158, /* fw version sub */ | ||
145 | 0x1B219C, /* npar state */ | ||
146 | 0x1B21FC, /* FW_IMG_VALID */ | ||
147 | 0x1B2250, /* CMD_PEG_STATE */ | ||
148 | 0x1B233C, /* RCV_PEG_STATE */ | ||
149 | 0x1B23B4, /* ASIC TEMP */ | ||
150 | 0x1B216C, /* FW api */ | ||
151 | 0x1B2170, /* drv op mode */ | ||
152 | 0x13C010, /* flash lock */ | ||
153 | 0x13C014, /* flash unlock */ | ||
154 | }; | ||
155 | |||
123 | static const struct qlcnic_board_info qlcnic_boards[] = { | 156 | static const struct qlcnic_board_info qlcnic_boards[] = { |
124 | {0x1077, 0x8020, 0x1077, 0x203, | 157 | {0x1077, 0x8020, 0x1077, 0x203, |
125 | "8200 Series Single Port 10GbE Converged Network Adapter" | 158 | "8200 Series Single Port 10GbE Converged Network Adapter" |
@@ -143,6 +176,7 @@ static const struct qlcnic_board_info qlcnic_boards[] = { | |||
143 | }; | 176 | }; |
144 | 177 | ||
145 | #define NUM_SUPPORTED_BOARDS ARRAY_SIZE(qlcnic_boards) | 178 | #define NUM_SUPPORTED_BOARDS ARRAY_SIZE(qlcnic_boards) |
179 | #define QLC_MAX_SDS_RINGS 8 | ||
146 | 180 | ||
147 | static const | 181 | static const |
148 | struct qlcnic_legacy_intr_set legacy_intr[] = QLCNIC_LEGACY_INTR_CONFIG; | 182 | struct qlcnic_legacy_intr_set legacy_intr[] = QLCNIC_LEGACY_INTR_CONFIG; |
@@ -164,35 +198,6 @@ void qlcnic_free_sds_rings(struct qlcnic_recv_context *recv_ctx) | |||
164 | recv_ctx->sds_rings = NULL; | 198 | recv_ctx->sds_rings = NULL; |
165 | } | 199 | } |
166 | 200 | ||
167 | static void qlcnic_clear_stats(struct qlcnic_adapter *adapter) | ||
168 | { | ||
169 | memset(&adapter->stats, 0, sizeof(adapter->stats)); | ||
170 | } | ||
171 | |||
172 | static void qlcnic_set_msix_bit(struct pci_dev *pdev, int enable) | ||
173 | { | ||
174 | u32 control; | ||
175 | int pos; | ||
176 | |||
177 | pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX); | ||
178 | if (pos) { | ||
179 | pci_read_config_dword(pdev, pos, &control); | ||
180 | if (enable) | ||
181 | control |= PCI_MSIX_FLAGS_ENABLE; | ||
182 | else | ||
183 | control = 0; | ||
184 | pci_write_config_dword(pdev, pos, control); | ||
185 | } | ||
186 | } | ||
187 | |||
188 | static void qlcnic_init_msix_entries(struct qlcnic_adapter *adapter, int count) | ||
189 | { | ||
190 | int i; | ||
191 | |||
192 | for (i = 0; i < count; i++) | ||
193 | adapter->msix_entries[i].entry = i; | ||
194 | } | ||
195 | |||
196 | static int | 201 | static int |
197 | qlcnic_read_mac_addr(struct qlcnic_adapter *adapter) | 202 | qlcnic_read_mac_addr(struct qlcnic_adapter *adapter) |
198 | { | 203 | { |
@@ -204,12 +209,11 @@ qlcnic_read_mac_addr(struct qlcnic_adapter *adapter) | |||
204 | return -EIO; | 209 | return -EIO; |
205 | 210 | ||
206 | memcpy(netdev->dev_addr, mac_addr, ETH_ALEN); | 211 | memcpy(netdev->dev_addr, mac_addr, ETH_ALEN); |
207 | memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len); | ||
208 | memcpy(adapter->mac_addr, netdev->dev_addr, netdev->addr_len); | 212 | memcpy(adapter->mac_addr, netdev->dev_addr, netdev->addr_len); |
209 | 213 | ||
210 | /* set station address */ | 214 | /* set station address */ |
211 | 215 | ||
212 | if (!is_valid_ether_addr(netdev->perm_addr)) | 216 | if (!is_valid_ether_addr(netdev->dev_addr)) |
213 | dev_warn(&pdev->dev, "Bad MAC address %pM.\n", | 217 | dev_warn(&pdev->dev, "Bad MAC address %pM.\n", |
214 | netdev->dev_addr); | 218 | netdev->dev_addr); |
215 | 219 | ||
@@ -225,7 +229,7 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p) | |||
225 | return -EOPNOTSUPP; | 229 | return -EOPNOTSUPP; |
226 | 230 | ||
227 | if (!is_valid_ether_addr(addr->sa_data)) | 231 | if (!is_valid_ether_addr(addr->sa_data)) |
228 | return -EADDRNOTAVAIL; | 232 | return -EINVAL; |
229 | 233 | ||
230 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) { | 234 | if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) { |
231 | netif_device_detach(netdev); | 235 | netif_device_detach(netdev); |
@@ -243,6 +247,85 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p) | |||
243 | return 0; | 247 | return 0; |
244 | } | 248 | } |
245 | 249 | ||
250 | static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], | ||
251 | struct net_device *netdev, const unsigned char *addr) | ||
252 | { | ||
253 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
254 | int err = -EOPNOTSUPP; | ||
255 | |||
256 | if (!adapter->fdb_mac_learn) { | ||
257 | pr_info("%s: Driver mac learn is enabled, FDB operation not allowed\n", | ||
258 | __func__); | ||
259 | return err; | ||
260 | } | ||
261 | |||
262 | if (adapter->flags & QLCNIC_ESWITCH_ENABLED) { | ||
263 | if (is_unicast_ether_addr(addr)) | ||
264 | err = qlcnic_nic_del_mac(adapter, addr); | ||
265 | else if (is_multicast_ether_addr(addr)) | ||
266 | err = dev_mc_del(netdev, addr); | ||
267 | else | ||
268 | err = -EINVAL; | ||
269 | } | ||
270 | return err; | ||
271 | } | ||
272 | |||
273 | static int qlcnic_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], | ||
274 | struct net_device *netdev, | ||
275 | const unsigned char *addr, u16 flags) | ||
276 | { | ||
277 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
278 | int err = 0; | ||
279 | |||
280 | if (!adapter->fdb_mac_learn) { | ||
281 | pr_info("%s: Driver mac learn is enabled, FDB operation not allowed\n", | ||
282 | __func__); | ||
283 | return -EOPNOTSUPP; | ||
284 | } | ||
285 | |||
286 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) { | ||
287 | pr_info("%s: FDB e-switch is not enabled\n", __func__); | ||
288 | return -EOPNOTSUPP; | ||
289 | } | ||
290 | |||
291 | if (ether_addr_equal(addr, adapter->mac_addr)) | ||
292 | return err; | ||
293 | |||
294 | if (is_unicast_ether_addr(addr)) | ||
295 | err = qlcnic_nic_add_mac(adapter, addr); | ||
296 | else if (is_multicast_ether_addr(addr)) | ||
297 | err = dev_mc_add_excl(netdev, addr); | ||
298 | else | ||
299 | err = -EINVAL; | ||
300 | |||
301 | return err; | ||
302 | } | ||
303 | |||
304 | static int qlcnic_fdb_dump(struct sk_buff *skb, struct netlink_callback *ncb, | ||
305 | struct net_device *netdev, int idx) | ||
306 | { | ||
307 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | ||
308 | |||
309 | if (!adapter->fdb_mac_learn) { | ||
310 | pr_info("%s: Driver mac learn is enabled, FDB operation not allowed\n", | ||
311 | __func__); | ||
312 | return -EOPNOTSUPP; | ||
313 | } | ||
314 | |||
315 | if (adapter->flags & QLCNIC_ESWITCH_ENABLED) | ||
316 | idx = ndo_dflt_fdb_dump(skb, ncb, netdev, idx); | ||
317 | |||
318 | return idx; | ||
319 | } | ||
320 | |||
321 | static void qlcnic_82xx_cancel_idc_work(struct qlcnic_adapter *adapter) | ||
322 | { | ||
323 | while (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) | ||
324 | usleep_range(10000, 11000); | ||
325 | |||
326 | cancel_delayed_work_sync(&adapter->fw_work); | ||
327 | } | ||
328 | |||
246 | static const struct net_device_ops qlcnic_netdev_ops = { | 329 | static const struct net_device_ops qlcnic_netdev_ops = { |
247 | .ndo_open = qlcnic_open, | 330 | .ndo_open = qlcnic_open, |
248 | .ndo_stop = qlcnic_close, | 331 | .ndo_stop = qlcnic_close, |
@@ -257,6 +340,9 @@ static const struct net_device_ops qlcnic_netdev_ops = { | |||
257 | .ndo_tx_timeout = qlcnic_tx_timeout, | 340 | .ndo_tx_timeout = qlcnic_tx_timeout, |
258 | .ndo_vlan_rx_add_vid = qlcnic_vlan_rx_add, | 341 | .ndo_vlan_rx_add_vid = qlcnic_vlan_rx_add, |
259 | .ndo_vlan_rx_kill_vid = qlcnic_vlan_rx_del, | 342 | .ndo_vlan_rx_kill_vid = qlcnic_vlan_rx_del, |
343 | .ndo_fdb_add = qlcnic_fdb_add, | ||
344 | .ndo_fdb_del = qlcnic_fdb_del, | ||
345 | .ndo_fdb_dump = qlcnic_fdb_dump, | ||
260 | #ifdef CONFIG_NET_POLL_CONTROLLER | 346 | #ifdef CONFIG_NET_POLL_CONTROLLER |
261 | .ndo_poll_controller = qlcnic_poll_controller, | 347 | .ndo_poll_controller = qlcnic_poll_controller, |
262 | #endif | 348 | #endif |
@@ -267,50 +353,125 @@ static const struct net_device_ops qlcnic_netdev_failed_ops = { | |||
267 | }; | 353 | }; |
268 | 354 | ||
269 | static struct qlcnic_nic_template qlcnic_ops = { | 355 | static struct qlcnic_nic_template qlcnic_ops = { |
270 | .config_bridged_mode = qlcnic_config_bridged_mode, | 356 | .config_bridged_mode = qlcnic_config_bridged_mode, |
271 | .config_led = qlcnic_config_led, | 357 | .config_led = qlcnic_82xx_config_led, |
272 | .start_firmware = qlcnic_start_firmware | 358 | .start_firmware = qlcnic_82xx_start_firmware, |
359 | .request_reset = qlcnic_82xx_dev_request_reset, | ||
360 | .cancel_idc_work = qlcnic_82xx_cancel_idc_work, | ||
361 | .napi_add = qlcnic_82xx_napi_add, | ||
362 | .napi_del = qlcnic_82xx_napi_del, | ||
363 | .config_ipaddr = qlcnic_82xx_config_ipaddr, | ||
364 | .clear_legacy_intr = qlcnic_82xx_clear_legacy_intr, | ||
273 | }; | 365 | }; |
274 | 366 | ||
275 | static struct qlcnic_nic_template qlcnic_vf_ops = { | 367 | struct qlcnic_nic_template qlcnic_vf_ops = { |
276 | .config_bridged_mode = qlcnicvf_config_bridged_mode, | 368 | .config_bridged_mode = qlcnicvf_config_bridged_mode, |
277 | .config_led = qlcnicvf_config_led, | 369 | .config_led = qlcnicvf_config_led, |
278 | .start_firmware = qlcnicvf_start_firmware | 370 | .start_firmware = qlcnicvf_start_firmware |
279 | }; | 371 | }; |
280 | 372 | ||
281 | static int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) | 373 | static struct qlcnic_hardware_ops qlcnic_hw_ops = { |
374 | .read_crb = qlcnic_82xx_read_crb, | ||
375 | .write_crb = qlcnic_82xx_write_crb, | ||
376 | .read_reg = qlcnic_82xx_hw_read_wx_2M, | ||
377 | .write_reg = qlcnic_82xx_hw_write_wx_2M, | ||
378 | .get_mac_address = qlcnic_82xx_get_mac_address, | ||
379 | .setup_intr = qlcnic_82xx_setup_intr, | ||
380 | .alloc_mbx_args = qlcnic_82xx_alloc_mbx_args, | ||
381 | .mbx_cmd = qlcnic_82xx_issue_cmd, | ||
382 | .get_func_no = qlcnic_82xx_get_func_no, | ||
383 | .api_lock = qlcnic_82xx_api_lock, | ||
384 | .api_unlock = qlcnic_82xx_api_unlock, | ||
385 | .add_sysfs = qlcnic_82xx_add_sysfs, | ||
386 | .remove_sysfs = qlcnic_82xx_remove_sysfs, | ||
387 | .process_lb_rcv_ring_diag = qlcnic_82xx_process_rcv_ring_diag, | ||
388 | .create_rx_ctx = qlcnic_82xx_fw_cmd_create_rx_ctx, | ||
389 | .create_tx_ctx = qlcnic_82xx_fw_cmd_create_tx_ctx, | ||
390 | .setup_link_event = qlcnic_82xx_linkevent_request, | ||
391 | .get_nic_info = qlcnic_82xx_get_nic_info, | ||
392 | .get_pci_info = qlcnic_82xx_get_pci_info, | ||
393 | .set_nic_info = qlcnic_82xx_set_nic_info, | ||
394 | .change_macvlan = qlcnic_82xx_sre_macaddr_change, | ||
395 | .napi_enable = qlcnic_82xx_napi_enable, | ||
396 | .napi_disable = qlcnic_82xx_napi_disable, | ||
397 | .config_intr_coal = qlcnic_82xx_config_intr_coalesce, | ||
398 | .config_rss = qlcnic_82xx_config_rss, | ||
399 | .config_hw_lro = qlcnic_82xx_config_hw_lro, | ||
400 | .config_loopback = qlcnic_82xx_set_lb_mode, | ||
401 | .clear_loopback = qlcnic_82xx_clear_lb_mode, | ||
402 | .config_promisc_mode = qlcnic_82xx_nic_set_promisc, | ||
403 | .change_l2_filter = qlcnic_82xx_change_filter, | ||
404 | .get_board_info = qlcnic_82xx_get_board_info, | ||
405 | }; | ||
406 | |||
407 | int qlcnic_enable_msix(struct qlcnic_adapter *adapter, u32 num_msix) | ||
282 | { | 408 | { |
283 | struct pci_dev *pdev = adapter->pdev; | 409 | struct pci_dev *pdev = adapter->pdev; |
284 | int err = -1; | 410 | int err = -1, i; |
411 | int max_tx_rings; | ||
412 | |||
413 | if (!adapter->msix_entries) { | ||
414 | adapter->msix_entries = kcalloc(num_msix, | ||
415 | sizeof(struct msix_entry), | ||
416 | GFP_KERNEL); | ||
417 | if (!adapter->msix_entries) | ||
418 | return -ENOMEM; | ||
419 | } | ||
285 | 420 | ||
286 | adapter->max_sds_rings = 1; | 421 | adapter->max_sds_rings = 1; |
287 | adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED); | 422 | adapter->flags &= ~(QLCNIC_MSI_ENABLED | QLCNIC_MSIX_ENABLED); |
288 | qlcnic_set_msix_bit(pdev, 0); | ||
289 | 423 | ||
290 | if (adapter->ahw->msix_supported) { | 424 | if (adapter->ahw->msix_supported) { |
291 | enable_msix: | 425 | enable_msix: |
292 | qlcnic_init_msix_entries(adapter, num_msix); | 426 | for (i = 0; i < num_msix; i++) |
427 | adapter->msix_entries[i].entry = i; | ||
293 | err = pci_enable_msix(pdev, adapter->msix_entries, num_msix); | 428 | err = pci_enable_msix(pdev, adapter->msix_entries, num_msix); |
294 | if (err == 0) { | 429 | if (err == 0) { |
295 | adapter->flags |= QLCNIC_MSIX_ENABLED; | 430 | adapter->flags |= QLCNIC_MSIX_ENABLED; |
296 | qlcnic_set_msix_bit(pdev, 1); | 431 | if (qlcnic_83xx_check(adapter)) { |
297 | 432 | adapter->ahw->num_msix = num_msix; | |
298 | adapter->max_sds_rings = num_msix; | 433 | /* subtract mail box and tx ring vectors */ |
299 | 434 | max_tx_rings = adapter->max_drv_tx_rings; | |
435 | adapter->max_sds_rings = num_msix - | ||
436 | max_tx_rings - 1; | ||
437 | } else { | ||
438 | adapter->max_sds_rings = num_msix; | ||
439 | } | ||
300 | dev_info(&pdev->dev, "using msi-x interrupts\n"); | 440 | dev_info(&pdev->dev, "using msi-x interrupts\n"); |
301 | return err; | 441 | return err; |
302 | } | 442 | } else if (err > 0) { |
303 | if (err > 0) { | 443 | dev_info(&pdev->dev, |
304 | num_msix = rounddown_pow_of_two(err); | 444 | "Unable to allocate %d MSI-X interrupt vectors\n", |
305 | if (num_msix) | 445 | num_msix); |
446 | if (qlcnic_83xx_check(adapter)) { | ||
447 | if (err < QLC_83XX_MINIMUM_VECTOR) | ||
448 | return err; | ||
449 | err -= (adapter->max_drv_tx_rings + 1); | ||
450 | num_msix = rounddown_pow_of_two(err); | ||
451 | num_msix += (adapter->max_drv_tx_rings + 1); | ||
452 | } else { | ||
453 | num_msix = rounddown_pow_of_two(err); | ||
454 | } | ||
455 | |||
456 | if (num_msix) { | ||
457 | dev_info(&pdev->dev, | ||
458 | "Trying to allocate %d MSI-X interrupt vectors\n", | ||
459 | num_msix); | ||
306 | goto enable_msix; | 460 | goto enable_msix; |
461 | } | ||
462 | } else { | ||
463 | dev_info(&pdev->dev, | ||
464 | "Unable to allocate %d MSI-X interrupt vectors\n", | ||
465 | num_msix); | ||
307 | } | 466 | } |
308 | } | 467 | } |
468 | |||
309 | return err; | 469 | return err; |
310 | } | 470 | } |
311 | 471 | ||
312 | static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter) | 472 | static int qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter) |
313 | { | 473 | { |
474 | int err = 0; | ||
314 | u32 offset, mask_reg; | 475 | u32 offset, mask_reg; |
315 | const struct qlcnic_legacy_intr_set *legacy_intrp; | 476 | const struct qlcnic_legacy_intr_set *legacy_intrp; |
316 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 477 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
@@ -323,8 +484,10 @@ static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter) | |||
323 | offset); | 484 | offset); |
324 | dev_info(&pdev->dev, "using msi interrupts\n"); | 485 | dev_info(&pdev->dev, "using msi interrupts\n"); |
325 | adapter->msix_entries[0].vector = pdev->irq; | 486 | adapter->msix_entries[0].vector = pdev->irq; |
326 | return; | 487 | return err; |
327 | } | 488 | } |
489 | if (qlcnic_use_msi || qlcnic_use_msi_x) | ||
490 | return -EOPNOTSUPP; | ||
328 | 491 | ||
329 | legacy_intrp = &legacy_intr[adapter->ahw->pci_func]; | 492 | legacy_intrp = &legacy_intr[adapter->ahw->pci_func]; |
330 | adapter->ahw->int_vec_bit = legacy_intrp->int_vec_bit; | 493 | adapter->ahw->int_vec_bit = legacy_intrp->int_vec_bit; |
@@ -336,32 +499,47 @@ static void qlcnic_enable_msi_legacy(struct qlcnic_adapter *adapter) | |||
336 | adapter->crb_int_state_reg = qlcnic_get_ioaddr(ahw, ISR_INT_STATE_REG); | 499 | adapter->crb_int_state_reg = qlcnic_get_ioaddr(ahw, ISR_INT_STATE_REG); |
337 | dev_info(&pdev->dev, "using legacy interrupts\n"); | 500 | dev_info(&pdev->dev, "using legacy interrupts\n"); |
338 | adapter->msix_entries[0].vector = pdev->irq; | 501 | adapter->msix_entries[0].vector = pdev->irq; |
502 | return err; | ||
339 | } | 503 | } |
340 | 504 | ||
341 | static void | 505 | int qlcnic_82xx_setup_intr(struct qlcnic_adapter *adapter, u8 num_intr) |
342 | qlcnic_setup_intr(struct qlcnic_adapter *adapter) | ||
343 | { | 506 | { |
344 | int num_msix; | 507 | int num_msix, err = 0; |
345 | 508 | ||
346 | if (adapter->ahw->msix_supported) { | 509 | if (!num_intr) |
510 | num_intr = QLCNIC_DEF_NUM_STS_DESC_RINGS; | ||
511 | |||
512 | if (adapter->ahw->msix_supported) | ||
347 | num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(), | 513 | num_msix = rounddown_pow_of_two(min_t(int, num_online_cpus(), |
348 | QLCNIC_DEF_NUM_STS_DESC_RINGS)); | 514 | num_intr)); |
349 | } else | 515 | else |
350 | num_msix = 1; | 516 | num_msix = 1; |
351 | 517 | ||
352 | if (!qlcnic_enable_msix(adapter, num_msix)) | 518 | err = qlcnic_enable_msix(adapter, num_msix); |
353 | return; | 519 | if (err == -ENOMEM || !err) |
520 | return err; | ||
354 | 521 | ||
355 | qlcnic_enable_msi_legacy(adapter); | 522 | err = qlcnic_enable_msi_legacy(adapter); |
523 | if (!err) | ||
524 | return err; | ||
525 | |||
526 | return -EIO; | ||
356 | } | 527 | } |
357 | 528 | ||
358 | static void | 529 | void qlcnic_teardown_intr(struct qlcnic_adapter *adapter) |
359 | qlcnic_teardown_intr(struct qlcnic_adapter *adapter) | ||
360 | { | 530 | { |
361 | if (adapter->flags & QLCNIC_MSIX_ENABLED) | 531 | if (adapter->flags & QLCNIC_MSIX_ENABLED) |
362 | pci_disable_msix(adapter->pdev); | 532 | pci_disable_msix(adapter->pdev); |
363 | if (adapter->flags & QLCNIC_MSI_ENABLED) | 533 | if (adapter->flags & QLCNIC_MSI_ENABLED) |
364 | pci_disable_msi(adapter->pdev); | 534 | pci_disable_msi(adapter->pdev); |
535 | |||
536 | kfree(adapter->msix_entries); | ||
537 | adapter->msix_entries = NULL; | ||
538 | |||
539 | if (adapter->ahw->intr_tbl) { | ||
540 | vfree(adapter->ahw->intr_tbl); | ||
541 | adapter->ahw->intr_tbl = NULL; | ||
542 | } | ||
365 | } | 543 | } |
366 | 544 | ||
367 | static void | 545 | static void |
@@ -371,7 +549,36 @@ qlcnic_cleanup_pci_map(struct qlcnic_adapter *adapter) | |||
371 | iounmap(adapter->ahw->pci_base0); | 549 | iounmap(adapter->ahw->pci_base0); |
372 | } | 550 | } |
373 | 551 | ||
374 | static int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) | 552 | static int qlcnic_get_act_pci_func(struct qlcnic_adapter *adapter) |
553 | { | ||
554 | struct qlcnic_pci_info *pci_info; | ||
555 | int ret; | ||
556 | |||
557 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) { | ||
558 | switch (adapter->ahw->port_type) { | ||
559 | case QLCNIC_GBE: | ||
560 | adapter->ahw->act_pci_func = QLCNIC_NIU_MAX_GBE_PORTS; | ||
561 | break; | ||
562 | case QLCNIC_XGBE: | ||
563 | adapter->ahw->act_pci_func = QLCNIC_NIU_MAX_XG_PORTS; | ||
564 | break; | ||
565 | } | ||
566 | return 0; | ||
567 | } | ||
568 | |||
569 | if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) | ||
570 | return 0; | ||
571 | |||
572 | pci_info = kcalloc(QLCNIC_MAX_PCI_FUNC, sizeof(*pci_info), GFP_KERNEL); | ||
573 | if (!pci_info) | ||
574 | return -ENOMEM; | ||
575 | |||
576 | ret = qlcnic_get_pci_info(adapter, pci_info); | ||
577 | kfree(pci_info); | ||
578 | return ret; | ||
579 | } | ||
580 | |||
581 | int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) | ||
375 | { | 582 | { |
376 | struct qlcnic_pci_info *pci_info; | 583 | struct qlcnic_pci_info *pci_info; |
377 | int i, ret = 0, j = 0; | 584 | int i, ret = 0, j = 0; |
@@ -423,8 +630,11 @@ static int qlcnic_init_pci_info(struct qlcnic_adapter *adapter) | |||
423 | j++; | 630 | j++; |
424 | } | 631 | } |
425 | 632 | ||
426 | for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) | 633 | for (i = 0; i < QLCNIC_NIU_MAX_XG_PORTS; i++) { |
427 | adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE; | 634 | adapter->eswitch[i].flags |= QLCNIC_SWITCH_ENABLE; |
635 | if (qlcnic_83xx_check(adapter)) | ||
636 | qlcnic_enable_eswitch(adapter, i, 1); | ||
637 | } | ||
428 | 638 | ||
429 | kfree(pci_info); | 639 | kfree(pci_info); |
430 | return 0; | 640 | return 0; |
@@ -462,40 +672,31 @@ qlcnic_set_function_modes(struct qlcnic_adapter *adapter) | |||
462 | QLC_DEV_SET_DRV(0xf, id)); | 672 | QLC_DEV_SET_DRV(0xf, id)); |
463 | } | 673 | } |
464 | } else { | 674 | } else { |
465 | data = QLCRD32(adapter, QLCNIC_DRV_OP_MODE); | 675 | data = QLC_SHARED_REG_RD32(adapter, QLCNIC_DRV_OP_MODE); |
466 | data = (data & ~QLC_DEV_SET_DRV(0xf, ahw->pci_func)) | | 676 | data = (data & ~QLC_DEV_SET_DRV(0xf, ahw->pci_func)) | |
467 | (QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC, | 677 | (QLC_DEV_SET_DRV(QLCNIC_MGMT_FUNC, |
468 | ahw->pci_func)); | 678 | ahw->pci_func)); |
469 | } | 679 | } |
470 | QLCWR32(adapter, QLCNIC_DRV_OP_MODE, data); | 680 | QLC_SHARED_REG_WR32(adapter, QLCNIC_DRV_OP_MODE, data); |
471 | qlcnic_api_unlock(adapter); | 681 | qlcnic_api_unlock(adapter); |
472 | err_lock: | 682 | err_lock: |
473 | return ret; | 683 | return ret; |
474 | } | 684 | } |
475 | 685 | ||
476 | static void | 686 | static void qlcnic_check_vf(struct qlcnic_adapter *adapter, |
477 | qlcnic_check_vf(struct qlcnic_adapter *adapter) | 687 | const struct pci_device_id *ent) |
478 | { | 688 | { |
479 | void __iomem *msix_base_addr; | ||
480 | void __iomem *priv_op; | ||
481 | u32 func; | ||
482 | u32 msix_base; | ||
483 | u32 op_mode, priv_level; | 689 | u32 op_mode, priv_level; |
484 | 690 | ||
485 | /* Determine FW API version */ | 691 | /* Determine FW API version */ |
486 | adapter->ahw->fw_hal_version = readl(adapter->ahw->pci_base0 + | 692 | adapter->ahw->fw_hal_version = QLC_SHARED_REG_RD32(adapter, |
487 | QLCNIC_FW_API); | 693 | QLCNIC_FW_API); |
488 | 694 | ||
489 | /* Find PCI function number */ | 695 | /* Find PCI function number */ |
490 | pci_read_config_dword(adapter->pdev, QLCNIC_MSIX_TABLE_OFFSET, &func); | 696 | qlcnic_get_func_no(adapter); |
491 | msix_base_addr = adapter->ahw->pci_base0 + QLCNIC_MSIX_BASE; | ||
492 | msix_base = readl(msix_base_addr); | ||
493 | func = (func - msix_base)/QLCNIC_MSIX_TBL_PGSIZE; | ||
494 | adapter->ahw->pci_func = func; | ||
495 | 697 | ||
496 | /* Determine function privilege level */ | 698 | /* Determine function privilege level */ |
497 | priv_op = adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE; | 699 | op_mode = QLC_SHARED_REG_RD32(adapter, QLCNIC_DRV_OP_MODE); |
498 | op_mode = readl(priv_op); | ||
499 | if (op_mode == QLC_DEV_DRV_DEFAULT) | 700 | if (op_mode == QLC_DEV_DRV_DEFAULT) |
500 | priv_level = QLCNIC_MGMT_FUNC; | 701 | priv_level = QLCNIC_MGMT_FUNC; |
501 | else | 702 | else |
@@ -512,12 +713,16 @@ qlcnic_check_vf(struct qlcnic_adapter *adapter) | |||
512 | } | 713 | } |
513 | 714 | ||
514 | #define QLCNIC_82XX_BAR0_LENGTH 0x00200000UL | 715 | #define QLCNIC_82XX_BAR0_LENGTH 0x00200000UL |
716 | #define QLCNIC_83XX_BAR0_LENGTH 0x4000 | ||
515 | static void qlcnic_get_bar_length(u32 dev_id, ulong *bar) | 717 | static void qlcnic_get_bar_length(u32 dev_id, ulong *bar) |
516 | { | 718 | { |
517 | switch (dev_id) { | 719 | switch (dev_id) { |
518 | case PCI_DEVICE_ID_QLOGIC_QLE824X: | 720 | case PCI_DEVICE_ID_QLOGIC_QLE824X: |
519 | *bar = QLCNIC_82XX_BAR0_LENGTH; | 721 | *bar = QLCNIC_82XX_BAR0_LENGTH; |
520 | break; | 722 | break; |
723 | case PCI_DEVICE_ID_QLOGIC_QLE834X: | ||
724 | *bar = QLCNIC_83XX_BAR0_LENGTH; | ||
725 | break; | ||
521 | default: | 726 | default: |
522 | *bar = 0; | 727 | *bar = 0; |
523 | } | 728 | } |
@@ -547,6 +752,7 @@ static int qlcnic_setup_pci_map(struct pci_dev *pdev, | |||
547 | } | 752 | } |
548 | 753 | ||
549 | dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20)); | 754 | dev_info(&pdev->dev, "%dMB memory map\n", (int)(mem_len>>20)); |
755 | |||
550 | ahw->pci_base0 = mem_ptr0; | 756 | ahw->pci_base0 = mem_ptr0; |
551 | ahw->pci_len0 = pci_len0; | 757 | ahw->pci_len0 = pci_len0; |
552 | offset = QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(ahw->pci_func)); | 758 | offset = QLCNIC_PCIX_PS_REG(PCIX_OCM_WINDOW_REG(ahw->pci_func)); |
@@ -581,19 +787,26 @@ static void qlcnic_get_board_name(struct qlcnic_adapter *adapter, char *name) | |||
581 | static void | 787 | static void |
582 | qlcnic_check_options(struct qlcnic_adapter *adapter) | 788 | qlcnic_check_options(struct qlcnic_adapter *adapter) |
583 | { | 789 | { |
790 | int err; | ||
584 | u32 fw_major, fw_minor, fw_build, prev_fw_version; | 791 | u32 fw_major, fw_minor, fw_build, prev_fw_version; |
585 | struct pci_dev *pdev = adapter->pdev; | 792 | struct pci_dev *pdev = adapter->pdev; |
586 | struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; | 793 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
794 | struct qlcnic_fw_dump *fw_dump = &ahw->fw_dump; | ||
587 | 795 | ||
588 | prev_fw_version = adapter->fw_version; | 796 | prev_fw_version = adapter->fw_version; |
589 | 797 | ||
590 | fw_major = QLCRD32(adapter, QLCNIC_FW_VERSION_MAJOR); | 798 | fw_major = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MAJOR); |
591 | fw_minor = QLCRD32(adapter, QLCNIC_FW_VERSION_MINOR); | 799 | fw_minor = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_MINOR); |
592 | fw_build = QLCRD32(adapter, QLCNIC_FW_VERSION_SUB); | 800 | fw_build = QLC_SHARED_REG_RD32(adapter, QLCNIC_FW_VERSION_SUB); |
593 | 801 | ||
594 | adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build); | 802 | adapter->fw_version = QLCNIC_VERSION_CODE(fw_major, fw_minor, fw_build); |
595 | 803 | ||
596 | if (adapter->ahw->op_mode != QLCNIC_NON_PRIV_FUNC) { | 804 | err = qlcnic_get_board_info(adapter); |
805 | if (err) { | ||
806 | dev_err(&pdev->dev, "Error getting board config info.\n"); | ||
807 | return; | ||
808 | } | ||
809 | if (ahw->op_mode != QLCNIC_NON_PRIV_FUNC) { | ||
597 | if (fw_dump->tmpl_hdr == NULL || | 810 | if (fw_dump->tmpl_hdr == NULL || |
598 | adapter->fw_version > prev_fw_version) { | 811 | adapter->fw_version > prev_fw_version) { |
599 | if (fw_dump->tmpl_hdr) | 812 | if (fw_dump->tmpl_hdr) |
@@ -604,8 +817,9 @@ qlcnic_check_options(struct qlcnic_adapter *adapter) | |||
604 | } | 817 | } |
605 | } | 818 | } |
606 | 819 | ||
607 | dev_info(&pdev->dev, "firmware v%d.%d.%d\n", | 820 | dev_info(&pdev->dev, "Driver v%s, firmware v%d.%d.%d\n", |
608 | fw_major, fw_minor, fw_build); | 821 | QLCNIC_LINUX_VERSIONID, fw_major, fw_minor, fw_build); |
822 | |||
609 | if (adapter->ahw->port_type == QLCNIC_XGBE) { | 823 | if (adapter->ahw->port_type == QLCNIC_XGBE) { |
610 | if (adapter->flags & QLCNIC_ESWITCH_ENABLED) { | 824 | if (adapter->flags & QLCNIC_ESWITCH_ENABLED) { |
611 | adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_VF; | 825 | adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_VF; |
@@ -648,9 +862,19 @@ qlcnic_initialize_nic(struct qlcnic_adapter *adapter) | |||
648 | adapter->ahw->max_tx_ques = nic_info.max_tx_ques; | 862 | adapter->ahw->max_tx_ques = nic_info.max_tx_ques; |
649 | adapter->ahw->max_rx_ques = nic_info.max_rx_ques; | 863 | adapter->ahw->max_rx_ques = nic_info.max_rx_ques; |
650 | adapter->ahw->capabilities = nic_info.capabilities; | 864 | adapter->ahw->capabilities = nic_info.capabilities; |
865 | |||
866 | if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) { | ||
867 | u32 temp; | ||
868 | temp = QLCRD32(adapter, CRB_FW_CAPABILITIES_2); | ||
869 | adapter->ahw->capabilities2 = temp; | ||
870 | } | ||
651 | adapter->ahw->max_mac_filters = nic_info.max_mac_filters; | 871 | adapter->ahw->max_mac_filters = nic_info.max_mac_filters; |
652 | adapter->ahw->max_mtu = nic_info.max_mtu; | 872 | adapter->ahw->max_mtu = nic_info.max_mtu; |
653 | 873 | ||
874 | /* Disable NPAR for 83XX */ | ||
875 | if (qlcnic_83xx_check(adapter)) | ||
876 | return err; | ||
877 | |||
654 | if (adapter->ahw->capabilities & BIT_6) | 878 | if (adapter->ahw->capabilities & BIT_6) |
655 | adapter->flags |= QLCNIC_ESWITCH_ENABLED; | 879 | adapter->flags |= QLCNIC_ESWITCH_ENABLED; |
656 | else | 880 | else |
@@ -709,7 +933,7 @@ void qlcnic_set_eswitch_port_features(struct qlcnic_adapter *adapter, | |||
709 | qlcnic_set_netdev_features(adapter, esw_cfg); | 933 | qlcnic_set_netdev_features(adapter, esw_cfg); |
710 | } | 934 | } |
711 | 935 | ||
712 | static int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter) | 936 | int qlcnic_set_eswitch_port_config(struct qlcnic_adapter *adapter) |
713 | { | 937 | { |
714 | struct qlcnic_esw_func_cfg esw_cfg; | 938 | struct qlcnic_esw_func_cfg esw_cfg; |
715 | 939 | ||
@@ -730,14 +954,17 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter, | |||
730 | struct qlcnic_esw_func_cfg *esw_cfg) | 954 | struct qlcnic_esw_func_cfg *esw_cfg) |
731 | { | 955 | { |
732 | struct net_device *netdev = adapter->netdev; | 956 | struct net_device *netdev = adapter->netdev; |
733 | netdev_features_t features, vlan_features; | 957 | unsigned long features, vlan_features; |
958 | |||
959 | if (qlcnic_83xx_check(adapter)) | ||
960 | return; | ||
734 | 961 | ||
735 | features = (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM | | 962 | features = (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM | |
736 | NETIF_F_IPV6_CSUM | NETIF_F_GRO); | 963 | NETIF_F_IPV6_CSUM | NETIF_F_GRO); |
737 | vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM | | 964 | vlan_features = (NETIF_F_SG | NETIF_F_IP_CSUM | |
738 | NETIF_F_IPV6_CSUM | NETIF_F_HW_VLAN_FILTER); | 965 | NETIF_F_IPV6_CSUM); |
739 | 966 | ||
740 | if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) { | 967 | if (QLCNIC_IS_TSO_CAPABLE(adapter)) { |
741 | features |= (NETIF_F_TSO | NETIF_F_TSO6); | 968 | features |= (NETIF_F_TSO | NETIF_F_TSO6); |
742 | vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6); | 969 | vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6); |
743 | } | 970 | } |
@@ -747,12 +974,19 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter, | |||
747 | 974 | ||
748 | if (esw_cfg->offload_flags & BIT_0) { | 975 | if (esw_cfg->offload_flags & BIT_0) { |
749 | netdev->features |= features; | 976 | netdev->features |= features; |
750 | if (!(esw_cfg->offload_flags & BIT_1)) | 977 | adapter->rx_csum = 1; |
978 | if (!(esw_cfg->offload_flags & BIT_1)) { | ||
751 | netdev->features &= ~NETIF_F_TSO; | 979 | netdev->features &= ~NETIF_F_TSO; |
752 | if (!(esw_cfg->offload_flags & BIT_2)) | 980 | features &= ~NETIF_F_TSO; |
981 | } | ||
982 | if (!(esw_cfg->offload_flags & BIT_2)) { | ||
753 | netdev->features &= ~NETIF_F_TSO6; | 983 | netdev->features &= ~NETIF_F_TSO6; |
984 | features &= ~NETIF_F_TSO6; | ||
985 | } | ||
754 | } else { | 986 | } else { |
755 | netdev->features &= ~features; | 987 | netdev->features &= ~features; |
988 | features &= ~features; | ||
989 | adapter->rx_csum = 0; | ||
756 | } | 990 | } |
757 | 991 | ||
758 | netdev->vlan_features = (features & vlan_features); | 992 | netdev->vlan_features = (features & vlan_features); |
@@ -761,7 +995,6 @@ qlcnic_set_netdev_features(struct qlcnic_adapter *adapter, | |||
761 | static int | 995 | static int |
762 | qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter) | 996 | qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter) |
763 | { | 997 | { |
764 | void __iomem *priv_op; | ||
765 | u32 op_mode, priv_level; | 998 | u32 op_mode, priv_level; |
766 | int err = 0; | 999 | int err = 0; |
767 | 1000 | ||
@@ -772,8 +1005,7 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter) | |||
772 | if (adapter->flags & QLCNIC_ADAPTER_INITIALIZED) | 1005 | if (adapter->flags & QLCNIC_ADAPTER_INITIALIZED) |
773 | return 0; | 1006 | return 0; |
774 | 1007 | ||
775 | priv_op = adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE; | 1008 | op_mode = QLC_SHARED_REG_RD32(adapter, QLCNIC_DRV_OP_MODE); |
776 | op_mode = readl(priv_op); | ||
777 | priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func); | 1009 | priv_level = QLC_DEV_GET_DRV(op_mode, adapter->ahw->pci_func); |
778 | 1010 | ||
779 | if (op_mode == QLC_DEV_DRV_DEFAULT) | 1011 | if (op_mode == QLC_DEV_DRV_DEFAULT) |
@@ -805,7 +1037,7 @@ qlcnic_check_eswitch_mode(struct qlcnic_adapter *adapter) | |||
805 | return err; | 1037 | return err; |
806 | } | 1038 | } |
807 | 1039 | ||
808 | static int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter) | 1040 | int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter) |
809 | { | 1041 | { |
810 | struct qlcnic_esw_func_cfg esw_cfg; | 1042 | struct qlcnic_esw_func_cfg esw_cfg; |
811 | struct qlcnic_npar_info *npar; | 1043 | struct qlcnic_npar_info *npar; |
@@ -838,6 +1070,7 @@ static int qlcnic_set_default_offload_settings(struct qlcnic_adapter *adapter) | |||
838 | return 0; | 1070 | return 0; |
839 | } | 1071 | } |
840 | 1072 | ||
1073 | |||
841 | static int | 1074 | static int |
842 | qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter, | 1075 | qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter, |
843 | struct qlcnic_npar_info *npar, int pci_func) | 1076 | struct qlcnic_npar_info *npar, int pci_func) |
@@ -861,7 +1094,7 @@ qlcnic_reset_eswitch_config(struct qlcnic_adapter *adapter, | |||
861 | return 0; | 1094 | return 0; |
862 | } | 1095 | } |
863 | 1096 | ||
864 | static int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter) | 1097 | int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter) |
865 | { | 1098 | { |
866 | int i, err; | 1099 | int i, err; |
867 | struct qlcnic_npar_info *npar; | 1100 | struct qlcnic_npar_info *npar; |
@@ -877,8 +1110,7 @@ static int qlcnic_reset_npar_config(struct qlcnic_adapter *adapter) | |||
877 | npar = &adapter->npars[i]; | 1110 | npar = &adapter->npars[i]; |
878 | pci_func = npar->pci_func; | 1111 | pci_func = npar->pci_func; |
879 | memset(&nic_info, 0, sizeof(struct qlcnic_info)); | 1112 | memset(&nic_info, 0, sizeof(struct qlcnic_info)); |
880 | err = qlcnic_get_nic_info(adapter, | 1113 | err = qlcnic_get_nic_info(adapter, &nic_info, pci_func); |
881 | &nic_info, pci_func); | ||
882 | if (err) | 1114 | if (err) |
883 | return err; | 1115 | return err; |
884 | nic_info.min_tx_bw = npar->min_bw; | 1116 | nic_info.min_tx_bw = npar->min_bw; |
@@ -909,14 +1141,16 @@ static int qlcnic_check_npar_opertional(struct qlcnic_adapter *adapter) | |||
909 | if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) | 1141 | if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) |
910 | return 0; | 1142 | return 0; |
911 | 1143 | ||
912 | npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); | 1144 | npar_state = QLC_SHARED_REG_RD32(adapter, |
1145 | QLCNIC_CRB_DEV_NPAR_STATE); | ||
913 | while (npar_state != QLCNIC_DEV_NPAR_OPER && --npar_opt_timeo) { | 1146 | while (npar_state != QLCNIC_DEV_NPAR_OPER && --npar_opt_timeo) { |
914 | msleep(1000); | 1147 | msleep(1000); |
915 | npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); | 1148 | npar_state = QLC_SHARED_REG_RD32(adapter, |
1149 | QLCNIC_CRB_DEV_NPAR_STATE); | ||
916 | } | 1150 | } |
917 | if (!npar_opt_timeo) { | 1151 | if (!npar_opt_timeo) { |
918 | dev_err(&adapter->pdev->dev, | 1152 | dev_err(&adapter->pdev->dev, |
919 | "Waiting for NPAR state to opertional timeout\n"); | 1153 | "Waiting for NPAR state to operational timeout\n"); |
920 | return -EIO; | 1154 | return -EIO; |
921 | } | 1155 | } |
922 | return 0; | 1156 | return 0; |
@@ -944,8 +1178,7 @@ qlcnic_set_mgmt_operations(struct qlcnic_adapter *adapter) | |||
944 | return err; | 1178 | return err; |
945 | } | 1179 | } |
946 | 1180 | ||
947 | static int | 1181 | int qlcnic_82xx_start_firmware(struct qlcnic_adapter *adapter) |
948 | qlcnic_start_firmware(struct qlcnic_adapter *adapter) | ||
949 | { | 1182 | { |
950 | int err; | 1183 | int err; |
951 | 1184 | ||
@@ -985,9 +1218,8 @@ check_fw_status: | |||
985 | if (err) | 1218 | if (err) |
986 | goto err_out; | 1219 | goto err_out; |
987 | 1220 | ||
988 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY); | 1221 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_READY); |
989 | qlcnic_idc_debug_info(adapter, 1); | 1222 | qlcnic_idc_debug_info(adapter, 1); |
990 | |||
991 | err = qlcnic_check_eswitch_mode(adapter); | 1223 | err = qlcnic_check_eswitch_mode(adapter); |
992 | if (err) { | 1224 | if (err) { |
993 | dev_err(&adapter->pdev->dev, | 1225 | dev_err(&adapter->pdev->dev, |
@@ -1005,7 +1237,7 @@ check_fw_status: | |||
1005 | return 0; | 1237 | return 0; |
1006 | 1238 | ||
1007 | err_out: | 1239 | err_out: |
1008 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED); | 1240 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED); |
1009 | dev_err(&adapter->pdev->dev, "Device state set to failed\n"); | 1241 | dev_err(&adapter->pdev->dev, "Device state set to failed\n"); |
1010 | 1242 | ||
1011 | qlcnic_release_firmware(adapter); | 1243 | qlcnic_release_firmware(adapter); |
@@ -1017,6 +1249,7 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter) | |||
1017 | { | 1249 | { |
1018 | irq_handler_t handler; | 1250 | irq_handler_t handler; |
1019 | struct qlcnic_host_sds_ring *sds_ring; | 1251 | struct qlcnic_host_sds_ring *sds_ring; |
1252 | struct qlcnic_host_tx_ring *tx_ring; | ||
1020 | int err, ring; | 1253 | int err, ring; |
1021 | 1254 | ||
1022 | unsigned long flags = 0; | 1255 | unsigned long flags = 0; |
@@ -1024,7 +1257,8 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter) | |||
1024 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | 1257 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; |
1025 | 1258 | ||
1026 | if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) { | 1259 | if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) { |
1027 | handler = qlcnic_tmp_intr; | 1260 | if (qlcnic_82xx_check(adapter)) |
1261 | handler = qlcnic_tmp_intr; | ||
1028 | if (!QLCNIC_IS_MSI_FAMILY(adapter)) | 1262 | if (!QLCNIC_IS_MSI_FAMILY(adapter)) |
1029 | flags |= IRQF_SHARED; | 1263 | flags |= IRQF_SHARED; |
1030 | 1264 | ||
@@ -1035,20 +1269,44 @@ qlcnic_request_irq(struct qlcnic_adapter *adapter) | |||
1035 | handler = qlcnic_msi_intr; | 1269 | handler = qlcnic_msi_intr; |
1036 | else { | 1270 | else { |
1037 | flags |= IRQF_SHARED; | 1271 | flags |= IRQF_SHARED; |
1038 | handler = qlcnic_intr; | 1272 | if (qlcnic_82xx_check(adapter)) |
1273 | handler = qlcnic_intr; | ||
1274 | else | ||
1275 | handler = qlcnic_83xx_intr; | ||
1039 | } | 1276 | } |
1040 | } | 1277 | } |
1041 | adapter->irq = netdev->irq; | 1278 | adapter->irq = netdev->irq; |
1042 | 1279 | ||
1043 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | 1280 | if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) { |
1044 | sds_ring = &recv_ctx->sds_rings[ring]; | 1281 | if (qlcnic_82xx_check(adapter) || |
1045 | sprintf(sds_ring->name, "%s[%d]", netdev->name, ring); | 1282 | (qlcnic_83xx_check(adapter) && |
1046 | err = request_irq(sds_ring->irq, handler, | 1283 | (adapter->flags & QLCNIC_MSIX_ENABLED))) { |
1047 | flags, sds_ring->name, sds_ring); | 1284 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
1048 | if (err) | 1285 | sds_ring = &recv_ctx->sds_rings[ring]; |
1049 | return err; | 1286 | snprintf(sds_ring->name, sizeof(int) + IFNAMSIZ, |
1287 | "%s[%d]", netdev->name, ring); | ||
1288 | err = request_irq(sds_ring->irq, handler, flags, | ||
1289 | sds_ring->name, sds_ring); | ||
1290 | if (err) | ||
1291 | return err; | ||
1292 | } | ||
1293 | } | ||
1294 | if (qlcnic_83xx_check(adapter) && | ||
1295 | (adapter->flags & QLCNIC_MSIX_ENABLED)) { | ||
1296 | handler = qlcnic_msix_tx_intr; | ||
1297 | for (ring = 0; ring < adapter->max_drv_tx_rings; | ||
1298 | ring++) { | ||
1299 | tx_ring = &adapter->tx_ring[ring]; | ||
1300 | snprintf(tx_ring->name, sizeof(int) + IFNAMSIZ, | ||
1301 | "%s[%d]", netdev->name, | ||
1302 | adapter->max_sds_rings + ring); | ||
1303 | err = request_irq(tx_ring->irq, handler, flags, | ||
1304 | tx_ring->name, tx_ring); | ||
1305 | if (err) | ||
1306 | return err; | ||
1307 | } | ||
1308 | } | ||
1050 | } | 1309 | } |
1051 | |||
1052 | return 0; | 1310 | return 0; |
1053 | } | 1311 | } |
1054 | 1312 | ||
@@ -1057,21 +1315,48 @@ qlcnic_free_irq(struct qlcnic_adapter *adapter) | |||
1057 | { | 1315 | { |
1058 | int ring; | 1316 | int ring; |
1059 | struct qlcnic_host_sds_ring *sds_ring; | 1317 | struct qlcnic_host_sds_ring *sds_ring; |
1318 | struct qlcnic_host_tx_ring *tx_ring; | ||
1060 | 1319 | ||
1061 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; | 1320 | struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; |
1062 | 1321 | ||
1063 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | 1322 | if (adapter->ahw->diag_test != QLCNIC_LOOPBACK_TEST) { |
1064 | sds_ring = &recv_ctx->sds_rings[ring]; | 1323 | if (qlcnic_82xx_check(adapter) || |
1065 | free_irq(sds_ring->irq, sds_ring); | 1324 | (qlcnic_83xx_check(adapter) && |
1325 | (adapter->flags & QLCNIC_MSIX_ENABLED))) { | ||
1326 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | ||
1327 | sds_ring = &recv_ctx->sds_rings[ring]; | ||
1328 | free_irq(sds_ring->irq, sds_ring); | ||
1329 | } | ||
1330 | } | ||
1331 | if (qlcnic_83xx_check(adapter)) { | ||
1332 | for (ring = 0; ring < adapter->max_drv_tx_rings; | ||
1333 | ring++) { | ||
1334 | tx_ring = &adapter->tx_ring[ring]; | ||
1335 | if (tx_ring->irq) | ||
1336 | free_irq(tx_ring->irq, tx_ring); | ||
1337 | } | ||
1338 | } | ||
1066 | } | 1339 | } |
1067 | } | 1340 | } |
1068 | 1341 | ||
1069 | static int | 1342 | static void qlcnic_get_lro_mss_capability(struct qlcnic_adapter *adapter) |
1070 | __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) | ||
1071 | { | 1343 | { |
1072 | int ring; | 1344 | u32 capab = 0; |
1073 | u32 capab2; | 1345 | |
1346 | if (qlcnic_82xx_check(adapter)) { | ||
1347 | if (adapter->ahw->capabilities2 & | ||
1348 | QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG) | ||
1349 | adapter->flags |= QLCNIC_FW_LRO_MSS_CAP; | ||
1350 | } else { | ||
1351 | capab = adapter->ahw->capabilities; | ||
1352 | if (QLC_83XX_GET_FW_LRO_MSS_CAPABILITY(capab)) | ||
1353 | adapter->flags |= QLCNIC_FW_LRO_MSS_CAP; | ||
1354 | } | ||
1355 | } | ||
1074 | 1356 | ||
1357 | int __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) | ||
1358 | { | ||
1359 | int ring; | ||
1075 | struct qlcnic_host_rds_ring *rds_ring; | 1360 | struct qlcnic_host_rds_ring *rds_ring; |
1076 | 1361 | ||
1077 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) | 1362 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) |
@@ -1081,19 +1366,14 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) | |||
1081 | return 0; | 1366 | return 0; |
1082 | if (qlcnic_set_eswitch_port_config(adapter)) | 1367 | if (qlcnic_set_eswitch_port_config(adapter)) |
1083 | return -EIO; | 1368 | return -EIO; |
1084 | 1369 | qlcnic_get_lro_mss_capability(adapter); | |
1085 | if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) { | ||
1086 | capab2 = QLCRD32(adapter, CRB_FW_CAPABILITIES_2); | ||
1087 | if (capab2 & QLCNIC_FW_CAPABILITY_2_LRO_MAX_TCP_SEG) | ||
1088 | adapter->flags |= QLCNIC_FW_LRO_MSS_CAP; | ||
1089 | } | ||
1090 | 1370 | ||
1091 | if (qlcnic_fw_create_ctx(adapter)) | 1371 | if (qlcnic_fw_create_ctx(adapter)) |
1092 | return -EIO; | 1372 | return -EIO; |
1093 | 1373 | ||
1094 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | 1374 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { |
1095 | rds_ring = &adapter->recv_ctx->rds_rings[ring]; | 1375 | rds_ring = &adapter->recv_ctx->rds_rings[ring]; |
1096 | qlcnic_post_rx_buffers(adapter, rds_ring); | 1376 | qlcnic_post_rx_buffers(adapter, rds_ring, ring); |
1097 | } | 1377 | } |
1098 | 1378 | ||
1099 | qlcnic_set_multi(netdev); | 1379 | qlcnic_set_multi(netdev); |
@@ -1118,10 +1398,7 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) | |||
1118 | return 0; | 1398 | return 0; |
1119 | } | 1399 | } |
1120 | 1400 | ||
1121 | /* Usage: During resume and firmware recovery module.*/ | 1401 | int qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) |
1122 | |||
1123 | static int | ||
1124 | qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) | ||
1125 | { | 1402 | { |
1126 | int err = 0; | 1403 | int err = 0; |
1127 | 1404 | ||
@@ -1133,8 +1410,7 @@ qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev) | |||
1133 | return err; | 1410 | return err; |
1134 | } | 1411 | } |
1135 | 1412 | ||
1136 | static void | 1413 | void __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) |
1137 | __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) | ||
1138 | { | 1414 | { |
1139 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) | 1415 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) |
1140 | return; | 1416 | return; |
@@ -1166,8 +1442,7 @@ __qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) | |||
1166 | 1442 | ||
1167 | /* Usage: During suspend and firmware recovery module */ | 1443 | /* Usage: During suspend and firmware recovery module */ |
1168 | 1444 | ||
1169 | static void | 1445 | void qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) |
1170 | qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) | ||
1171 | { | 1446 | { |
1172 | rtnl_lock(); | 1447 | rtnl_lock(); |
1173 | if (netif_running(netdev)) | 1448 | if (netif_running(netdev)) |
@@ -1176,7 +1451,7 @@ qlcnic_down(struct qlcnic_adapter *adapter, struct net_device *netdev) | |||
1176 | 1451 | ||
1177 | } | 1452 | } |
1178 | 1453 | ||
1179 | static int | 1454 | int |
1180 | qlcnic_attach(struct qlcnic_adapter *adapter) | 1455 | qlcnic_attach(struct qlcnic_adapter *adapter) |
1181 | { | 1456 | { |
1182 | struct net_device *netdev = adapter->netdev; | 1457 | struct net_device *netdev = adapter->netdev; |
@@ -1222,8 +1497,7 @@ err_out_napi_del: | |||
1222 | return err; | 1497 | return err; |
1223 | } | 1498 | } |
1224 | 1499 | ||
1225 | static void | 1500 | void qlcnic_detach(struct qlcnic_adapter *adapter) |
1226 | qlcnic_detach(struct qlcnic_adapter *adapter) | ||
1227 | { | 1501 | { |
1228 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) | 1502 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) |
1229 | return; | 1503 | return; |
@@ -1272,21 +1546,9 @@ out: | |||
1272 | static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter) | 1546 | static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter) |
1273 | { | 1547 | { |
1274 | int err = 0; | 1548 | int err = 0; |
1275 | adapter->ahw = kzalloc(sizeof(struct qlcnic_hardware_context), | ||
1276 | GFP_KERNEL); | ||
1277 | if (!adapter->ahw) { | ||
1278 | dev_err(&adapter->pdev->dev, | ||
1279 | "Failed to allocate recv ctx resources for adapter\n"); | ||
1280 | err = -ENOMEM; | ||
1281 | goto err_out; | ||
1282 | } | ||
1283 | adapter->recv_ctx = kzalloc(sizeof(struct qlcnic_recv_context), | 1549 | adapter->recv_ctx = kzalloc(sizeof(struct qlcnic_recv_context), |
1284 | GFP_KERNEL); | 1550 | GFP_KERNEL); |
1285 | if (!adapter->recv_ctx) { | 1551 | if (!adapter->recv_ctx) { |
1286 | dev_err(&adapter->pdev->dev, | ||
1287 | "Failed to allocate recv ctx resources for adapter\n"); | ||
1288 | kfree(adapter->ahw); | ||
1289 | adapter->ahw = NULL; | ||
1290 | err = -ENOMEM; | 1552 | err = -ENOMEM; |
1291 | goto err_out; | 1553 | goto err_out; |
1292 | } | 1554 | } |
@@ -1294,6 +1556,8 @@ static int qlcnic_alloc_adapter_resources(struct qlcnic_adapter *adapter) | |||
1294 | adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT; | 1556 | adapter->ahw->coal.flag = QLCNIC_INTR_DEFAULT; |
1295 | adapter->ahw->coal.rx_time_us = QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US; | 1557 | adapter->ahw->coal.rx_time_us = QLCNIC_DEFAULT_INTR_COALESCE_RX_TIME_US; |
1296 | adapter->ahw->coal.rx_packets = QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS; | 1558 | adapter->ahw->coal.rx_packets = QLCNIC_DEFAULT_INTR_COALESCE_RX_PACKETS; |
1559 | /* clear stats */ | ||
1560 | memset(&adapter->stats, 0, sizeof(adapter->stats)); | ||
1297 | err_out: | 1561 | err_out: |
1298 | return err; | 1562 | return err; |
1299 | } | 1563 | } |
@@ -1307,8 +1571,9 @@ static void qlcnic_free_adapter_resources(struct qlcnic_adapter *adapter) | |||
1307 | vfree(adapter->ahw->fw_dump.tmpl_hdr); | 1571 | vfree(adapter->ahw->fw_dump.tmpl_hdr); |
1308 | adapter->ahw->fw_dump.tmpl_hdr = NULL; | 1572 | adapter->ahw->fw_dump.tmpl_hdr = NULL; |
1309 | } | 1573 | } |
1310 | kfree(adapter->ahw); | 1574 | |
1311 | adapter->ahw = NULL; | 1575 | kfree(adapter->ahw->reset.buff); |
1576 | adapter->ahw->fw_dump.tmpl_hdr = NULL; | ||
1312 | } | 1577 | } |
1313 | 1578 | ||
1314 | int qlcnic_diag_alloc_res(struct net_device *netdev, int test) | 1579 | int qlcnic_diag_alloc_res(struct net_device *netdev, int test) |
@@ -1328,6 +1593,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test) | |||
1328 | 1593 | ||
1329 | adapter->max_sds_rings = 1; | 1594 | adapter->max_sds_rings = 1; |
1330 | adapter->ahw->diag_test = test; | 1595 | adapter->ahw->diag_test = test; |
1596 | adapter->ahw->linkup = 0; | ||
1331 | 1597 | ||
1332 | ret = qlcnic_attach(adapter); | 1598 | ret = qlcnic_attach(adapter); |
1333 | if (ret) { | 1599 | if (ret) { |
@@ -1344,7 +1610,7 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test) | |||
1344 | 1610 | ||
1345 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { | 1611 | for (ring = 0; ring < adapter->max_rds_rings; ring++) { |
1346 | rds_ring = &adapter->recv_ctx->rds_rings[ring]; | 1612 | rds_ring = &adapter->recv_ctx->rds_rings[ring]; |
1347 | qlcnic_post_rx_buffers(adapter, rds_ring); | 1613 | qlcnic_post_rx_buffers(adapter, rds_ring, ring); |
1348 | } | 1614 | } |
1349 | 1615 | ||
1350 | if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) { | 1616 | if (adapter->ahw->diag_test == QLCNIC_INTERRUPT_TEST) { |
@@ -1382,6 +1648,7 @@ qlcnic_reset_hw_context(struct qlcnic_adapter *adapter) | |||
1382 | netif_device_attach(netdev); | 1648 | netif_device_attach(netdev); |
1383 | 1649 | ||
1384 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 1650 | clear_bit(__QLCNIC_RESETTING, &adapter->state); |
1651 | dev_err(&adapter->pdev->dev, "%s:\n", __func__); | ||
1385 | return 0; | 1652 | return 0; |
1386 | } | 1653 | } |
1387 | 1654 | ||
@@ -1425,34 +1692,40 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev, | |||
1425 | int err; | 1692 | int err; |
1426 | struct pci_dev *pdev = adapter->pdev; | 1693 | struct pci_dev *pdev = adapter->pdev; |
1427 | 1694 | ||
1695 | adapter->rx_csum = 1; | ||
1428 | adapter->ahw->mc_enabled = 0; | 1696 | adapter->ahw->mc_enabled = 0; |
1429 | adapter->ahw->max_mc_count = 38; | 1697 | adapter->ahw->max_mc_count = QLCNIC_MAX_MC_COUNT; |
1430 | 1698 | ||
1431 | netdev->netdev_ops = &qlcnic_netdev_ops; | 1699 | netdev->netdev_ops = &qlcnic_netdev_ops; |
1432 | netdev->watchdog_timeo = 5*HZ; | 1700 | netdev->watchdog_timeo = QLCNIC_WATCHDOG_TIMEOUTVALUE * HZ; |
1433 | 1701 | ||
1434 | qlcnic_change_mtu(netdev, netdev->mtu); | 1702 | qlcnic_change_mtu(netdev, netdev->mtu); |
1435 | 1703 | ||
1436 | SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops); | 1704 | SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_ops); |
1437 | 1705 | ||
1438 | netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | | 1706 | netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM | |
1439 | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM; | 1707 | NETIF_F_IPV6_CSUM | NETIF_F_GRO | |
1708 | NETIF_F_HW_VLAN_RX); | ||
1709 | netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | | ||
1710 | NETIF_F_IPV6_CSUM); | ||
1711 | |||
1712 | if (QLCNIC_IS_TSO_CAPABLE(adapter)) { | ||
1713 | netdev->features |= (NETIF_F_TSO | NETIF_F_TSO6); | ||
1714 | netdev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6); | ||
1715 | } | ||
1440 | 1716 | ||
1441 | if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_TSO) | 1717 | if (pci_using_dac) { |
1442 | netdev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6; | 1718 | netdev->features |= NETIF_F_HIGHDMA; |
1443 | if (pci_using_dac == 1) | 1719 | netdev->vlan_features |= NETIF_F_HIGHDMA; |
1444 | netdev->hw_features |= NETIF_F_HIGHDMA; | 1720 | } |
1445 | 1721 | ||
1446 | netdev->vlan_features = netdev->hw_features; | 1722 | if (qlcnic_vlan_tx_check(adapter)) |
1723 | netdev->features |= (NETIF_F_HW_VLAN_TX); | ||
1447 | 1724 | ||
1448 | if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_FVLANTX) | ||
1449 | netdev->hw_features |= NETIF_F_HW_VLAN_TX; | ||
1450 | if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO) | 1725 | if (adapter->ahw->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO) |
1451 | netdev->hw_features |= NETIF_F_LRO; | 1726 | netdev->features |= NETIF_F_LRO; |
1452 | |||
1453 | netdev->features |= netdev->hw_features | | ||
1454 | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; | ||
1455 | 1727 | ||
1728 | netdev->hw_features = netdev->features; | ||
1456 | netdev->irq = adapter->msix_entries[0].vector; | 1729 | netdev->irq = adapter->msix_entries[0].vector; |
1457 | 1730 | ||
1458 | err = register_netdev(netdev); | 1731 | err = register_netdev(netdev); |
@@ -1480,17 +1753,61 @@ static int qlcnic_set_dma_mask(struct pci_dev *pdev, int *pci_using_dac) | |||
1480 | return 0; | 1753 | return 0; |
1481 | } | 1754 | } |
1482 | 1755 | ||
1483 | static int | 1756 | void qlcnic_free_tx_rings(struct qlcnic_adapter *adapter) |
1484 | qlcnic_alloc_msix_entries(struct qlcnic_adapter *adapter, u16 count) | ||
1485 | { | 1757 | { |
1486 | adapter->msix_entries = kcalloc(count, sizeof(struct msix_entry), | 1758 | int ring; |
1487 | GFP_KERNEL); | 1759 | struct qlcnic_host_tx_ring *tx_ring; |
1488 | 1760 | ||
1489 | if (adapter->msix_entries) | 1761 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { |
1490 | return 0; | 1762 | tx_ring = &adapter->tx_ring[ring]; |
1763 | if (tx_ring && tx_ring->cmd_buf_arr != NULL) { | ||
1764 | vfree(tx_ring->cmd_buf_arr); | ||
1765 | tx_ring->cmd_buf_arr = NULL; | ||
1766 | } | ||
1767 | } | ||
1768 | if (adapter->tx_ring != NULL) | ||
1769 | kfree(adapter->tx_ring); | ||
1770 | } | ||
1771 | |||
1772 | int qlcnic_alloc_tx_rings(struct qlcnic_adapter *adapter, | ||
1773 | struct net_device *netdev) | ||
1774 | { | ||
1775 | int ring, vector, index; | ||
1776 | struct qlcnic_host_tx_ring *tx_ring; | ||
1777 | struct qlcnic_cmd_buffer *cmd_buf_arr; | ||
1778 | |||
1779 | tx_ring = kcalloc(adapter->max_drv_tx_rings, | ||
1780 | sizeof(struct qlcnic_host_tx_ring), GFP_KERNEL); | ||
1781 | if (tx_ring == NULL) | ||
1782 | return -ENOMEM; | ||
1491 | 1783 | ||
1492 | dev_err(&adapter->pdev->dev, "failed allocating msix_entries\n"); | 1784 | adapter->tx_ring = tx_ring; |
1493 | return -ENOMEM; | 1785 | |
1786 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | ||
1787 | tx_ring = &adapter->tx_ring[ring]; | ||
1788 | tx_ring->num_desc = adapter->num_txd; | ||
1789 | tx_ring->txq = netdev_get_tx_queue(netdev, ring); | ||
1790 | cmd_buf_arr = vzalloc(TX_BUFF_RINGSIZE(tx_ring)); | ||
1791 | if (cmd_buf_arr == NULL) { | ||
1792 | qlcnic_free_tx_rings(adapter); | ||
1793 | return -ENOMEM; | ||
1794 | } | ||
1795 | memset(cmd_buf_arr, 0, TX_BUFF_RINGSIZE(tx_ring)); | ||
1796 | tx_ring->cmd_buf_arr = cmd_buf_arr; | ||
1797 | } | ||
1798 | |||
1799 | if (qlcnic_83xx_check(adapter)) { | ||
1800 | for (ring = 0; ring < adapter->max_drv_tx_rings; ring++) { | ||
1801 | tx_ring = &adapter->tx_ring[ring]; | ||
1802 | tx_ring->adapter = adapter; | ||
1803 | if (adapter->flags & QLCNIC_MSIX_ENABLED) { | ||
1804 | index = adapter->max_sds_rings + ring; | ||
1805 | vector = adapter->msix_entries[index].vector; | ||
1806 | tx_ring->irq = vector; | ||
1807 | } | ||
1808 | } | ||
1809 | } | ||
1810 | return 0; | ||
1494 | } | 1811 | } |
1495 | 1812 | ||
1496 | static int | 1813 | static int |
@@ -1498,9 +1815,10 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1498 | { | 1815 | { |
1499 | struct net_device *netdev = NULL; | 1816 | struct net_device *netdev = NULL; |
1500 | struct qlcnic_adapter *adapter = NULL; | 1817 | struct qlcnic_adapter *adapter = NULL; |
1818 | struct qlcnic_hardware_context *ahw; | ||
1501 | int err, pci_using_dac = -1; | 1819 | int err, pci_using_dac = -1; |
1502 | uint8_t revision_id; | 1820 | u32 capab2; |
1503 | char board_name[QLCNIC_MAX_BOARD_NAME_LEN]; | 1821 | char board_name[QLCNIC_MAX_BOARD_NAME_LEN + 19]; /* MAC + ": " + name */ |
1504 | 1822 | ||
1505 | err = pci_enable_device(pdev); | 1823 | err = pci_enable_device(pdev); |
1506 | if (err) | 1824 | if (err) |
@@ -1522,10 +1840,27 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1522 | pci_set_master(pdev); | 1840 | pci_set_master(pdev); |
1523 | pci_enable_pcie_error_reporting(pdev); | 1841 | pci_enable_pcie_error_reporting(pdev); |
1524 | 1842 | ||
1843 | ahw = kzalloc(sizeof(struct qlcnic_hardware_context), GFP_KERNEL); | ||
1844 | if (!ahw) | ||
1845 | goto err_out_free_res; | ||
1846 | |||
1847 | if (ent->device == PCI_DEVICE_ID_QLOGIC_QLE824X) { | ||
1848 | ahw->hw_ops = &qlcnic_hw_ops; | ||
1849 | ahw->reg_tbl = (u32 *)qlcnic_reg_tbl; | ||
1850 | } else if (ent->device == PCI_DEVICE_ID_QLOGIC_QLE834X) { | ||
1851 | qlcnic_83xx_register_map(ahw); | ||
1852 | } else { | ||
1853 | goto err_out_free_hw_res; | ||
1854 | } | ||
1855 | |||
1856 | err = qlcnic_setup_pci_map(pdev, ahw); | ||
1857 | if (err) | ||
1858 | goto err_out_free_hw_res; | ||
1859 | |||
1525 | netdev = alloc_etherdev(sizeof(struct qlcnic_adapter)); | 1860 | netdev = alloc_etherdev(sizeof(struct qlcnic_adapter)); |
1526 | if (!netdev) { | 1861 | if (!netdev) { |
1527 | err = -ENOMEM; | 1862 | err = -ENOMEM; |
1528 | goto err_out_free_res; | 1863 | goto err_out_iounmap; |
1529 | } | 1864 | } |
1530 | 1865 | ||
1531 | SET_NETDEV_DEV(netdev, &pdev->dev); | 1866 | SET_NETDEV_DEV(netdev, &pdev->dev); |
@@ -1533,15 +1868,25 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1533 | adapter = netdev_priv(netdev); | 1868 | adapter = netdev_priv(netdev); |
1534 | adapter->netdev = netdev; | 1869 | adapter->netdev = netdev; |
1535 | adapter->pdev = pdev; | 1870 | adapter->pdev = pdev; |
1871 | adapter->ahw = ahw; | ||
1872 | |||
1873 | adapter->qlcnic_wq = create_singlethread_workqueue("qlcnic"); | ||
1874 | if (adapter->qlcnic_wq == NULL) { | ||
1875 | dev_err(&pdev->dev, "Failed to create workqueue\n"); | ||
1876 | goto err_out_free_netdev; | ||
1877 | } | ||
1536 | 1878 | ||
1537 | err = qlcnic_alloc_adapter_resources(adapter); | 1879 | err = qlcnic_alloc_adapter_resources(adapter); |
1538 | if (err) | 1880 | if (err) |
1539 | goto err_out_free_netdev; | 1881 | goto err_out_free_netdev; |
1540 | 1882 | ||
1541 | adapter->dev_rst_time = jiffies; | 1883 | adapter->dev_rst_time = jiffies; |
1542 | revision_id = pdev->revision; | 1884 | adapter->ahw->revision_id = pdev->revision; |
1543 | adapter->ahw->revision_id = revision_id; | 1885 | if (qlcnic_mac_learn == FDB_MAC_LEARN) |
1544 | adapter->mac_learn = qlcnic_mac_learn; | 1886 | adapter->fdb_mac_learn = true; |
1887 | else if (qlcnic_mac_learn == DRV_MAC_LEARN) | ||
1888 | adapter->drv_mac_learn = true; | ||
1889 | adapter->max_drv_tx_rings = 1; | ||
1545 | 1890 | ||
1546 | rwlock_init(&adapter->ahw->crb_lock); | 1891 | rwlock_init(&adapter->ahw->crb_lock); |
1547 | mutex_init(&adapter->ahw->mem_lock); | 1892 | mutex_init(&adapter->ahw->mem_lock); |
@@ -1549,31 +1894,32 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1549 | spin_lock_init(&adapter->tx_clean_lock); | 1894 | spin_lock_init(&adapter->tx_clean_lock); |
1550 | INIT_LIST_HEAD(&adapter->mac_list); | 1895 | INIT_LIST_HEAD(&adapter->mac_list); |
1551 | 1896 | ||
1552 | err = qlcnic_setup_pci_map(pdev, adapter->ahw); | 1897 | if (qlcnic_82xx_check(adapter)) { |
1553 | if (err) | 1898 | qlcnic_check_vf(adapter, ent); |
1554 | goto err_out_free_hw; | 1899 | adapter->portnum = adapter->ahw->pci_func; |
1555 | qlcnic_check_vf(adapter); | 1900 | err = qlcnic_start_firmware(adapter); |
1556 | 1901 | if (err) { | |
1557 | /* This will be reset for mezz cards */ | 1902 | dev_err(&pdev->dev, "Loading fw failed.Please Reboot\n"); |
1558 | adapter->portnum = adapter->ahw->pci_func; | 1903 | goto err_out_free_hw; |
1559 | 1904 | } | |
1560 | err = qlcnic_get_board_info(adapter); | ||
1561 | if (err) { | ||
1562 | dev_err(&pdev->dev, "Error getting board config info.\n"); | ||
1563 | goto err_out_iounmap; | ||
1564 | } | ||
1565 | |||
1566 | err = qlcnic_setup_idc_param(adapter); | ||
1567 | if (err) | ||
1568 | goto err_out_iounmap; | ||
1569 | 1905 | ||
1570 | adapter->flags |= QLCNIC_NEED_FLR; | 1906 | err = qlcnic_setup_idc_param(adapter); |
1907 | if (err) | ||
1908 | goto err_out_free_hw; | ||
1571 | 1909 | ||
1572 | err = adapter->nic_ops->start_firmware(adapter); | 1910 | adapter->flags |= QLCNIC_NEED_FLR; |
1573 | if (err) { | 1911 | } else if (qlcnic_83xx_check(adapter)) { |
1574 | dev_err(&pdev->dev, "Loading fw failed. Please Reboot\n" | 1912 | qlcnic_83xx_check_vf(adapter, ent); |
1575 | "\t\tIf reboot doesn't help, try flashing the card\n"); | 1913 | adapter->portnum = adapter->ahw->pci_func; |
1576 | goto err_out_maintenance_mode; | 1914 | err = qlcnic_83xx_init(adapter); |
1915 | if (err) { | ||
1916 | dev_err(&pdev->dev, "%s: failed\n", __func__); | ||
1917 | goto err_out_free_hw; | ||
1918 | } | ||
1919 | } else { | ||
1920 | dev_err(&pdev->dev, | ||
1921 | "%s: failed. Please Reboot\n", __func__); | ||
1922 | goto err_out_free_hw; | ||
1577 | } | 1923 | } |
1578 | 1924 | ||
1579 | if (qlcnic_read_mac_addr(adapter)) | 1925 | if (qlcnic_read_mac_addr(adapter)) |
@@ -1581,22 +1927,34 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1581 | 1927 | ||
1582 | if (adapter->portnum == 0) { | 1928 | if (adapter->portnum == 0) { |
1583 | qlcnic_get_board_name(adapter, board_name); | 1929 | qlcnic_get_board_name(adapter, board_name); |
1930 | |||
1584 | pr_info("%s: %s Board Chip rev 0x%x\n", | 1931 | pr_info("%s: %s Board Chip rev 0x%x\n", |
1585 | module_name(THIS_MODULE), | 1932 | module_name(THIS_MODULE), |
1586 | board_name, adapter->ahw->revision_id); | 1933 | board_name, adapter->ahw->revision_id); |
1587 | } | 1934 | } |
1935 | err = qlcnic_setup_intr(adapter, 0); | ||
1936 | if (err) { | ||
1937 | dev_err(&pdev->dev, "Failed to setup interrupt\n"); | ||
1938 | goto err_out_disable_msi; | ||
1939 | } | ||
1588 | 1940 | ||
1589 | qlcnic_clear_stats(adapter); | 1941 | if (qlcnic_83xx_check(adapter)) { |
1590 | 1942 | err = qlcnic_83xx_setup_mbx_intr(adapter); | |
1591 | err = qlcnic_alloc_msix_entries(adapter, adapter->ahw->max_rx_ques); | 1943 | if (err) |
1592 | if (err) | 1944 | goto err_out_disable_msi; |
1593 | goto err_out_decr_ref; | 1945 | } |
1594 | |||
1595 | qlcnic_setup_intr(adapter); | ||
1596 | 1946 | ||
1597 | err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac); | 1947 | err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac); |
1598 | if (err) | 1948 | if (err) |
1599 | goto err_out_disable_msi; | 1949 | goto err_out_disable_mbx_intr; |
1950 | |||
1951 | if (qlcnic_82xx_check(adapter)) { | ||
1952 | if (ahw->capabilities & QLCNIC_FW_CAPABILITY_MORE_CAPS) { | ||
1953 | capab2 = QLCRD32(adapter, CRB_FW_CAPABILITIES_2); | ||
1954 | if (capab2 & QLCNIC_FW_CAPABILITY_2_OCBB) | ||
1955 | qlcnic_fw_cmd_set_drv_version(adapter); | ||
1956 | } | ||
1957 | } | ||
1600 | 1958 | ||
1601 | pci_set_drvdata(pdev, adapter); | 1959 | pci_set_drvdata(pdev, adapter); |
1602 | 1960 | ||
@@ -1615,29 +1973,37 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1615 | break; | 1973 | break; |
1616 | } | 1974 | } |
1617 | 1975 | ||
1618 | if (adapter->mac_learn) | 1976 | if (qlcnic_get_act_pci_func(adapter)) |
1977 | goto err_out_disable_mbx_intr; | ||
1978 | |||
1979 | if (adapter->drv_mac_learn) | ||
1619 | qlcnic_alloc_lb_filters_mem(adapter); | 1980 | qlcnic_alloc_lb_filters_mem(adapter); |
1620 | 1981 | ||
1621 | qlcnic_create_diag_entries(adapter); | 1982 | qlcnic_add_sysfs(adapter); |
1622 | 1983 | ||
1623 | return 0; | 1984 | return 0; |
1624 | 1985 | ||
1986 | err_out_disable_mbx_intr: | ||
1987 | if (qlcnic_83xx_check(adapter)) | ||
1988 | qlcnic_83xx_free_mbx_intr(adapter); | ||
1989 | |||
1625 | err_out_disable_msi: | 1990 | err_out_disable_msi: |
1626 | qlcnic_teardown_intr(adapter); | 1991 | qlcnic_teardown_intr(adapter); |
1627 | kfree(adapter->msix_entries); | 1992 | qlcnic_cancel_idc_work(adapter); |
1628 | |||
1629 | err_out_decr_ref: | ||
1630 | qlcnic_clr_all_drv_state(adapter, 0); | 1993 | qlcnic_clr_all_drv_state(adapter, 0); |
1631 | 1994 | ||
1632 | err_out_iounmap: | ||
1633 | qlcnic_cleanup_pci_map(adapter); | ||
1634 | |||
1635 | err_out_free_hw: | 1995 | err_out_free_hw: |
1636 | qlcnic_free_adapter_resources(adapter); | 1996 | qlcnic_free_adapter_resources(adapter); |
1637 | 1997 | ||
1638 | err_out_free_netdev: | 1998 | err_out_free_netdev: |
1639 | free_netdev(netdev); | 1999 | free_netdev(netdev); |
1640 | 2000 | ||
2001 | err_out_iounmap: | ||
2002 | qlcnic_cleanup_pci_map(adapter); | ||
2003 | |||
2004 | err_out_free_hw_res: | ||
2005 | kfree(ahw); | ||
2006 | |||
1641 | err_out_free_res: | 2007 | err_out_free_res: |
1642 | pci_release_regions(pdev); | 2008 | pci_release_regions(pdev); |
1643 | 2009 | ||
@@ -1645,24 +2011,13 @@ err_out_disable_pdev: | |||
1645 | pci_set_drvdata(pdev, NULL); | 2011 | pci_set_drvdata(pdev, NULL); |
1646 | pci_disable_device(pdev); | 2012 | pci_disable_device(pdev); |
1647 | return err; | 2013 | return err; |
1648 | |||
1649 | err_out_maintenance_mode: | ||
1650 | netdev->netdev_ops = &qlcnic_netdev_failed_ops; | ||
1651 | SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_failed_ops); | ||
1652 | err = register_netdev(netdev); | ||
1653 | if (err) { | ||
1654 | dev_err(&pdev->dev, "failed to register net device\n"); | ||
1655 | goto err_out_decr_ref; | ||
1656 | } | ||
1657 | pci_set_drvdata(pdev, adapter); | ||
1658 | qlcnic_create_diag_entries(adapter); | ||
1659 | return 0; | ||
1660 | } | 2014 | } |
1661 | 2015 | ||
1662 | static void qlcnic_remove(struct pci_dev *pdev) | 2016 | static void qlcnic_remove(struct pci_dev *pdev) |
1663 | { | 2017 | { |
1664 | struct qlcnic_adapter *adapter; | 2018 | struct qlcnic_adapter *adapter; |
1665 | struct net_device *netdev; | 2019 | struct net_device *netdev; |
2020 | struct qlcnic_hardware_context *ahw; | ||
1666 | 2021 | ||
1667 | adapter = pci_get_drvdata(pdev); | 2022 | adapter = pci_get_drvdata(pdev); |
1668 | if (adapter == NULL) | 2023 | if (adapter == NULL) |
@@ -1670,10 +2025,17 @@ static void qlcnic_remove(struct pci_dev *pdev) | |||
1670 | 2025 | ||
1671 | netdev = adapter->netdev; | 2026 | netdev = adapter->netdev; |
1672 | 2027 | ||
1673 | qlcnic_cancel_fw_work(adapter); | 2028 | qlcnic_cancel_idc_work(adapter); |
2029 | ahw = adapter->ahw; | ||
1674 | 2030 | ||
1675 | unregister_netdev(netdev); | 2031 | unregister_netdev(netdev); |
1676 | 2032 | ||
2033 | if (qlcnic_83xx_check(adapter)) { | ||
2034 | qlcnic_83xx_free_mbx_intr(adapter); | ||
2035 | qlcnic_83xx_register_nic_idc_func(adapter, 0); | ||
2036 | cancel_delayed_work_sync(&adapter->idc_aen_work); | ||
2037 | } | ||
2038 | |||
1677 | qlcnic_detach(adapter); | 2039 | qlcnic_detach(adapter); |
1678 | 2040 | ||
1679 | if (adapter->npars != NULL) | 2041 | if (adapter->npars != NULL) |
@@ -1689,9 +2051,8 @@ static void qlcnic_remove(struct pci_dev *pdev) | |||
1689 | qlcnic_free_lb_filters_mem(adapter); | 2051 | qlcnic_free_lb_filters_mem(adapter); |
1690 | 2052 | ||
1691 | qlcnic_teardown_intr(adapter); | 2053 | qlcnic_teardown_intr(adapter); |
1692 | kfree(adapter->msix_entries); | ||
1693 | 2054 | ||
1694 | qlcnic_remove_diag_entries(adapter); | 2055 | qlcnic_remove_sysfs(adapter); |
1695 | 2056 | ||
1696 | qlcnic_cleanup_pci_map(adapter); | 2057 | qlcnic_cleanup_pci_map(adapter); |
1697 | 2058 | ||
@@ -1702,7 +2063,12 @@ static void qlcnic_remove(struct pci_dev *pdev) | |||
1702 | pci_disable_device(pdev); | 2063 | pci_disable_device(pdev); |
1703 | pci_set_drvdata(pdev, NULL); | 2064 | pci_set_drvdata(pdev, NULL); |
1704 | 2065 | ||
2066 | if (adapter->qlcnic_wq) { | ||
2067 | destroy_workqueue(adapter->qlcnic_wq); | ||
2068 | adapter->qlcnic_wq = NULL; | ||
2069 | } | ||
1705 | qlcnic_free_adapter_resources(adapter); | 2070 | qlcnic_free_adapter_resources(adapter); |
2071 | kfree(ahw); | ||
1706 | free_netdev(netdev); | 2072 | free_netdev(netdev); |
1707 | } | 2073 | } |
1708 | static int __qlcnic_shutdown(struct pci_dev *pdev) | 2074 | static int __qlcnic_shutdown(struct pci_dev *pdev) |
@@ -1713,7 +2079,7 @@ static int __qlcnic_shutdown(struct pci_dev *pdev) | |||
1713 | 2079 | ||
1714 | netif_device_detach(netdev); | 2080 | netif_device_detach(netdev); |
1715 | 2081 | ||
1716 | qlcnic_cancel_fw_work(adapter); | 2082 | qlcnic_cancel_idc_work(adapter); |
1717 | 2083 | ||
1718 | if (netif_running(netdev)) | 2084 | if (netif_running(netdev)) |
1719 | qlcnic_down(adapter, netdev); | 2085 | qlcnic_down(adapter, netdev); |
@@ -1726,7 +2092,6 @@ static int __qlcnic_shutdown(struct pci_dev *pdev) | |||
1726 | retval = pci_save_state(pdev); | 2092 | retval = pci_save_state(pdev); |
1727 | if (retval) | 2093 | if (retval) |
1728 | return retval; | 2094 | return retval; |
1729 | |||
1730 | if (qlcnic_82xx_check(adapter)) { | 2095 | if (qlcnic_82xx_check(adapter)) { |
1731 | if (qlcnic_wol_supported(adapter)) { | 2096 | if (qlcnic_wol_supported(adapter)) { |
1732 | pci_enable_wake(pdev, PCI_D3cold, 1); | 2097 | pci_enable_wake(pdev, PCI_D3cold, 1); |
@@ -1774,7 +2139,7 @@ qlcnic_resume(struct pci_dev *pdev) | |||
1774 | pci_set_master(pdev); | 2139 | pci_set_master(pdev); |
1775 | pci_restore_state(pdev); | 2140 | pci_restore_state(pdev); |
1776 | 2141 | ||
1777 | err = adapter->nic_ops->start_firmware(adapter); | 2142 | err = qlcnic_start_firmware(adapter); |
1778 | if (err) { | 2143 | if (err) { |
1779 | dev_err(&pdev->dev, "failed to start firmware\n"); | 2144 | dev_err(&pdev->dev, "failed to start firmware\n"); |
1780 | return err; | 2145 | return err; |
@@ -1797,14 +2162,8 @@ done: | |||
1797 | static int qlcnic_open(struct net_device *netdev) | 2162 | static int qlcnic_open(struct net_device *netdev) |
1798 | { | 2163 | { |
1799 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 2164 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
1800 | u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); | ||
1801 | int err; | 2165 | int err; |
1802 | 2166 | ||
1803 | if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) { | ||
1804 | netdev_err(netdev, "Device in FAILED state\n"); | ||
1805 | return -EIO; | ||
1806 | } | ||
1807 | |||
1808 | netif_carrier_off(netdev); | 2167 | netif_carrier_off(netdev); |
1809 | 2168 | ||
1810 | err = qlcnic_attach(adapter); | 2169 | err = qlcnic_attach(adapter); |
@@ -1832,6 +2191,7 @@ static int qlcnic_close(struct net_device *netdev) | |||
1832 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 2191 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
1833 | 2192 | ||
1834 | __qlcnic_down(adapter, netdev); | 2193 | __qlcnic_down(adapter, netdev); |
2194 | |||
1835 | return 0; | 2195 | return 0; |
1836 | } | 2196 | } |
1837 | 2197 | ||
@@ -1839,22 +2199,53 @@ void qlcnic_alloc_lb_filters_mem(struct qlcnic_adapter *adapter) | |||
1839 | { | 2199 | { |
1840 | void *head; | 2200 | void *head; |
1841 | int i; | 2201 | int i; |
2202 | struct net_device *netdev = adapter->netdev; | ||
2203 | u32 filter_size = 0; | ||
2204 | u16 act_pci_func = 0; | ||
1842 | 2205 | ||
1843 | if (adapter->fhash.fmax && adapter->fhash.fhead) | 2206 | if (adapter->fhash.fmax && adapter->fhash.fhead) |
1844 | return; | 2207 | return; |
1845 | 2208 | ||
2209 | act_pci_func = adapter->ahw->act_pci_func; | ||
1846 | spin_lock_init(&adapter->mac_learn_lock); | 2210 | spin_lock_init(&adapter->mac_learn_lock); |
2211 | spin_lock_init(&adapter->rx_mac_learn_lock); | ||
2212 | |||
2213 | if (qlcnic_82xx_check(adapter)) { | ||
2214 | filter_size = QLCNIC_LB_MAX_FILTERS; | ||
2215 | adapter->fhash.fbucket_size = QLCNIC_LB_BUCKET_SIZE; | ||
2216 | } else { | ||
2217 | filter_size = QLC_83XX_LB_MAX_FILTERS; | ||
2218 | adapter->fhash.fbucket_size = QLC_83XX_LB_BUCKET_SIZE; | ||
2219 | } | ||
2220 | |||
2221 | head = kcalloc(adapter->fhash.fbucket_size, | ||
2222 | sizeof(struct hlist_head), GFP_ATOMIC); | ||
1847 | 2223 | ||
1848 | head = kcalloc(QLCNIC_LB_MAX_FILTERS, sizeof(struct hlist_head), | ||
1849 | GFP_KERNEL); | ||
1850 | if (!head) | 2224 | if (!head) |
1851 | return; | 2225 | return; |
1852 | 2226 | ||
1853 | adapter->fhash.fmax = QLCNIC_LB_MAX_FILTERS; | 2227 | adapter->fhash.fmax = (filter_size / act_pci_func); |
1854 | adapter->fhash.fhead = head; | 2228 | adapter->fhash.fhead = head; |
1855 | 2229 | ||
1856 | for (i = 0; i < adapter->fhash.fmax; i++) | 2230 | netdev_info(netdev, "active nic func = %d, mac filter size=%d\n", |
2231 | act_pci_func, adapter->fhash.fmax); | ||
2232 | |||
2233 | for (i = 0; i < adapter->fhash.fbucket_size; i++) | ||
1857 | INIT_HLIST_HEAD(&adapter->fhash.fhead[i]); | 2234 | INIT_HLIST_HEAD(&adapter->fhash.fhead[i]); |
2235 | |||
2236 | adapter->rx_fhash.fbucket_size = adapter->fhash.fbucket_size; | ||
2237 | |||
2238 | head = kcalloc(adapter->rx_fhash.fbucket_size, | ||
2239 | sizeof(struct hlist_head), GFP_ATOMIC); | ||
2240 | |||
2241 | if (!head) | ||
2242 | return; | ||
2243 | |||
2244 | adapter->rx_fhash.fmax = (filter_size / act_pci_func); | ||
2245 | adapter->rx_fhash.fhead = head; | ||
2246 | |||
2247 | for (i = 0; i < adapter->rx_fhash.fbucket_size; i++) | ||
2248 | INIT_HLIST_HEAD(&adapter->rx_fhash.fhead[i]); | ||
1858 | } | 2249 | } |
1859 | 2250 | ||
1860 | static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter) | 2251 | static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter) |
@@ -1864,16 +2255,25 @@ static void qlcnic_free_lb_filters_mem(struct qlcnic_adapter *adapter) | |||
1864 | 2255 | ||
1865 | adapter->fhash.fhead = NULL; | 2256 | adapter->fhash.fhead = NULL; |
1866 | adapter->fhash.fmax = 0; | 2257 | adapter->fhash.fmax = 0; |
2258 | |||
2259 | if (adapter->rx_fhash.fmax && adapter->rx_fhash.fhead) | ||
2260 | kfree(adapter->rx_fhash.fhead); | ||
2261 | |||
2262 | adapter->rx_fhash.fmax = 0; | ||
2263 | adapter->rx_fhash.fhead = NULL; | ||
1867 | } | 2264 | } |
1868 | 2265 | ||
1869 | static int qlcnic_check_temp(struct qlcnic_adapter *adapter) | 2266 | int qlcnic_check_temp(struct qlcnic_adapter *adapter) |
1870 | { | 2267 | { |
1871 | struct net_device *netdev = adapter->netdev; | 2268 | struct net_device *netdev = adapter->netdev; |
1872 | u32 temp_state, temp_val, temp = 0; | 2269 | u32 temp_state, temp_val, temp = 0; |
1873 | int rv = 0; | 2270 | int rv = 0; |
1874 | 2271 | ||
2272 | if (qlcnic_83xx_check(adapter)) | ||
2273 | temp = QLCRDX(adapter->ahw, QLC_83XX_ASIC_TEMP); | ||
2274 | |||
1875 | if (qlcnic_82xx_check(adapter)) | 2275 | if (qlcnic_82xx_check(adapter)) |
1876 | temp = QLCRD32(adapter, CRB_TEMP_STATE); | 2276 | temp = QLC_SHARED_REG_RD32(adapter, QLCNIC_ASIC_TEMP); |
1877 | 2277 | ||
1878 | temp_state = qlcnic_get_temp_state(temp); | 2278 | temp_state = qlcnic_get_temp_state(temp); |
1879 | temp_val = qlcnic_get_temp_val(temp); | 2279 | temp_val = qlcnic_get_temp_val(temp); |
@@ -1933,7 +2333,7 @@ static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev) | |||
1933 | return stats; | 2333 | return stats; |
1934 | } | 2334 | } |
1935 | 2335 | ||
1936 | static irqreturn_t qlcnic_clear_legacy_intr(struct qlcnic_adapter *adapter) | 2336 | irqreturn_t qlcnic_82xx_clear_legacy_intr(struct qlcnic_adapter *adapter) |
1937 | { | 2337 | { |
1938 | u32 status; | 2338 | u32 status; |
1939 | 2339 | ||
@@ -2009,6 +2409,14 @@ static irqreturn_t qlcnic_msix_intr(int irq, void *data) | |||
2009 | return IRQ_HANDLED; | 2409 | return IRQ_HANDLED; |
2010 | } | 2410 | } |
2011 | 2411 | ||
2412 | static irqreturn_t qlcnic_msix_tx_intr(int irq, void *data) | ||
2413 | { | ||
2414 | struct qlcnic_host_tx_ring *tx_ring = data; | ||
2415 | |||
2416 | napi_schedule(&tx_ring->napi); | ||
2417 | return IRQ_HANDLED; | ||
2418 | } | ||
2419 | |||
2012 | #ifdef CONFIG_NET_POLL_CONTROLLER | 2420 | #ifdef CONFIG_NET_POLL_CONTROLLER |
2013 | static void qlcnic_poll_controller(struct net_device *netdev) | 2421 | static void qlcnic_poll_controller(struct net_device *netdev) |
2014 | { | 2422 | { |
@@ -2035,7 +2443,7 @@ qlcnic_idc_debug_info(struct qlcnic_adapter *adapter, u8 encoding) | |||
2035 | val |= encoding << 7; | 2443 | val |= encoding << 7; |
2036 | val |= (jiffies - adapter->dev_rst_time) << 8; | 2444 | val |= (jiffies - adapter->dev_rst_time) << 8; |
2037 | 2445 | ||
2038 | QLCWR32(adapter, QLCNIC_CRB_DRV_SCRATCH, val); | 2446 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_SCRATCH, val); |
2039 | adapter->dev_rst_time = jiffies; | 2447 | adapter->dev_rst_time = jiffies; |
2040 | } | 2448 | } |
2041 | 2449 | ||
@@ -2050,14 +2458,14 @@ qlcnic_set_drv_state(struct qlcnic_adapter *adapter, u8 state) | |||
2050 | if (qlcnic_api_lock(adapter)) | 2458 | if (qlcnic_api_lock(adapter)) |
2051 | return -EIO; | 2459 | return -EIO; |
2052 | 2460 | ||
2053 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); | 2461 | val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE); |
2054 | 2462 | ||
2055 | if (state == QLCNIC_DEV_NEED_RESET) | 2463 | if (state == QLCNIC_DEV_NEED_RESET) |
2056 | QLC_DEV_SET_RST_RDY(val, adapter->portnum); | 2464 | QLC_DEV_SET_RST_RDY(val, adapter->portnum); |
2057 | else if (state == QLCNIC_DEV_NEED_QUISCENT) | 2465 | else if (state == QLCNIC_DEV_NEED_QUISCENT) |
2058 | QLC_DEV_SET_QSCNT_RDY(val, adapter->portnum); | 2466 | QLC_DEV_SET_QSCNT_RDY(val, adapter->portnum); |
2059 | 2467 | ||
2060 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); | 2468 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_STATE, val); |
2061 | 2469 | ||
2062 | qlcnic_api_unlock(adapter); | 2470 | qlcnic_api_unlock(adapter); |
2063 | 2471 | ||
@@ -2072,9 +2480,9 @@ qlcnic_clr_drv_state(struct qlcnic_adapter *adapter) | |||
2072 | if (qlcnic_api_lock(adapter)) | 2480 | if (qlcnic_api_lock(adapter)) |
2073 | return -EBUSY; | 2481 | return -EBUSY; |
2074 | 2482 | ||
2075 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); | 2483 | val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE); |
2076 | QLC_DEV_CLR_RST_QSCNT(val, adapter->portnum); | 2484 | QLC_DEV_CLR_RST_QSCNT(val, adapter->portnum); |
2077 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); | 2485 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_STATE, val); |
2078 | 2486 | ||
2079 | qlcnic_api_unlock(adapter); | 2487 | qlcnic_api_unlock(adapter); |
2080 | 2488 | ||
@@ -2089,20 +2497,22 @@ qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter, u8 failed) | |||
2089 | if (qlcnic_api_lock(adapter)) | 2497 | if (qlcnic_api_lock(adapter)) |
2090 | goto err; | 2498 | goto err; |
2091 | 2499 | ||
2092 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE); | 2500 | val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_ACTIVE); |
2093 | QLC_DEV_CLR_REF_CNT(val, adapter->portnum); | 2501 | QLC_DEV_CLR_REF_CNT(val, adapter->portnum); |
2094 | QLCWR32(adapter, QLCNIC_CRB_DRV_ACTIVE, val); | 2502 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_ACTIVE, val); |
2095 | 2503 | ||
2096 | if (failed) { | 2504 | if (failed) { |
2097 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_FAILED); | 2505 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE, |
2506 | QLCNIC_DEV_FAILED); | ||
2098 | dev_info(&adapter->pdev->dev, | 2507 | dev_info(&adapter->pdev->dev, |
2099 | "Device state set to Failed. Please Reboot\n"); | 2508 | "Device state set to Failed. Please Reboot\n"); |
2100 | } else if (!(val & 0x11111111)) | 2509 | } else if (!(val & 0x11111111)) |
2101 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_COLD); | 2510 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE, |
2511 | QLCNIC_DEV_COLD); | ||
2102 | 2512 | ||
2103 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); | 2513 | val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE); |
2104 | QLC_DEV_CLR_RST_QSCNT(val, adapter->portnum); | 2514 | QLC_DEV_CLR_RST_QSCNT(val, adapter->portnum); |
2105 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); | 2515 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_STATE, val); |
2106 | 2516 | ||
2107 | qlcnic_api_unlock(adapter); | 2517 | qlcnic_api_unlock(adapter); |
2108 | err: | 2518 | err: |
@@ -2117,12 +2527,13 @@ static int | |||
2117 | qlcnic_check_drv_state(struct qlcnic_adapter *adapter) | 2527 | qlcnic_check_drv_state(struct qlcnic_adapter *adapter) |
2118 | { | 2528 | { |
2119 | int act, state, active_mask; | 2529 | int act, state, active_mask; |
2530 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
2120 | 2531 | ||
2121 | state = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); | 2532 | state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE); |
2122 | act = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE); | 2533 | act = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_ACTIVE); |
2123 | 2534 | ||
2124 | if (adapter->flags & QLCNIC_FW_RESET_OWNER) { | 2535 | if (adapter->flags & QLCNIC_FW_RESET_OWNER) { |
2125 | active_mask = (~(1 << (adapter->ahw->pci_func * 4))); | 2536 | active_mask = (~(1 << (ahw->pci_func * 4))); |
2126 | act = act & active_mask; | 2537 | act = act & active_mask; |
2127 | } | 2538 | } |
2128 | 2539 | ||
@@ -2135,7 +2546,7 @@ qlcnic_check_drv_state(struct qlcnic_adapter *adapter) | |||
2135 | 2546 | ||
2136 | static int qlcnic_check_idc_ver(struct qlcnic_adapter *adapter) | 2547 | static int qlcnic_check_idc_ver(struct qlcnic_adapter *adapter) |
2137 | { | 2548 | { |
2138 | u32 val = QLCRD32(adapter, QLCNIC_CRB_DRV_IDC_VER); | 2549 | u32 val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_IDC_VER); |
2139 | 2550 | ||
2140 | if (val != QLCNIC_DRV_IDC_VER) { | 2551 | if (val != QLCNIC_DRV_IDC_VER) { |
2141 | dev_warn(&adapter->pdev->dev, "IDC Version mismatch, driver's" | 2552 | dev_warn(&adapter->pdev->dev, "IDC Version mismatch, driver's" |
@@ -2159,19 +2570,21 @@ qlcnic_can_start_firmware(struct qlcnic_adapter *adapter) | |||
2159 | if (qlcnic_api_lock(adapter)) | 2570 | if (qlcnic_api_lock(adapter)) |
2160 | return -1; | 2571 | return -1; |
2161 | 2572 | ||
2162 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_ACTIVE); | 2573 | val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_ACTIVE); |
2163 | if (!(val & (1 << (portnum * 4)))) { | 2574 | if (!(val & (1 << (portnum * 4)))) { |
2164 | QLC_DEV_SET_REF_CNT(val, portnum); | 2575 | QLC_DEV_SET_REF_CNT(val, portnum); |
2165 | QLCWR32(adapter, QLCNIC_CRB_DRV_ACTIVE, val); | 2576 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_ACTIVE, val); |
2166 | } | 2577 | } |
2167 | 2578 | ||
2168 | prev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); | 2579 | prev_state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); |
2169 | QLCDB(adapter, HW, "Device state = %u\n", prev_state); | 2580 | QLCDB(adapter, HW, "Device state = %u\n", prev_state); |
2170 | 2581 | ||
2171 | switch (prev_state) { | 2582 | switch (prev_state) { |
2172 | case QLCNIC_DEV_COLD: | 2583 | case QLCNIC_DEV_COLD: |
2173 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING); | 2584 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE, |
2174 | QLCWR32(adapter, QLCNIC_CRB_DRV_IDC_VER, QLCNIC_DRV_IDC_VER); | 2585 | QLCNIC_DEV_INITIALIZING); |
2586 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_IDC_VER, | ||
2587 | QLCNIC_DRV_IDC_VER); | ||
2175 | qlcnic_idc_debug_info(adapter, 0); | 2588 | qlcnic_idc_debug_info(adapter, 0); |
2176 | qlcnic_api_unlock(adapter); | 2589 | qlcnic_api_unlock(adapter); |
2177 | return 1; | 2590 | return 1; |
@@ -2182,15 +2595,15 @@ qlcnic_can_start_firmware(struct qlcnic_adapter *adapter) | |||
2182 | return ret; | 2595 | return ret; |
2183 | 2596 | ||
2184 | case QLCNIC_DEV_NEED_RESET: | 2597 | case QLCNIC_DEV_NEED_RESET: |
2185 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); | 2598 | val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE); |
2186 | QLC_DEV_SET_RST_RDY(val, portnum); | 2599 | QLC_DEV_SET_RST_RDY(val, portnum); |
2187 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); | 2600 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_STATE, val); |
2188 | break; | 2601 | break; |
2189 | 2602 | ||
2190 | case QLCNIC_DEV_NEED_QUISCENT: | 2603 | case QLCNIC_DEV_NEED_QUISCENT: |
2191 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); | 2604 | val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE); |
2192 | QLC_DEV_SET_QSCNT_RDY(val, portnum); | 2605 | QLC_DEV_SET_QSCNT_RDY(val, portnum); |
2193 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); | 2606 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_STATE, val); |
2194 | break; | 2607 | break; |
2195 | 2608 | ||
2196 | case QLCNIC_DEV_FAILED: | 2609 | case QLCNIC_DEV_FAILED: |
@@ -2207,7 +2620,7 @@ qlcnic_can_start_firmware(struct qlcnic_adapter *adapter) | |||
2207 | 2620 | ||
2208 | do { | 2621 | do { |
2209 | msleep(1000); | 2622 | msleep(1000); |
2210 | prev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); | 2623 | prev_state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); |
2211 | 2624 | ||
2212 | if (prev_state == QLCNIC_DEV_QUISCENT) | 2625 | if (prev_state == QLCNIC_DEV_QUISCENT) |
2213 | continue; | 2626 | continue; |
@@ -2222,9 +2635,9 @@ qlcnic_can_start_firmware(struct qlcnic_adapter *adapter) | |||
2222 | if (qlcnic_api_lock(adapter)) | 2635 | if (qlcnic_api_lock(adapter)) |
2223 | return -1; | 2636 | return -1; |
2224 | 2637 | ||
2225 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); | 2638 | val = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DRV_STATE); |
2226 | QLC_DEV_CLR_RST_QSCNT(val, portnum); | 2639 | QLC_DEV_CLR_RST_QSCNT(val, portnum); |
2227 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); | 2640 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DRV_STATE, val); |
2228 | 2641 | ||
2229 | ret = qlcnic_check_idc_ver(adapter); | 2642 | ret = qlcnic_check_idc_ver(adapter); |
2230 | qlcnic_api_unlock(adapter); | 2643 | qlcnic_api_unlock(adapter); |
@@ -2243,7 +2656,7 @@ qlcnic_fwinit_work(struct work_struct *work) | |||
2243 | if (qlcnic_api_lock(adapter)) | 2656 | if (qlcnic_api_lock(adapter)) |
2244 | goto err_ret; | 2657 | goto err_ret; |
2245 | 2658 | ||
2246 | dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); | 2659 | dev_state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); |
2247 | if (dev_state == QLCNIC_DEV_QUISCENT || | 2660 | if (dev_state == QLCNIC_DEV_QUISCENT || |
2248 | dev_state == QLCNIC_DEV_NEED_QUISCENT) { | 2661 | dev_state == QLCNIC_DEV_NEED_QUISCENT) { |
2249 | qlcnic_api_unlock(adapter); | 2662 | qlcnic_api_unlock(adapter); |
@@ -2272,17 +2685,19 @@ qlcnic_fwinit_work(struct work_struct *work) | |||
2272 | 2685 | ||
2273 | if (!qlcnic_check_drv_state(adapter)) { | 2686 | if (!qlcnic_check_drv_state(adapter)) { |
2274 | skip_ack_check: | 2687 | skip_ack_check: |
2275 | dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); | 2688 | dev_state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); |
2276 | 2689 | ||
2277 | if (dev_state == QLCNIC_DEV_NEED_RESET) { | 2690 | if (dev_state == QLCNIC_DEV_NEED_RESET) { |
2278 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, | 2691 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE, |
2279 | QLCNIC_DEV_INITIALIZING); | 2692 | QLCNIC_DEV_INITIALIZING); |
2280 | set_bit(__QLCNIC_START_FW, &adapter->state); | 2693 | set_bit(__QLCNIC_START_FW, &adapter->state); |
2281 | QLCDB(adapter, DRV, "Restarting fw\n"); | 2694 | QLCDB(adapter, DRV, "Restarting fw\n"); |
2282 | qlcnic_idc_debug_info(adapter, 0); | 2695 | qlcnic_idc_debug_info(adapter, 0); |
2283 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); | 2696 | val = QLC_SHARED_REG_RD32(adapter, |
2697 | QLCNIC_CRB_DRV_STATE); | ||
2284 | QLC_DEV_SET_RST_RDY(val, adapter->portnum); | 2698 | QLC_DEV_SET_RST_RDY(val, adapter->portnum); |
2285 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); | 2699 | QLC_SHARED_REG_WR32(adapter, |
2700 | QLCNIC_CRB_DRV_STATE, val); | ||
2286 | } | 2701 | } |
2287 | 2702 | ||
2288 | qlcnic_api_unlock(adapter); | 2703 | qlcnic_api_unlock(adapter); |
@@ -2308,12 +2723,12 @@ skip_ack_check: | |||
2308 | qlcnic_api_unlock(adapter); | 2723 | qlcnic_api_unlock(adapter); |
2309 | 2724 | ||
2310 | wait_npar: | 2725 | wait_npar: |
2311 | dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); | 2726 | dev_state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); |
2312 | QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state); | 2727 | QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state); |
2313 | 2728 | ||
2314 | switch (dev_state) { | 2729 | switch (dev_state) { |
2315 | case QLCNIC_DEV_READY: | 2730 | case QLCNIC_DEV_READY: |
2316 | if (!adapter->nic_ops->start_firmware(adapter)) { | 2731 | if (!qlcnic_start_firmware(adapter)) { |
2317 | qlcnic_schedule_work(adapter, qlcnic_attach_work, 0); | 2732 | qlcnic_schedule_work(adapter, qlcnic_attach_work, 0); |
2318 | adapter->fw_wait_cnt = 0; | 2733 | adapter->fw_wait_cnt = 0; |
2319 | return; | 2734 | return; |
@@ -2350,7 +2765,7 @@ qlcnic_detach_work(struct work_struct *work) | |||
2350 | } else | 2765 | } else |
2351 | qlcnic_down(adapter, netdev); | 2766 | qlcnic_down(adapter, netdev); |
2352 | 2767 | ||
2353 | status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1); | 2768 | status = QLC_SHARED_REG_RD32(adapter, QLCNIC_PEG_HALT_STATUS1); |
2354 | 2769 | ||
2355 | if (status & QLCNIC_RCODE_FATAL_ERROR) { | 2770 | if (status & QLCNIC_RCODE_FATAL_ERROR) { |
2356 | dev_err(&adapter->pdev->dev, | 2771 | dev_err(&adapter->pdev->dev, |
@@ -2401,19 +2816,18 @@ qlcnic_set_npar_non_operational(struct qlcnic_adapter *adapter) | |||
2401 | { | 2816 | { |
2402 | u32 state; | 2817 | u32 state; |
2403 | 2818 | ||
2404 | state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); | 2819 | state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); |
2405 | if (state == QLCNIC_DEV_NPAR_NON_OPER) | 2820 | if (state == QLCNIC_DEV_NPAR_NON_OPER) |
2406 | return; | 2821 | return; |
2407 | 2822 | ||
2408 | if (qlcnic_api_lock(adapter)) | 2823 | if (qlcnic_api_lock(adapter)) |
2409 | return; | 2824 | return; |
2410 | QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER); | 2825 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, |
2826 | QLCNIC_DEV_NPAR_NON_OPER); | ||
2411 | qlcnic_api_unlock(adapter); | 2827 | qlcnic_api_unlock(adapter); |
2412 | } | 2828 | } |
2413 | 2829 | ||
2414 | /*Transit to RESET state from READY state only */ | 2830 | void qlcnic_82xx_dev_request_reset(struct qlcnic_adapter *adapter, u32 key) |
2415 | void | ||
2416 | qlcnic_dev_request_reset(struct qlcnic_adapter *adapter) | ||
2417 | { | 2831 | { |
2418 | u32 state, xg_val = 0, gb_val = 0; | 2832 | u32 state, xg_val = 0, gb_val = 0; |
2419 | 2833 | ||
@@ -2428,25 +2842,22 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter) | |||
2428 | dev_info(&adapter->pdev->dev, "Pause control frames disabled" | 2842 | dev_info(&adapter->pdev->dev, "Pause control frames disabled" |
2429 | " on all ports\n"); | 2843 | " on all ports\n"); |
2430 | adapter->need_fw_reset = 1; | 2844 | adapter->need_fw_reset = 1; |
2845 | |||
2431 | if (qlcnic_api_lock(adapter)) | 2846 | if (qlcnic_api_lock(adapter)) |
2432 | return; | 2847 | return; |
2433 | 2848 | ||
2434 | state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); | 2849 | state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); |
2435 | if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) { | ||
2436 | netdev_err(adapter->netdev, | ||
2437 | "Device is in FAILED state, Please Reboot\n"); | ||
2438 | qlcnic_api_unlock(adapter); | ||
2439 | return; | ||
2440 | } | ||
2441 | 2850 | ||
2442 | if (state == QLCNIC_DEV_READY) { | 2851 | if (state == QLCNIC_DEV_READY) { |
2443 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_RESET); | 2852 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE, |
2853 | QLCNIC_DEV_NEED_RESET); | ||
2444 | adapter->flags |= QLCNIC_FW_RESET_OWNER; | 2854 | adapter->flags |= QLCNIC_FW_RESET_OWNER; |
2445 | QLCDB(adapter, DRV, "NEED_RESET state set\n"); | 2855 | QLCDB(adapter, DRV, "NEED_RESET state set\n"); |
2446 | qlcnic_idc_debug_info(adapter, 0); | 2856 | qlcnic_idc_debug_info(adapter, 0); |
2447 | } | 2857 | } |
2448 | 2858 | ||
2449 | QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_NON_OPER); | 2859 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, |
2860 | QLCNIC_DEV_NPAR_NON_OPER); | ||
2450 | qlcnic_api_unlock(adapter); | 2861 | qlcnic_api_unlock(adapter); |
2451 | } | 2862 | } |
2452 | 2863 | ||
@@ -2457,34 +2868,22 @@ qlcnic_dev_set_npar_ready(struct qlcnic_adapter *adapter) | |||
2457 | if (qlcnic_api_lock(adapter)) | 2868 | if (qlcnic_api_lock(adapter)) |
2458 | return; | 2869 | return; |
2459 | 2870 | ||
2460 | QLCWR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, QLCNIC_DEV_NPAR_OPER); | 2871 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_NPAR_STATE, |
2872 | QLCNIC_DEV_NPAR_OPER); | ||
2461 | QLCDB(adapter, DRV, "NPAR operational state set\n"); | 2873 | QLCDB(adapter, DRV, "NPAR operational state set\n"); |
2462 | 2874 | ||
2463 | qlcnic_api_unlock(adapter); | 2875 | qlcnic_api_unlock(adapter); |
2464 | } | 2876 | } |
2465 | 2877 | ||
2466 | static void | 2878 | void qlcnic_schedule_work(struct qlcnic_adapter *adapter, |
2467 | qlcnic_schedule_work(struct qlcnic_adapter *adapter, | 2879 | work_func_t func, int delay) |
2468 | work_func_t func, int delay) | ||
2469 | { | 2880 | { |
2470 | if (test_bit(__QLCNIC_AER, &adapter->state)) | 2881 | if (test_bit(__QLCNIC_AER, &adapter->state)) |
2471 | return; | 2882 | return; |
2472 | 2883 | ||
2473 | INIT_DELAYED_WORK(&adapter->fw_work, func); | 2884 | INIT_DELAYED_WORK(&adapter->fw_work, func); |
2474 | queue_delayed_work(qlcnic_wq, &adapter->fw_work, | 2885 | queue_delayed_work(adapter->qlcnic_wq, &adapter->fw_work, |
2475 | round_jiffies_relative(delay)); | 2886 | round_jiffies_relative(delay)); |
2476 | } | ||
2477 | |||
2478 | static void | ||
2479 | qlcnic_cancel_fw_work(struct qlcnic_adapter *adapter) | ||
2480 | { | ||
2481 | while (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) | ||
2482 | msleep(10); | ||
2483 | |||
2484 | if (!adapter->fw_work.work.func) | ||
2485 | return; | ||
2486 | |||
2487 | cancel_delayed_work_sync(&adapter->fw_work); | ||
2488 | } | 2887 | } |
2489 | 2888 | ||
2490 | static void | 2889 | static void |
@@ -2496,7 +2895,8 @@ qlcnic_attach_work(struct work_struct *work) | |||
2496 | u32 npar_state; | 2895 | u32 npar_state; |
2497 | 2896 | ||
2498 | if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) { | 2897 | if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC) { |
2499 | npar_state = QLCRD32(adapter, QLCNIC_CRB_DEV_NPAR_STATE); | 2898 | npar_state = QLC_SHARED_REG_RD32(adapter, |
2899 | QLCNIC_CRB_DEV_NPAR_STATE); | ||
2500 | if (adapter->fw_wait_cnt++ > QLCNIC_DEV_NPAR_OPER_TIMEO) | 2900 | if (adapter->fw_wait_cnt++ > QLCNIC_DEV_NPAR_OPER_TIMEO) |
2501 | qlcnic_clr_all_drv_state(adapter, 0); | 2901 | qlcnic_clr_all_drv_state(adapter, 0); |
2502 | else if (npar_state != QLCNIC_DEV_NPAR_OPER) | 2902 | else if (npar_state != QLCNIC_DEV_NPAR_OPER) |
@@ -2536,16 +2936,16 @@ qlcnic_check_health(struct qlcnic_adapter *adapter) | |||
2536 | goto detach; | 2936 | goto detach; |
2537 | 2937 | ||
2538 | if (adapter->need_fw_reset) | 2938 | if (adapter->need_fw_reset) |
2539 | qlcnic_dev_request_reset(adapter); | 2939 | qlcnic_dev_request_reset(adapter, 0); |
2540 | 2940 | ||
2541 | state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); | 2941 | state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); |
2542 | if (state == QLCNIC_DEV_NEED_RESET) { | 2942 | if (state == QLCNIC_DEV_NEED_RESET) { |
2543 | qlcnic_set_npar_non_operational(adapter); | 2943 | qlcnic_set_npar_non_operational(adapter); |
2544 | adapter->need_fw_reset = 1; | 2944 | adapter->need_fw_reset = 1; |
2545 | } else if (state == QLCNIC_DEV_NEED_QUISCENT) | 2945 | } else if (state == QLCNIC_DEV_NEED_QUISCENT) |
2546 | goto detach; | 2946 | goto detach; |
2547 | 2947 | ||
2548 | heartbeat = QLCRD32(adapter, QLCNIC_PEG_ALIVE_COUNTER); | 2948 | heartbeat = QLC_SHARED_REG_RD32(adapter, QLCNIC_PEG_ALIVE_COUNTER); |
2549 | if (heartbeat != adapter->heartbeat) { | 2949 | if (heartbeat != adapter->heartbeat) { |
2550 | adapter->heartbeat = heartbeat; | 2950 | adapter->heartbeat = heartbeat; |
2551 | adapter->fw_fail_cnt = 0; | 2951 | adapter->fw_fail_cnt = 0; |
@@ -2565,25 +2965,25 @@ qlcnic_check_health(struct qlcnic_adapter *adapter) | |||
2565 | 2965 | ||
2566 | adapter->flags |= QLCNIC_FW_HANG; | 2966 | adapter->flags |= QLCNIC_FW_HANG; |
2567 | 2967 | ||
2568 | qlcnic_dev_request_reset(adapter); | 2968 | qlcnic_dev_request_reset(adapter, 0); |
2569 | 2969 | ||
2570 | if (qlcnic_auto_fw_reset) | 2970 | if (qlcnic_auto_fw_reset) |
2571 | clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state); | 2971 | clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state); |
2572 | 2972 | ||
2573 | dev_err(&adapter->pdev->dev, "firmware hang detected\n"); | 2973 | dev_err(&adapter->pdev->dev, "firmware hang detected\n"); |
2974 | peg_status = QLC_SHARED_REG_RD32(adapter, QLCNIC_PEG_HALT_STATUS1); | ||
2574 | dev_err(&adapter->pdev->dev, "Dumping hw/fw registers\n" | 2975 | dev_err(&adapter->pdev->dev, "Dumping hw/fw registers\n" |
2575 | "PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n" | 2976 | "PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n" |
2576 | "PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n" | 2977 | "PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n" |
2577 | "PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n" | 2978 | "PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n" |
2578 | "PEG_NET_4_PC: 0x%x\n", | 2979 | "PEG_NET_4_PC: 0x%x\n", |
2579 | QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1), | 2980 | peg_status, |
2580 | QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS2), | 2981 | QLC_SHARED_REG_RD32(adapter, QLCNIC_PEG_HALT_STATUS2), |
2581 | QLCRD32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x3c), | 2982 | QLCRD32(adapter, QLCNIC_CRB_PEG_NET_0 + 0x3c), |
2582 | QLCRD32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x3c), | 2983 | QLCRD32(adapter, QLCNIC_CRB_PEG_NET_1 + 0x3c), |
2583 | QLCRD32(adapter, QLCNIC_CRB_PEG_NET_2 + 0x3c), | 2984 | QLCRD32(adapter, QLCNIC_CRB_PEG_NET_2 + 0x3c), |
2584 | QLCRD32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x3c), | 2985 | QLCRD32(adapter, QLCNIC_CRB_PEG_NET_3 + 0x3c), |
2585 | QLCRD32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x3c)); | 2986 | QLCRD32(adapter, QLCNIC_CRB_PEG_NET_4 + 0x3c)); |
2586 | peg_status = QLCRD32(adapter, QLCNIC_PEG_HALT_STATUS1); | ||
2587 | if (QLCNIC_FWERROR_CODE(peg_status) == 0x67) | 2987 | if (QLCNIC_FWERROR_CODE(peg_status) == 0x67) |
2588 | dev_err(&adapter->pdev->dev, | 2988 | dev_err(&adapter->pdev->dev, |
2589 | "Firmware aborted with error code 0x00006700. " | 2989 | "Firmware aborted with error code 0x00006700. " |
@@ -2667,17 +3067,39 @@ static int qlcnic_attach_func(struct pci_dev *pdev) | |||
2667 | if (adapter->ahw->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) { | 3067 | if (adapter->ahw->op_mode != QLCNIC_NON_PRIV_FUNC && first_func) { |
2668 | adapter->need_fw_reset = 1; | 3068 | adapter->need_fw_reset = 1; |
2669 | set_bit(__QLCNIC_START_FW, &adapter->state); | 3069 | set_bit(__QLCNIC_START_FW, &adapter->state); |
2670 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING); | 3070 | QLC_SHARED_REG_WR32(adapter, QLCNIC_CRB_DEV_STATE, |
3071 | QLCNIC_DEV_INITIALIZING); | ||
2671 | QLCDB(adapter, DRV, "Restarting fw\n"); | 3072 | QLCDB(adapter, DRV, "Restarting fw\n"); |
2672 | } | 3073 | } |
2673 | qlcnic_api_unlock(adapter); | 3074 | qlcnic_api_unlock(adapter); |
2674 | 3075 | ||
2675 | err = adapter->nic_ops->start_firmware(adapter); | 3076 | err = qlcnic_start_firmware(adapter); |
2676 | if (err) | 3077 | if (err) |
2677 | return err; | 3078 | return err; |
2678 | 3079 | ||
2679 | qlcnic_clr_drv_state(adapter); | 3080 | qlcnic_clr_drv_state(adapter); |
2680 | qlcnic_setup_intr(adapter); | 3081 | kfree(adapter->msix_entries); |
3082 | adapter->msix_entries = NULL; | ||
3083 | err = qlcnic_setup_intr(adapter, 0); | ||
3084 | |||
3085 | if (err) { | ||
3086 | kfree(adapter->msix_entries); | ||
3087 | netdev_err(netdev, "failed to setup interrupt\n"); | ||
3088 | return err; | ||
3089 | } | ||
3090 | |||
3091 | if (qlcnic_83xx_check(adapter)) { | ||
3092 | /* register for NIC IDC AEN Events */ | ||
3093 | qlcnic_83xx_register_nic_idc_func(adapter, 1); | ||
3094 | err = qlcnic_83xx_setup_mbx_intr(adapter); | ||
3095 | if (err) { | ||
3096 | dev_err(&adapter->pdev->dev, | ||
3097 | "failed to setup mbx interrupt\n"); | ||
3098 | qlcnic_clr_all_drv_state(adapter, 1); | ||
3099 | clear_bit(__QLCNIC_AER, &adapter->state); | ||
3100 | goto done; | ||
3101 | } | ||
3102 | } | ||
2681 | 3103 | ||
2682 | if (netif_running(netdev)) { | 3104 | if (netif_running(netdev)) { |
2683 | err = qlcnic_attach(adapter); | 3105 | err = qlcnic_attach(adapter); |
@@ -2719,6 +3141,12 @@ static pci_ers_result_t qlcnic_io_error_detected(struct pci_dev *pdev, | |||
2719 | if (netif_running(netdev)) | 3141 | if (netif_running(netdev)) |
2720 | qlcnic_down(adapter, netdev); | 3142 | qlcnic_down(adapter, netdev); |
2721 | 3143 | ||
3144 | if (qlcnic_83xx_check(adapter)) { | ||
3145 | qlcnic_83xx_free_mbx_intr(adapter); | ||
3146 | qlcnic_83xx_register_nic_idc_func(adapter, 0); | ||
3147 | cancel_delayed_work_sync(&adapter->idc_aen_work); | ||
3148 | } | ||
3149 | |||
2722 | qlcnic_detach(adapter); | 3150 | qlcnic_detach(adapter); |
2723 | qlcnic_teardown_intr(adapter); | 3151 | qlcnic_teardown_intr(adapter); |
2724 | 3152 | ||
@@ -2738,12 +3166,13 @@ static pci_ers_result_t qlcnic_io_slot_reset(struct pci_dev *pdev) | |||
2738 | 3166 | ||
2739 | static void qlcnic_io_resume(struct pci_dev *pdev) | 3167 | static void qlcnic_io_resume(struct pci_dev *pdev) |
2740 | { | 3168 | { |
3169 | u32 state; | ||
2741 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); | 3170 | struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); |
2742 | 3171 | ||
2743 | pci_cleanup_aer_uncorrect_error_status(pdev); | 3172 | pci_cleanup_aer_uncorrect_error_status(pdev); |
2744 | 3173 | state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); | |
2745 | if (QLCRD32(adapter, QLCNIC_CRB_DEV_STATE) == QLCNIC_DEV_READY && | 3174 | if (state == QLCNIC_DEV_READY && test_and_clear_bit(__QLCNIC_AER, |
2746 | test_and_clear_bit(__QLCNIC_AER, &adapter->state)) | 3175 | &adapter->state)) |
2747 | qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, | 3176 | qlcnic_schedule_work(adapter, qlcnic_fw_poll_work, |
2748 | FW_POLL_DELAY); | 3177 | FW_POLL_DELAY); |
2749 | } | 3178 | } |
@@ -2776,39 +3205,59 @@ qlcnicvf_start_firmware(struct qlcnic_adapter *adapter) | |||
2776 | return err; | 3205 | return err; |
2777 | } | 3206 | } |
2778 | 3207 | ||
2779 | int qlcnic_validate_max_rss(struct net_device *netdev, u8 max_hw, u8 val) | 3208 | int qlcnic_validate_max_rss(u8 max_hw, u8 val) |
2780 | { | 3209 | { |
2781 | if (!qlcnic_use_msi_x && !qlcnic_use_msi) { | 3210 | u32 max_allowed; |
2782 | netdev_info(netdev, "no msix or msi support, hence no rss\n"); | 3211 | |
2783 | return -EINVAL; | 3212 | if (max_hw > QLC_MAX_SDS_RINGS) { |
3213 | max_hw = QLC_MAX_SDS_RINGS; | ||
3214 | pr_info("max rss reset to %d\n", QLC_MAX_SDS_RINGS); | ||
2784 | } | 3215 | } |
2785 | 3216 | ||
2786 | if ((val > max_hw) || (val < 2) || !is_power_of_2(val)) { | 3217 | max_allowed = rounddown_pow_of_two(min_t(int, max_hw, |
2787 | netdev_info(netdev, "rss_ring valid range [2 - %x] in " | 3218 | num_online_cpus())); |
2788 | " powers of 2\n", max_hw); | 3219 | if ((val > max_allowed) || (val < 2) || !is_power_of_2(val)) { |
3220 | pr_info("rss_ring valid range [2 - %x] in powers of 2\n", | ||
3221 | max_allowed); | ||
2789 | return -EINVAL; | 3222 | return -EINVAL; |
2790 | } | 3223 | } |
2791 | return 0; | 3224 | return 0; |
2792 | |||
2793 | } | 3225 | } |
2794 | 3226 | ||
2795 | int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data) | 3227 | int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data, size_t len) |
2796 | { | 3228 | { |
3229 | int err; | ||
2797 | struct net_device *netdev = adapter->netdev; | 3230 | struct net_device *netdev = adapter->netdev; |
2798 | int err = 0; | ||
2799 | 3231 | ||
2800 | if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) | 3232 | if (test_bit(__QLCNIC_RESETTING, &adapter->state)) |
2801 | return -EBUSY; | 3233 | return -EBUSY; |
2802 | 3234 | ||
2803 | netif_device_detach(netdev); | 3235 | netif_device_detach(netdev); |
2804 | if (netif_running(netdev)) | 3236 | if (netif_running(netdev)) |
2805 | __qlcnic_down(adapter, netdev); | 3237 | __qlcnic_down(adapter, netdev); |
3238 | |||
2806 | qlcnic_detach(adapter); | 3239 | qlcnic_detach(adapter); |
3240 | |||
3241 | if (qlcnic_83xx_check(adapter)) | ||
3242 | qlcnic_83xx_free_mbx_intr(adapter); | ||
3243 | |||
2807 | qlcnic_teardown_intr(adapter); | 3244 | qlcnic_teardown_intr(adapter); |
3245 | err = qlcnic_setup_intr(adapter, data); | ||
3246 | if (err) { | ||
3247 | kfree(adapter->msix_entries); | ||
3248 | netdev_err(netdev, "failed to setup interrupt\n"); | ||
3249 | return err; | ||
3250 | } | ||
2808 | 3251 | ||
2809 | if (qlcnic_enable_msix(adapter, data)) { | 3252 | if (qlcnic_83xx_check(adapter)) { |
2810 | netdev_info(netdev, "failed setting max_rss; rss disabled\n"); | 3253 | /* register for NIC IDC AEN Events */ |
2811 | qlcnic_enable_msi_legacy(adapter); | 3254 | qlcnic_83xx_register_nic_idc_func(adapter, 1); |
3255 | err = qlcnic_83xx_setup_mbx_intr(adapter); | ||
3256 | if (err) { | ||
3257 | dev_err(&adapter->pdev->dev, | ||
3258 | "failed to setup mbx interrupt\n"); | ||
3259 | goto done; | ||
3260 | } | ||
2812 | } | 3261 | } |
2813 | 3262 | ||
2814 | if (netif_running(netdev)) { | 3263 | if (netif_running(netdev)) { |
@@ -2820,6 +3269,7 @@ int qlcnic_set_max_rss(struct qlcnic_adapter *adapter, u8 data) | |||
2820 | goto done; | 3269 | goto done; |
2821 | qlcnic_restore_indev_addr(netdev, NETDEV_UP); | 3270 | qlcnic_restore_indev_addr(netdev, NETDEV_UP); |
2822 | } | 3271 | } |
3272 | err = len; | ||
2823 | done: | 3273 | done: |
2824 | netif_device_attach(netdev); | 3274 | netif_device_attach(netdev); |
2825 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 3275 | clear_bit(__QLCNIC_RESETTING, &adapter->state); |
@@ -2858,8 +3308,7 @@ qlcnic_config_indev_addr(struct qlcnic_adapter *adapter, | |||
2858 | in_dev_put(indev); | 3308 | in_dev_put(indev); |
2859 | } | 3309 | } |
2860 | 3310 | ||
2861 | static void | 3311 | void qlcnic_restore_indev_addr(struct net_device *netdev, unsigned long event) |
2862 | qlcnic_restore_indev_addr(struct net_device *netdev, unsigned long event) | ||
2863 | { | 3312 | { |
2864 | struct qlcnic_adapter *adapter = netdev_priv(netdev); | 3313 | struct qlcnic_adapter *adapter = netdev_priv(netdev); |
2865 | struct net_device *dev; | 3314 | struct net_device *dev; |
@@ -2867,12 +3316,14 @@ qlcnic_restore_indev_addr(struct net_device *netdev, unsigned long event) | |||
2867 | 3316 | ||
2868 | qlcnic_config_indev_addr(adapter, netdev, event); | 3317 | qlcnic_config_indev_addr(adapter, netdev, event); |
2869 | 3318 | ||
3319 | rcu_read_lock(); | ||
2870 | for_each_set_bit(vid, adapter->vlans, VLAN_N_VID) { | 3320 | for_each_set_bit(vid, adapter->vlans, VLAN_N_VID) { |
2871 | dev = __vlan_find_dev_deep(netdev, vid); | 3321 | dev = __vlan_find_dev_deep(netdev, vid); |
2872 | if (!dev) | 3322 | if (!dev) |
2873 | continue; | 3323 | continue; |
2874 | qlcnic_config_indev_addr(adapter, dev, event); | 3324 | qlcnic_config_indev_addr(adapter, dev, event); |
2875 | } | 3325 | } |
3326 | rcu_read_unlock(); | ||
2876 | } | 3327 | } |
2877 | 3328 | ||
2878 | static int qlcnic_netdev_event(struct notifier_block *this, | 3329 | static int qlcnic_netdev_event(struct notifier_block *this, |
@@ -2940,9 +3391,11 @@ recheck: | |||
2940 | switch (event) { | 3391 | switch (event) { |
2941 | case NETDEV_UP: | 3392 | case NETDEV_UP: |
2942 | qlcnic_config_ipaddr(adapter, ifa->ifa_address, QLCNIC_IP_UP); | 3393 | qlcnic_config_ipaddr(adapter, ifa->ifa_address, QLCNIC_IP_UP); |
3394 | |||
2943 | break; | 3395 | break; |
2944 | case NETDEV_DOWN: | 3396 | case NETDEV_DOWN: |
2945 | qlcnic_config_ipaddr(adapter, ifa->ifa_address, QLCNIC_IP_DOWN); | 3397 | qlcnic_config_ipaddr(adapter, ifa->ifa_address, QLCNIC_IP_DOWN); |
3398 | |||
2946 | break; | 3399 | break; |
2947 | default: | 3400 | default: |
2948 | break; | 3401 | break; |
@@ -2960,11 +3413,10 @@ static struct notifier_block qlcnic_inetaddr_cb = { | |||
2960 | .notifier_call = qlcnic_inetaddr_event, | 3413 | .notifier_call = qlcnic_inetaddr_event, |
2961 | }; | 3414 | }; |
2962 | #else | 3415 | #else |
2963 | static void | 3416 | void qlcnic_restore_indev_addr(struct net_device *dev, unsigned long event) |
2964 | qlcnic_restore_indev_addr(struct net_device *dev, unsigned long event) | ||
2965 | { } | 3417 | { } |
2966 | #endif | 3418 | #endif |
2967 | static struct pci_error_handlers qlcnic_err_handler = { | 3419 | static const struct pci_error_handlers qlcnic_err_handler = { |
2968 | .error_detected = qlcnic_io_error_detected, | 3420 | .error_detected = qlcnic_io_error_detected, |
2969 | .slot_reset = qlcnic_io_slot_reset, | 3421 | .slot_reset = qlcnic_io_slot_reset, |
2970 | .resume = qlcnic_io_resume, | 3422 | .resume = qlcnic_io_resume, |
@@ -2990,12 +3442,6 @@ static int __init qlcnic_init_module(void) | |||
2990 | 3442 | ||
2991 | printk(KERN_INFO "%s\n", qlcnic_driver_string); | 3443 | printk(KERN_INFO "%s\n", qlcnic_driver_string); |
2992 | 3444 | ||
2993 | qlcnic_wq = create_singlethread_workqueue("qlcnic"); | ||
2994 | if (qlcnic_wq == NULL) { | ||
2995 | printk(KERN_ERR "qlcnic: cannot create workqueue\n"); | ||
2996 | return -ENOMEM; | ||
2997 | } | ||
2998 | |||
2999 | #ifdef CONFIG_INET | 3445 | #ifdef CONFIG_INET |
3000 | register_netdevice_notifier(&qlcnic_netdev_cb); | 3446 | register_netdevice_notifier(&qlcnic_netdev_cb); |
3001 | register_inetaddr_notifier(&qlcnic_inetaddr_cb); | 3447 | register_inetaddr_notifier(&qlcnic_inetaddr_cb); |
@@ -3007,7 +3453,6 @@ static int __init qlcnic_init_module(void) | |||
3007 | unregister_inetaddr_notifier(&qlcnic_inetaddr_cb); | 3453 | unregister_inetaddr_notifier(&qlcnic_inetaddr_cb); |
3008 | unregister_netdevice_notifier(&qlcnic_netdev_cb); | 3454 | unregister_netdevice_notifier(&qlcnic_netdev_cb); |
3009 | #endif | 3455 | #endif |
3010 | destroy_workqueue(qlcnic_wq); | ||
3011 | } | 3456 | } |
3012 | 3457 | ||
3013 | return ret; | 3458 | return ret; |
@@ -3017,14 +3462,12 @@ module_init(qlcnic_init_module); | |||
3017 | 3462 | ||
3018 | static void __exit qlcnic_exit_module(void) | 3463 | static void __exit qlcnic_exit_module(void) |
3019 | { | 3464 | { |
3020 | |||
3021 | pci_unregister_driver(&qlcnic_driver); | 3465 | pci_unregister_driver(&qlcnic_driver); |
3022 | 3466 | ||
3023 | #ifdef CONFIG_INET | 3467 | #ifdef CONFIG_INET |
3024 | unregister_inetaddr_notifier(&qlcnic_inetaddr_cb); | 3468 | unregister_inetaddr_notifier(&qlcnic_inetaddr_cb); |
3025 | unregister_netdevice_notifier(&qlcnic_netdev_cb); | 3469 | unregister_netdevice_notifier(&qlcnic_netdev_cb); |
3026 | #endif | 3470 | #endif |
3027 | destroy_workqueue(qlcnic_wq); | ||
3028 | } | 3471 | } |
3029 | 3472 | ||
3030 | module_exit(qlcnic_exit_module); | 3473 | module_exit(qlcnic_exit_module); |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c index 0b8d8625834c..abbd22c814a6 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_minidump.c | |||
@@ -1,8 +1,25 @@ | |||
1 | /* | ||
2 | * QLogic qlcnic NIC Driver | ||
3 | * Copyright (c) 2009-2013 QLogic Corporation | ||
4 | * | ||
5 | * See LICENSE.qlcnic for copyright and licensing details. | ||
6 | */ | ||
7 | |||
1 | #include "qlcnic.h" | 8 | #include "qlcnic.h" |
2 | #include "qlcnic_hdr.h" | 9 | #include "qlcnic_hdr.h" |
10 | #include "qlcnic_83xx_hw.h" | ||
11 | #include "qlcnic_hw.h" | ||
3 | 12 | ||
4 | #include <net/ip.h> | 13 | #include <net/ip.h> |
5 | 14 | ||
15 | #define QLC_83XX_MINIDUMP_FLASH 0x520000 | ||
16 | #define QLC_83XX_OCM_INDEX 3 | ||
17 | #define QLC_83XX_PCI_INDEX 0 | ||
18 | |||
19 | static const u32 qlcnic_ms_read_data[] = { | ||
20 | 0x410000A8, 0x410000AC, 0x410000B8, 0x410000BC | ||
21 | }; | ||
22 | |||
6 | #define QLCNIC_DUMP_WCRB BIT_0 | 23 | #define QLCNIC_DUMP_WCRB BIT_0 |
7 | #define QLCNIC_DUMP_RWCRB BIT_1 | 24 | #define QLCNIC_DUMP_RWCRB BIT_1 |
8 | #define QLCNIC_DUMP_ANDCRB BIT_2 | 25 | #define QLCNIC_DUMP_ANDCRB BIT_2 |
@@ -102,16 +119,55 @@ struct __queue { | |||
102 | u8 rsvd3[2]; | 119 | u8 rsvd3[2]; |
103 | } __packed; | 120 | } __packed; |
104 | 121 | ||
122 | struct __pollrd { | ||
123 | u32 sel_addr; | ||
124 | u32 read_addr; | ||
125 | u32 sel_val; | ||
126 | u16 sel_val_stride; | ||
127 | u16 no_ops; | ||
128 | u32 poll_wait; | ||
129 | u32 poll_mask; | ||
130 | u32 data_size; | ||
131 | u8 rsvd[4]; | ||
132 | } __packed; | ||
133 | |||
134 | struct __mux2 { | ||
135 | u32 sel_addr1; | ||
136 | u32 sel_addr2; | ||
137 | u32 sel_val1; | ||
138 | u32 sel_val2; | ||
139 | u32 no_ops; | ||
140 | u32 sel_val_mask; | ||
141 | u32 read_addr; | ||
142 | u8 sel_val_stride; | ||
143 | u8 data_size; | ||
144 | u8 rsvd[2]; | ||
145 | } __packed; | ||
146 | |||
147 | struct __pollrdmwr { | ||
148 | u32 addr1; | ||
149 | u32 addr2; | ||
150 | u32 val1; | ||
151 | u32 val2; | ||
152 | u32 poll_wait; | ||
153 | u32 poll_mask; | ||
154 | u32 mod_mask; | ||
155 | u32 data_size; | ||
156 | } __packed; | ||
157 | |||
105 | struct qlcnic_dump_entry { | 158 | struct qlcnic_dump_entry { |
106 | struct qlcnic_common_entry_hdr hdr; | 159 | struct qlcnic_common_entry_hdr hdr; |
107 | union { | 160 | union { |
108 | struct __crb crb; | 161 | struct __crb crb; |
109 | struct __cache cache; | 162 | struct __cache cache; |
110 | struct __ocm ocm; | 163 | struct __ocm ocm; |
111 | struct __mem mem; | 164 | struct __mem mem; |
112 | struct __mux mux; | 165 | struct __mux mux; |
113 | struct __queue que; | 166 | struct __queue que; |
114 | struct __ctrl ctrl; | 167 | struct __ctrl ctrl; |
168 | struct __pollrdmwr pollrdmwr; | ||
169 | struct __mux2 mux2; | ||
170 | struct __pollrd pollrd; | ||
115 | } region; | 171 | } region; |
116 | } __packed; | 172 | } __packed; |
117 | 173 | ||
@@ -131,6 +187,9 @@ enum qlcnic_minidump_opcode { | |||
131 | QLCNIC_DUMP_L2_ITAG = 22, | 187 | QLCNIC_DUMP_L2_ITAG = 22, |
132 | QLCNIC_DUMP_L2_DATA = 23, | 188 | QLCNIC_DUMP_L2_DATA = 23, |
133 | QLCNIC_DUMP_L2_INST = 24, | 189 | QLCNIC_DUMP_L2_INST = 24, |
190 | QLCNIC_DUMP_POLL_RD = 35, | ||
191 | QLCNIC_READ_MUX2 = 36, | ||
192 | QLCNIC_READ_POLLRDMWR = 37, | ||
134 | QLCNIC_DUMP_READ_ROM = 71, | 193 | QLCNIC_DUMP_READ_ROM = 71, |
135 | QLCNIC_DUMP_READ_MEM = 72, | 194 | QLCNIC_DUMP_READ_MEM = 72, |
136 | QLCNIC_DUMP_READ_CTRL = 98, | 195 | QLCNIC_DUMP_READ_CTRL = 98, |
@@ -144,46 +203,17 @@ struct qlcnic_dump_operations { | |||
144 | __le32 *); | 203 | __le32 *); |
145 | }; | 204 | }; |
146 | 205 | ||
147 | static void qlcnic_read_dump_reg(u32 addr, void __iomem *bar0, u32 *data) | ||
148 | { | ||
149 | u32 dest; | ||
150 | void __iomem *window_reg; | ||
151 | |||
152 | dest = addr & 0xFFFF0000; | ||
153 | window_reg = bar0 + QLCNIC_FW_DUMP_REG1; | ||
154 | writel(dest, window_reg); | ||
155 | readl(window_reg); | ||
156 | window_reg = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr); | ||
157 | *data = readl(window_reg); | ||
158 | } | ||
159 | |||
160 | static void qlcnic_write_dump_reg(u32 addr, void __iomem *bar0, u32 data) | ||
161 | { | ||
162 | u32 dest; | ||
163 | void __iomem *window_reg; | ||
164 | |||
165 | dest = addr & 0xFFFF0000; | ||
166 | window_reg = bar0 + QLCNIC_FW_DUMP_REG1; | ||
167 | writel(dest, window_reg); | ||
168 | readl(window_reg); | ||
169 | window_reg = bar0 + QLCNIC_FW_DUMP_REG2 + LSW(addr); | ||
170 | writel(data, window_reg); | ||
171 | readl(window_reg); | ||
172 | } | ||
173 | |||
174 | /* FW dump related functions */ | ||
175 | static u32 qlcnic_dump_crb(struct qlcnic_adapter *adapter, | 206 | static u32 qlcnic_dump_crb(struct qlcnic_adapter *adapter, |
176 | struct qlcnic_dump_entry *entry, __le32 *buffer) | 207 | struct qlcnic_dump_entry *entry, __le32 *buffer) |
177 | { | 208 | { |
178 | int i; | 209 | int i; |
179 | u32 addr, data; | 210 | u32 addr, data; |
180 | struct __crb *crb = &entry->region.crb; | 211 | struct __crb *crb = &entry->region.crb; |
181 | void __iomem *base = adapter->ahw->pci_base0; | ||
182 | 212 | ||
183 | addr = crb->addr; | 213 | addr = crb->addr; |
184 | 214 | ||
185 | for (i = 0; i < crb->no_ops; i++) { | 215 | for (i = 0; i < crb->no_ops; i++) { |
186 | qlcnic_read_dump_reg(addr, base, &data); | 216 | data = qlcnic_ind_rd(adapter, addr); |
187 | *buffer++ = cpu_to_le32(addr); | 217 | *buffer++ = cpu_to_le32(addr); |
188 | *buffer++ = cpu_to_le32(data); | 218 | *buffer++ = cpu_to_le32(data); |
189 | addr += crb->stride; | 219 | addr += crb->stride; |
@@ -195,7 +225,6 @@ static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter, | |||
195 | struct qlcnic_dump_entry *entry, __le32 *buffer) | 225 | struct qlcnic_dump_entry *entry, __le32 *buffer) |
196 | { | 226 | { |
197 | int i, k, timeout = 0; | 227 | int i, k, timeout = 0; |
198 | void __iomem *base = adapter->ahw->pci_base0; | ||
199 | u32 addr, data; | 228 | u32 addr, data; |
200 | u8 no_ops; | 229 | u8 no_ops; |
201 | struct __ctrl *ctr = &entry->region.ctrl; | 230 | struct __ctrl *ctr = &entry->region.ctrl; |
@@ -211,28 +240,28 @@ static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter, | |||
211 | continue; | 240 | continue; |
212 | switch (1 << k) { | 241 | switch (1 << k) { |
213 | case QLCNIC_DUMP_WCRB: | 242 | case QLCNIC_DUMP_WCRB: |
214 | qlcnic_write_dump_reg(addr, base, ctr->val1); | 243 | qlcnic_ind_wr(adapter, addr, ctr->val1); |
215 | break; | 244 | break; |
216 | case QLCNIC_DUMP_RWCRB: | 245 | case QLCNIC_DUMP_RWCRB: |
217 | qlcnic_read_dump_reg(addr, base, &data); | 246 | data = qlcnic_ind_rd(adapter, addr); |
218 | qlcnic_write_dump_reg(addr, base, data); | 247 | qlcnic_ind_wr(adapter, addr, data); |
219 | break; | 248 | break; |
220 | case QLCNIC_DUMP_ANDCRB: | 249 | case QLCNIC_DUMP_ANDCRB: |
221 | qlcnic_read_dump_reg(addr, base, &data); | 250 | data = qlcnic_ind_rd(adapter, addr); |
222 | qlcnic_write_dump_reg(addr, base, | 251 | qlcnic_ind_wr(adapter, addr, |
223 | data & ctr->val2); | 252 | (data & ctr->val2)); |
224 | break; | 253 | break; |
225 | case QLCNIC_DUMP_ORCRB: | 254 | case QLCNIC_DUMP_ORCRB: |
226 | qlcnic_read_dump_reg(addr, base, &data); | 255 | data = qlcnic_ind_rd(adapter, addr); |
227 | qlcnic_write_dump_reg(addr, base, | 256 | qlcnic_ind_wr(adapter, addr, |
228 | data | ctr->val3); | 257 | (data | ctr->val3)); |
229 | break; | 258 | break; |
230 | case QLCNIC_DUMP_POLLCRB: | 259 | case QLCNIC_DUMP_POLLCRB: |
231 | while (timeout <= ctr->timeout) { | 260 | while (timeout <= ctr->timeout) { |
232 | qlcnic_read_dump_reg(addr, base, &data); | 261 | data = qlcnic_ind_rd(adapter, addr); |
233 | if ((data & ctr->val2) == ctr->val1) | 262 | if ((data & ctr->val2) == ctr->val1) |
234 | break; | 263 | break; |
235 | msleep(1); | 264 | usleep_range(1000, 2000); |
236 | timeout++; | 265 | timeout++; |
237 | } | 266 | } |
238 | if (timeout > ctr->timeout) { | 267 | if (timeout > ctr->timeout) { |
@@ -244,7 +273,7 @@ static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter, | |||
244 | case QLCNIC_DUMP_RD_SAVE: | 273 | case QLCNIC_DUMP_RD_SAVE: |
245 | if (ctr->index_a) | 274 | if (ctr->index_a) |
246 | addr = t_hdr->saved_state[ctr->index_a]; | 275 | addr = t_hdr->saved_state[ctr->index_a]; |
247 | qlcnic_read_dump_reg(addr, base, &data); | 276 | data = qlcnic_ind_rd(adapter, addr); |
248 | t_hdr->saved_state[ctr->index_v] = data; | 277 | t_hdr->saved_state[ctr->index_v] = data; |
249 | break; | 278 | break; |
250 | case QLCNIC_DUMP_WRT_SAVED: | 279 | case QLCNIC_DUMP_WRT_SAVED: |
@@ -254,7 +283,7 @@ static u32 qlcnic_dump_ctrl(struct qlcnic_adapter *adapter, | |||
254 | data = ctr->val1; | 283 | data = ctr->val1; |
255 | if (ctr->index_a) | 284 | if (ctr->index_a) |
256 | addr = t_hdr->saved_state[ctr->index_a]; | 285 | addr = t_hdr->saved_state[ctr->index_a]; |
257 | qlcnic_write_dump_reg(addr, base, data); | 286 | qlcnic_ind_wr(adapter, addr, data); |
258 | break; | 287 | break; |
259 | case QLCNIC_DUMP_MOD_SAVE_ST: | 288 | case QLCNIC_DUMP_MOD_SAVE_ST: |
260 | data = t_hdr->saved_state[ctr->index_v]; | 289 | data = t_hdr->saved_state[ctr->index_v]; |
@@ -283,12 +312,11 @@ static u32 qlcnic_dump_mux(struct qlcnic_adapter *adapter, | |||
283 | int loop; | 312 | int loop; |
284 | u32 val, data = 0; | 313 | u32 val, data = 0; |
285 | struct __mux *mux = &entry->region.mux; | 314 | struct __mux *mux = &entry->region.mux; |
286 | void __iomem *base = adapter->ahw->pci_base0; | ||
287 | 315 | ||
288 | val = mux->val; | 316 | val = mux->val; |
289 | for (loop = 0; loop < mux->no_ops; loop++) { | 317 | for (loop = 0; loop < mux->no_ops; loop++) { |
290 | qlcnic_write_dump_reg(mux->addr, base, val); | 318 | qlcnic_ind_wr(adapter, mux->addr, val); |
291 | qlcnic_read_dump_reg(mux->read_addr, base, &data); | 319 | data = qlcnic_ind_rd(adapter, mux->read_addr); |
292 | *buffer++ = cpu_to_le32(val); | 320 | *buffer++ = cpu_to_le32(val); |
293 | *buffer++ = cpu_to_le32(data); | 321 | *buffer++ = cpu_to_le32(data); |
294 | val += mux->val_stride; | 322 | val += mux->val_stride; |
@@ -301,17 +329,16 @@ static u32 qlcnic_dump_que(struct qlcnic_adapter *adapter, | |||
301 | { | 329 | { |
302 | int i, loop; | 330 | int i, loop; |
303 | u32 cnt, addr, data, que_id = 0; | 331 | u32 cnt, addr, data, que_id = 0; |
304 | void __iomem *base = adapter->ahw->pci_base0; | ||
305 | struct __queue *que = &entry->region.que; | 332 | struct __queue *que = &entry->region.que; |
306 | 333 | ||
307 | addr = que->read_addr; | 334 | addr = que->read_addr; |
308 | cnt = que->read_addr_cnt; | 335 | cnt = que->read_addr_cnt; |
309 | 336 | ||
310 | for (loop = 0; loop < que->no_ops; loop++) { | 337 | for (loop = 0; loop < que->no_ops; loop++) { |
311 | qlcnic_write_dump_reg(que->sel_addr, base, que_id); | 338 | qlcnic_ind_wr(adapter, que->sel_addr, que_id); |
312 | addr = que->read_addr; | 339 | addr = que->read_addr; |
313 | for (i = 0; i < cnt; i++) { | 340 | for (i = 0; i < cnt; i++) { |
314 | qlcnic_read_dump_reg(addr, base, &data); | 341 | data = qlcnic_ind_rd(adapter, addr); |
315 | *buffer++ = cpu_to_le32(data); | 342 | *buffer++ = cpu_to_le32(data); |
316 | addr += que->read_addr_stride; | 343 | addr += que->read_addr_stride; |
317 | } | 344 | } |
@@ -343,27 +370,27 @@ static u32 qlcnic_read_rom(struct qlcnic_adapter *adapter, | |||
343 | int i, count = 0; | 370 | int i, count = 0; |
344 | u32 fl_addr, size, val, lck_val, addr; | 371 | u32 fl_addr, size, val, lck_val, addr; |
345 | struct __mem *rom = &entry->region.mem; | 372 | struct __mem *rom = &entry->region.mem; |
346 | void __iomem *base = adapter->ahw->pci_base0; | ||
347 | 373 | ||
348 | fl_addr = rom->addr; | 374 | fl_addr = rom->addr; |
349 | size = rom->size/4; | 375 | size = rom->size / 4; |
350 | lock_try: | 376 | lock_try: |
351 | lck_val = readl(base + QLCNIC_FLASH_SEM2_LK); | 377 | lck_val = QLC_SHARED_REG_RD32(adapter, QLCNIC_FLASH_LOCK); |
352 | if (!lck_val && count < MAX_CTL_CHECK) { | 378 | if (!lck_val && count < MAX_CTL_CHECK) { |
353 | msleep(10); | 379 | usleep_range(10000, 11000); |
354 | count++; | 380 | count++; |
355 | goto lock_try; | 381 | goto lock_try; |
356 | } | 382 | } |
357 | writel(adapter->ahw->pci_func, (base + QLCNIC_FLASH_LOCK_ID)); | 383 | QLC_SHARED_REG_WR32(adapter, QLCNIC_FLASH_LOCK_OWNER, |
384 | adapter->ahw->pci_func); | ||
358 | for (i = 0; i < size; i++) { | 385 | for (i = 0; i < size; i++) { |
359 | addr = fl_addr & 0xFFFF0000; | 386 | addr = fl_addr & 0xFFFF0000; |
360 | qlcnic_write_dump_reg(FLASH_ROM_WINDOW, base, addr); | 387 | qlcnic_ind_wr(adapter, FLASH_ROM_WINDOW, addr); |
361 | addr = LSW(fl_addr) + FLASH_ROM_DATA; | 388 | addr = LSW(fl_addr) + FLASH_ROM_DATA; |
362 | qlcnic_read_dump_reg(addr, base, &val); | 389 | val = qlcnic_ind_rd(adapter, addr); |
363 | fl_addr += 4; | 390 | fl_addr += 4; |
364 | *buffer++ = cpu_to_le32(val); | 391 | *buffer++ = cpu_to_le32(val); |
365 | } | 392 | } |
366 | readl(base + QLCNIC_FLASH_SEM2_ULK); | 393 | QLC_SHARED_REG_RD32(adapter, QLCNIC_FLASH_UNLOCK); |
367 | return rom->size; | 394 | return rom->size; |
368 | } | 395 | } |
369 | 396 | ||
@@ -372,18 +399,17 @@ static u32 qlcnic_dump_l1_cache(struct qlcnic_adapter *adapter, | |||
372 | { | 399 | { |
373 | int i; | 400 | int i; |
374 | u32 cnt, val, data, addr; | 401 | u32 cnt, val, data, addr; |
375 | void __iomem *base = adapter->ahw->pci_base0; | ||
376 | struct __cache *l1 = &entry->region.cache; | 402 | struct __cache *l1 = &entry->region.cache; |
377 | 403 | ||
378 | val = l1->init_tag_val; | 404 | val = l1->init_tag_val; |
379 | 405 | ||
380 | for (i = 0; i < l1->no_ops; i++) { | 406 | for (i = 0; i < l1->no_ops; i++) { |
381 | qlcnic_write_dump_reg(l1->addr, base, val); | 407 | qlcnic_ind_wr(adapter, l1->addr, val); |
382 | qlcnic_write_dump_reg(l1->ctrl_addr, base, LSW(l1->ctrl_val)); | 408 | qlcnic_ind_wr(adapter, l1->ctrl_addr, LSW(l1->ctrl_val)); |
383 | addr = l1->read_addr; | 409 | addr = l1->read_addr; |
384 | cnt = l1->read_addr_num; | 410 | cnt = l1->read_addr_num; |
385 | while (cnt) { | 411 | while (cnt) { |
386 | qlcnic_read_dump_reg(addr, base, &data); | 412 | data = qlcnic_ind_rd(adapter, addr); |
387 | *buffer++ = cpu_to_le32(data); | 413 | *buffer++ = cpu_to_le32(data); |
388 | addr += l1->read_addr_stride; | 414 | addr += l1->read_addr_stride; |
389 | cnt--; | 415 | cnt--; |
@@ -399,7 +425,6 @@ static u32 qlcnic_dump_l2_cache(struct qlcnic_adapter *adapter, | |||
399 | int i; | 425 | int i; |
400 | u32 cnt, val, data, addr; | 426 | u32 cnt, val, data, addr; |
401 | u8 poll_mask, poll_to, time_out = 0; | 427 | u8 poll_mask, poll_to, time_out = 0; |
402 | void __iomem *base = adapter->ahw->pci_base0; | ||
403 | struct __cache *l2 = &entry->region.cache; | 428 | struct __cache *l2 = &entry->region.cache; |
404 | 429 | ||
405 | val = l2->init_tag_val; | 430 | val = l2->init_tag_val; |
@@ -407,17 +432,17 @@ static u32 qlcnic_dump_l2_cache(struct qlcnic_adapter *adapter, | |||
407 | poll_to = MSB(MSW(l2->ctrl_val)); | 432 | poll_to = MSB(MSW(l2->ctrl_val)); |
408 | 433 | ||
409 | for (i = 0; i < l2->no_ops; i++) { | 434 | for (i = 0; i < l2->no_ops; i++) { |
410 | qlcnic_write_dump_reg(l2->addr, base, val); | 435 | qlcnic_ind_wr(adapter, l2->addr, val); |
411 | if (LSW(l2->ctrl_val)) | 436 | if (LSW(l2->ctrl_val)) |
412 | qlcnic_write_dump_reg(l2->ctrl_addr, base, | 437 | qlcnic_ind_wr(adapter, l2->ctrl_addr, |
413 | LSW(l2->ctrl_val)); | 438 | LSW(l2->ctrl_val)); |
414 | if (!poll_mask) | 439 | if (!poll_mask) |
415 | goto skip_poll; | 440 | goto skip_poll; |
416 | do { | 441 | do { |
417 | qlcnic_read_dump_reg(l2->ctrl_addr, base, &data); | 442 | data = qlcnic_ind_rd(adapter, l2->ctrl_addr); |
418 | if (!(data & poll_mask)) | 443 | if (!(data & poll_mask)) |
419 | break; | 444 | break; |
420 | msleep(1); | 445 | usleep_range(1000, 2000); |
421 | time_out++; | 446 | time_out++; |
422 | } while (time_out <= poll_to); | 447 | } while (time_out <= poll_to); |
423 | 448 | ||
@@ -431,7 +456,7 @@ skip_poll: | |||
431 | addr = l2->read_addr; | 456 | addr = l2->read_addr; |
432 | cnt = l2->read_addr_num; | 457 | cnt = l2->read_addr_num; |
433 | while (cnt) { | 458 | while (cnt) { |
434 | qlcnic_read_dump_reg(addr, base, &data); | 459 | data = qlcnic_ind_rd(adapter, addr); |
435 | *buffer++ = cpu_to_le32(data); | 460 | *buffer++ = cpu_to_le32(data); |
436 | addr += l2->read_addr_stride; | 461 | addr += l2->read_addr_stride; |
437 | cnt--; | 462 | cnt--; |
@@ -447,7 +472,6 @@ static u32 qlcnic_read_memory(struct qlcnic_adapter *adapter, | |||
447 | u32 addr, data, test, ret = 0; | 472 | u32 addr, data, test, ret = 0; |
448 | int i, reg_read; | 473 | int i, reg_read; |
449 | struct __mem *mem = &entry->region.mem; | 474 | struct __mem *mem = &entry->region.mem; |
450 | void __iomem *base = adapter->ahw->pci_base0; | ||
451 | 475 | ||
452 | reg_read = mem->size; | 476 | reg_read = mem->size; |
453 | addr = mem->addr; | 477 | addr = mem->addr; |
@@ -462,13 +486,12 @@ static u32 qlcnic_read_memory(struct qlcnic_adapter *adapter, | |||
462 | mutex_lock(&adapter->ahw->mem_lock); | 486 | mutex_lock(&adapter->ahw->mem_lock); |
463 | 487 | ||
464 | while (reg_read != 0) { | 488 | while (reg_read != 0) { |
465 | qlcnic_write_dump_reg(MIU_TEST_ADDR_LO, base, addr); | 489 | qlcnic_ind_wr(adapter, QLCNIC_MS_ADDR_LO, addr); |
466 | qlcnic_write_dump_reg(MIU_TEST_ADDR_HI, base, 0); | 490 | qlcnic_ind_wr(adapter, QLCNIC_MS_ADDR_HI, 0); |
467 | qlcnic_write_dump_reg(MIU_TEST_CTR, base, | 491 | qlcnic_ind_wr(adapter, QLCNIC_MS_CTRL, QLCNIC_TA_START_ENABLE); |
468 | TA_CTL_ENABLE | TA_CTL_START); | ||
469 | 492 | ||
470 | for (i = 0; i < MAX_CTL_CHECK; i++) { | 493 | for (i = 0; i < MAX_CTL_CHECK; i++) { |
471 | qlcnic_read_dump_reg(MIU_TEST_CTR, base, &test); | 494 | test = qlcnic_ind_rd(adapter, QLCNIC_MS_CTRL); |
472 | if (!(test & TA_CTL_BUSY)) | 495 | if (!(test & TA_CTL_BUSY)) |
473 | break; | 496 | break; |
474 | } | 497 | } |
@@ -481,8 +504,7 @@ static u32 qlcnic_read_memory(struct qlcnic_adapter *adapter, | |||
481 | } | 504 | } |
482 | } | 505 | } |
483 | for (i = 0; i < 4; i++) { | 506 | for (i = 0; i < 4; i++) { |
484 | qlcnic_read_dump_reg(MIU_TEST_READ_DATA[i], base, | 507 | data = qlcnic_ind_rd(adapter, qlcnic_ms_read_data[i]); |
485 | &data); | ||
486 | *buffer++ = cpu_to_le32(data); | 508 | *buffer++ = cpu_to_le32(data); |
487 | } | 509 | } |
488 | addr += 16; | 510 | addr += 16; |
@@ -501,48 +523,388 @@ static u32 qlcnic_dump_nop(struct qlcnic_adapter *adapter, | |||
501 | return 0; | 523 | return 0; |
502 | } | 524 | } |
503 | 525 | ||
504 | static const struct qlcnic_dump_operations fw_dump_ops[] = { | 526 | static int qlcnic_valid_dump_entry(struct device *dev, |
505 | { QLCNIC_DUMP_NOP, qlcnic_dump_nop }, | 527 | struct qlcnic_dump_entry *entry, u32 size) |
506 | { QLCNIC_DUMP_READ_CRB, qlcnic_dump_crb }, | ||
507 | { QLCNIC_DUMP_READ_MUX, qlcnic_dump_mux }, | ||
508 | { QLCNIC_DUMP_QUEUE, qlcnic_dump_que }, | ||
509 | { QLCNIC_DUMP_BRD_CONFIG, qlcnic_read_rom }, | ||
510 | { QLCNIC_DUMP_READ_OCM, qlcnic_dump_ocm }, | ||
511 | { QLCNIC_DUMP_PEG_REG, qlcnic_dump_ctrl }, | ||
512 | { QLCNIC_DUMP_L1_DTAG, qlcnic_dump_l1_cache }, | ||
513 | { QLCNIC_DUMP_L1_ITAG, qlcnic_dump_l1_cache }, | ||
514 | { QLCNIC_DUMP_L1_DATA, qlcnic_dump_l1_cache }, | ||
515 | { QLCNIC_DUMP_L1_INST, qlcnic_dump_l1_cache }, | ||
516 | { QLCNIC_DUMP_L2_DTAG, qlcnic_dump_l2_cache }, | ||
517 | { QLCNIC_DUMP_L2_ITAG, qlcnic_dump_l2_cache }, | ||
518 | { QLCNIC_DUMP_L2_DATA, qlcnic_dump_l2_cache }, | ||
519 | { QLCNIC_DUMP_L2_INST, qlcnic_dump_l2_cache }, | ||
520 | { QLCNIC_DUMP_READ_ROM, qlcnic_read_rom }, | ||
521 | { QLCNIC_DUMP_READ_MEM, qlcnic_read_memory }, | ||
522 | { QLCNIC_DUMP_READ_CTRL, qlcnic_dump_ctrl }, | ||
523 | { QLCNIC_DUMP_TLHDR, qlcnic_dump_nop }, | ||
524 | { QLCNIC_DUMP_RDEND, qlcnic_dump_nop }, | ||
525 | }; | ||
526 | |||
527 | /* Walk the template and collect dump for each entry in the dump template */ | ||
528 | static int | ||
529 | qlcnic_valid_dump_entry(struct device *dev, struct qlcnic_dump_entry *entry, | ||
530 | u32 size) | ||
531 | { | 528 | { |
532 | int ret = 1; | 529 | int ret = 1; |
533 | if (size != entry->hdr.cap_size) { | 530 | if (size != entry->hdr.cap_size) { |
534 | dev_info(dev, | 531 | dev_err(dev, |
535 | "Invalid dump, Type:%d\tMask:%d\tSize:%dCap_size:%d\n", | 532 | "Invalid entry, Type:%d\tMask:%d\tSize:%dCap_size:%d\n", |
536 | entry->hdr.type, entry->hdr.mask, size, entry->hdr.cap_size); | 533 | entry->hdr.type, entry->hdr.mask, size, |
537 | dev_info(dev, "Aborting further dump capture\n"); | 534 | entry->hdr.cap_size); |
538 | ret = 0; | 535 | ret = 0; |
539 | } | 536 | } |
540 | return ret; | 537 | return ret; |
541 | } | 538 | } |
542 | 539 | ||
540 | static u32 qlcnic_read_pollrdmwr(struct qlcnic_adapter *adapter, | ||
541 | struct qlcnic_dump_entry *entry, | ||
542 | __le32 *buffer) | ||
543 | { | ||
544 | struct __pollrdmwr *poll = &entry->region.pollrdmwr; | ||
545 | u32 data, wait_count, poll_wait, temp; | ||
546 | |||
547 | poll_wait = poll->poll_wait; | ||
548 | |||
549 | qlcnic_ind_wr(adapter, poll->addr1, poll->val1); | ||
550 | wait_count = 0; | ||
551 | |||
552 | while (wait_count < poll_wait) { | ||
553 | data = qlcnic_ind_rd(adapter, poll->addr1); | ||
554 | if ((data & poll->poll_mask) != 0) | ||
555 | break; | ||
556 | wait_count++; | ||
557 | } | ||
558 | |||
559 | if (wait_count == poll_wait) { | ||
560 | dev_err(&adapter->pdev->dev, | ||
561 | "Timeout exceeded in %s, aborting dump\n", | ||
562 | __func__); | ||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | data = qlcnic_ind_rd(adapter, poll->addr2) & poll->mod_mask; | ||
567 | qlcnic_ind_wr(adapter, poll->addr2, data); | ||
568 | qlcnic_ind_wr(adapter, poll->addr1, poll->val2); | ||
569 | wait_count = 0; | ||
570 | |||
571 | while (wait_count < poll_wait) { | ||
572 | temp = qlcnic_ind_rd(adapter, poll->addr1); | ||
573 | if ((temp & poll->poll_mask) != 0) | ||
574 | break; | ||
575 | wait_count++; | ||
576 | } | ||
577 | |||
578 | *buffer++ = cpu_to_le32(poll->addr2); | ||
579 | *buffer++ = cpu_to_le32(data); | ||
580 | |||
581 | return 2 * sizeof(u32); | ||
582 | |||
583 | } | ||
584 | |||
585 | static u32 qlcnic_read_pollrd(struct qlcnic_adapter *adapter, | ||
586 | struct qlcnic_dump_entry *entry, __le32 *buffer) | ||
587 | { | ||
588 | struct __pollrd *pollrd = &entry->region.pollrd; | ||
589 | u32 data, wait_count, poll_wait, sel_val; | ||
590 | int i; | ||
591 | |||
592 | poll_wait = pollrd->poll_wait; | ||
593 | sel_val = pollrd->sel_val; | ||
594 | |||
595 | for (i = 0; i < pollrd->no_ops; i++) { | ||
596 | qlcnic_ind_wr(adapter, pollrd->sel_addr, sel_val); | ||
597 | wait_count = 0; | ||
598 | while (wait_count < poll_wait) { | ||
599 | data = qlcnic_ind_rd(adapter, pollrd->sel_addr); | ||
600 | if ((data & pollrd->poll_mask) != 0) | ||
601 | break; | ||
602 | wait_count++; | ||
603 | } | ||
604 | |||
605 | if (wait_count == poll_wait) { | ||
606 | dev_err(&adapter->pdev->dev, | ||
607 | "Timeout exceeded in %s, aborting dump\n", | ||
608 | __func__); | ||
609 | return 0; | ||
610 | } | ||
611 | |||
612 | data = qlcnic_ind_rd(adapter, pollrd->read_addr); | ||
613 | *buffer++ = cpu_to_le32(sel_val); | ||
614 | *buffer++ = cpu_to_le32(data); | ||
615 | sel_val += pollrd->sel_val_stride; | ||
616 | } | ||
617 | return pollrd->no_ops * (2 * sizeof(u32)); | ||
618 | } | ||
619 | |||
620 | static u32 qlcnic_read_mux2(struct qlcnic_adapter *adapter, | ||
621 | struct qlcnic_dump_entry *entry, __le32 *buffer) | ||
622 | { | ||
623 | struct __mux2 *mux2 = &entry->region.mux2; | ||
624 | u32 data; | ||
625 | u32 t_sel_val, sel_val1, sel_val2; | ||
626 | int i; | ||
627 | |||
628 | sel_val1 = mux2->sel_val1; | ||
629 | sel_val2 = mux2->sel_val2; | ||
630 | |||
631 | for (i = 0; i < mux2->no_ops; i++) { | ||
632 | qlcnic_ind_wr(adapter, mux2->sel_addr1, sel_val1); | ||
633 | t_sel_val = sel_val1 & mux2->sel_val_mask; | ||
634 | qlcnic_ind_wr(adapter, mux2->sel_addr2, t_sel_val); | ||
635 | data = qlcnic_ind_rd(adapter, mux2->read_addr); | ||
636 | *buffer++ = cpu_to_le32(t_sel_val); | ||
637 | *buffer++ = cpu_to_le32(data); | ||
638 | qlcnic_ind_wr(adapter, mux2->sel_addr1, sel_val2); | ||
639 | t_sel_val = sel_val2 & mux2->sel_val_mask; | ||
640 | qlcnic_ind_wr(adapter, mux2->sel_addr2, t_sel_val); | ||
641 | data = qlcnic_ind_rd(adapter, mux2->read_addr); | ||
642 | *buffer++ = cpu_to_le32(t_sel_val); | ||
643 | *buffer++ = cpu_to_le32(data); | ||
644 | sel_val1 += mux2->sel_val_stride; | ||
645 | sel_val2 += mux2->sel_val_stride; | ||
646 | } | ||
647 | |||
648 | return mux2->no_ops * (4 * sizeof(u32)); | ||
649 | } | ||
650 | |||
651 | static u32 qlcnic_83xx_dump_rom(struct qlcnic_adapter *adapter, | ||
652 | struct qlcnic_dump_entry *entry, __le32 *buffer) | ||
653 | { | ||
654 | u32 fl_addr, size; | ||
655 | struct __mem *rom = &entry->region.mem; | ||
656 | |||
657 | fl_addr = rom->addr; | ||
658 | size = rom->size / 4; | ||
659 | |||
660 | if (!qlcnic_83xx_lockless_flash_read32(adapter, fl_addr, | ||
661 | (u8 *)buffer, size)) | ||
662 | return rom->size; | ||
663 | |||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static const struct qlcnic_dump_operations qlcnic_fw_dump_ops[] = { | ||
668 | {QLCNIC_DUMP_NOP, qlcnic_dump_nop}, | ||
669 | {QLCNIC_DUMP_READ_CRB, qlcnic_dump_crb}, | ||
670 | {QLCNIC_DUMP_READ_MUX, qlcnic_dump_mux}, | ||
671 | {QLCNIC_DUMP_QUEUE, qlcnic_dump_que}, | ||
672 | {QLCNIC_DUMP_BRD_CONFIG, qlcnic_read_rom}, | ||
673 | {QLCNIC_DUMP_READ_OCM, qlcnic_dump_ocm}, | ||
674 | {QLCNIC_DUMP_PEG_REG, qlcnic_dump_ctrl}, | ||
675 | {QLCNIC_DUMP_L1_DTAG, qlcnic_dump_l1_cache}, | ||
676 | {QLCNIC_DUMP_L1_ITAG, qlcnic_dump_l1_cache}, | ||
677 | {QLCNIC_DUMP_L1_DATA, qlcnic_dump_l1_cache}, | ||
678 | {QLCNIC_DUMP_L1_INST, qlcnic_dump_l1_cache}, | ||
679 | {QLCNIC_DUMP_L2_DTAG, qlcnic_dump_l2_cache}, | ||
680 | {QLCNIC_DUMP_L2_ITAG, qlcnic_dump_l2_cache}, | ||
681 | {QLCNIC_DUMP_L2_DATA, qlcnic_dump_l2_cache}, | ||
682 | {QLCNIC_DUMP_L2_INST, qlcnic_dump_l2_cache}, | ||
683 | {QLCNIC_DUMP_READ_ROM, qlcnic_read_rom}, | ||
684 | {QLCNIC_DUMP_READ_MEM, qlcnic_read_memory}, | ||
685 | {QLCNIC_DUMP_READ_CTRL, qlcnic_dump_ctrl}, | ||
686 | {QLCNIC_DUMP_TLHDR, qlcnic_dump_nop}, | ||
687 | {QLCNIC_DUMP_RDEND, qlcnic_dump_nop}, | ||
688 | }; | ||
689 | |||
690 | static const struct qlcnic_dump_operations qlcnic_83xx_fw_dump_ops[] = { | ||
691 | {QLCNIC_DUMP_NOP, qlcnic_dump_nop}, | ||
692 | {QLCNIC_DUMP_READ_CRB, qlcnic_dump_crb}, | ||
693 | {QLCNIC_DUMP_READ_MUX, qlcnic_dump_mux}, | ||
694 | {QLCNIC_DUMP_QUEUE, qlcnic_dump_que}, | ||
695 | {QLCNIC_DUMP_BRD_CONFIG, qlcnic_83xx_dump_rom}, | ||
696 | {QLCNIC_DUMP_READ_OCM, qlcnic_dump_ocm}, | ||
697 | {QLCNIC_DUMP_PEG_REG, qlcnic_dump_ctrl}, | ||
698 | {QLCNIC_DUMP_L1_DTAG, qlcnic_dump_l1_cache}, | ||
699 | {QLCNIC_DUMP_L1_ITAG, qlcnic_dump_l1_cache}, | ||
700 | {QLCNIC_DUMP_L1_DATA, qlcnic_dump_l1_cache}, | ||
701 | {QLCNIC_DUMP_L1_INST, qlcnic_dump_l1_cache}, | ||
702 | {QLCNIC_DUMP_L2_DTAG, qlcnic_dump_l2_cache}, | ||
703 | {QLCNIC_DUMP_L2_ITAG, qlcnic_dump_l2_cache}, | ||
704 | {QLCNIC_DUMP_L2_DATA, qlcnic_dump_l2_cache}, | ||
705 | {QLCNIC_DUMP_L2_INST, qlcnic_dump_l2_cache}, | ||
706 | {QLCNIC_DUMP_POLL_RD, qlcnic_read_pollrd}, | ||
707 | {QLCNIC_READ_MUX2, qlcnic_read_mux2}, | ||
708 | {QLCNIC_READ_POLLRDMWR, qlcnic_read_pollrdmwr}, | ||
709 | {QLCNIC_DUMP_READ_ROM, qlcnic_83xx_dump_rom}, | ||
710 | {QLCNIC_DUMP_READ_MEM, qlcnic_read_memory}, | ||
711 | {QLCNIC_DUMP_READ_CTRL, qlcnic_dump_ctrl}, | ||
712 | {QLCNIC_DUMP_TLHDR, qlcnic_dump_nop}, | ||
713 | {QLCNIC_DUMP_RDEND, qlcnic_dump_nop}, | ||
714 | }; | ||
715 | |||
716 | static uint32_t qlcnic_temp_checksum(uint32_t *temp_buffer, u32 temp_size) | ||
717 | { | ||
718 | uint64_t sum = 0; | ||
719 | int count = temp_size / sizeof(uint32_t); | ||
720 | while (count-- > 0) | ||
721 | sum += *temp_buffer++; | ||
722 | while (sum >> 32) | ||
723 | sum = (sum & 0xFFFFFFFF) + (sum >> 32); | ||
724 | return ~sum; | ||
725 | } | ||
726 | |||
727 | static int qlcnic_fw_flash_get_minidump_temp(struct qlcnic_adapter *adapter, | ||
728 | u8 *buffer, u32 size) | ||
729 | { | ||
730 | int ret = 0; | ||
731 | |||
732 | if (qlcnic_82xx_check(adapter)) | ||
733 | return -EIO; | ||
734 | |||
735 | if (qlcnic_83xx_lock_flash(adapter)) | ||
736 | return -EIO; | ||
737 | |||
738 | ret = qlcnic_83xx_lockless_flash_read32(adapter, | ||
739 | QLC_83XX_MINIDUMP_FLASH, | ||
740 | buffer, size / sizeof(u32)); | ||
741 | |||
742 | qlcnic_83xx_unlock_flash(adapter); | ||
743 | |||
744 | return ret; | ||
745 | } | ||
746 | |||
747 | static int | ||
748 | qlcnic_fw_flash_get_minidump_temp_size(struct qlcnic_adapter *adapter, | ||
749 | struct qlcnic_cmd_args *cmd) | ||
750 | { | ||
751 | struct qlcnic_dump_template_hdr tmp_hdr; | ||
752 | u32 size = sizeof(struct qlcnic_dump_template_hdr) / sizeof(u32); | ||
753 | int ret = 0; | ||
754 | |||
755 | if (qlcnic_82xx_check(adapter)) | ||
756 | return -EIO; | ||
757 | |||
758 | if (qlcnic_83xx_lock_flash(adapter)) | ||
759 | return -EIO; | ||
760 | |||
761 | ret = qlcnic_83xx_lockless_flash_read32(adapter, | ||
762 | QLC_83XX_MINIDUMP_FLASH, | ||
763 | (u8 *)&tmp_hdr, size); | ||
764 | |||
765 | qlcnic_83xx_unlock_flash(adapter); | ||
766 | |||
767 | cmd->rsp.arg[2] = tmp_hdr.size; | ||
768 | cmd->rsp.arg[3] = tmp_hdr.version; | ||
769 | |||
770 | return ret; | ||
771 | } | ||
772 | |||
773 | static int qlcnic_fw_get_minidump_temp_size(struct qlcnic_adapter *adapter, | ||
774 | u32 *version, u32 *temp_size, | ||
775 | u8 *use_flash_temp) | ||
776 | { | ||
777 | int err = 0; | ||
778 | struct qlcnic_cmd_args cmd; | ||
779 | |||
780 | if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_TEMP_SIZE)) | ||
781 | return -ENOMEM; | ||
782 | |||
783 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
784 | if (err != QLCNIC_RCODE_SUCCESS) { | ||
785 | if (qlcnic_fw_flash_get_minidump_temp_size(adapter, &cmd)) { | ||
786 | qlcnic_free_mbx_args(&cmd); | ||
787 | return -EIO; | ||
788 | } | ||
789 | *use_flash_temp = 1; | ||
790 | } | ||
791 | |||
792 | *temp_size = cmd.rsp.arg[2]; | ||
793 | *version = cmd.rsp.arg[3]; | ||
794 | qlcnic_free_mbx_args(&cmd); | ||
795 | |||
796 | if (!(*temp_size)) | ||
797 | return -EIO; | ||
798 | |||
799 | return 0; | ||
800 | } | ||
801 | |||
802 | static int __qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter, | ||
803 | u32 *buffer, u32 temp_size) | ||
804 | { | ||
805 | int err = 0, i; | ||
806 | void *tmp_addr; | ||
807 | __le32 *tmp_buf; | ||
808 | struct qlcnic_cmd_args cmd; | ||
809 | dma_addr_t tmp_addr_t = 0; | ||
810 | |||
811 | tmp_addr = dma_alloc_coherent(&adapter->pdev->dev, temp_size, | ||
812 | &tmp_addr_t, GFP_KERNEL); | ||
813 | if (!tmp_addr) { | ||
814 | dev_err(&adapter->pdev->dev, | ||
815 | "Can't get memory for FW dump template\n"); | ||
816 | return -ENOMEM; | ||
817 | } | ||
818 | |||
819 | if (qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_TEMP_HDR)) { | ||
820 | err = -ENOMEM; | ||
821 | goto free_mem; | ||
822 | } | ||
823 | |||
824 | cmd.req.arg[1] = LSD(tmp_addr_t); | ||
825 | cmd.req.arg[2] = MSD(tmp_addr_t); | ||
826 | cmd.req.arg[3] = temp_size; | ||
827 | err = qlcnic_issue_cmd(adapter, &cmd); | ||
828 | |||
829 | tmp_buf = tmp_addr; | ||
830 | if (err == QLCNIC_RCODE_SUCCESS) { | ||
831 | for (i = 0; i < temp_size / sizeof(u32); i++) | ||
832 | *buffer++ = __le32_to_cpu(*tmp_buf++); | ||
833 | } | ||
834 | |||
835 | qlcnic_free_mbx_args(&cmd); | ||
836 | |||
837 | free_mem: | ||
838 | dma_free_coherent(&adapter->pdev->dev, temp_size, tmp_addr, tmp_addr_t); | ||
839 | |||
840 | return err; | ||
841 | } | ||
842 | |||
843 | int qlcnic_fw_cmd_get_minidump_temp(struct qlcnic_adapter *adapter) | ||
844 | { | ||
845 | int err; | ||
846 | u32 temp_size = 0; | ||
847 | u32 version, csum, *tmp_buf; | ||
848 | struct qlcnic_hardware_context *ahw; | ||
849 | struct qlcnic_dump_template_hdr *tmpl_hdr; | ||
850 | u8 use_flash_temp = 0; | ||
851 | |||
852 | ahw = adapter->ahw; | ||
853 | |||
854 | err = qlcnic_fw_get_minidump_temp_size(adapter, &version, &temp_size, | ||
855 | &use_flash_temp); | ||
856 | if (err) { | ||
857 | dev_err(&adapter->pdev->dev, | ||
858 | "Can't get template size %d\n", err); | ||
859 | return -EIO; | ||
860 | } | ||
861 | |||
862 | ahw->fw_dump.tmpl_hdr = vzalloc(temp_size); | ||
863 | if (!ahw->fw_dump.tmpl_hdr) | ||
864 | return -ENOMEM; | ||
865 | |||
866 | tmp_buf = (u32 *)ahw->fw_dump.tmpl_hdr; | ||
867 | if (use_flash_temp) | ||
868 | goto flash_temp; | ||
869 | |||
870 | err = __qlcnic_fw_cmd_get_minidump_temp(adapter, tmp_buf, temp_size); | ||
871 | |||
872 | if (err) { | ||
873 | flash_temp: | ||
874 | err = qlcnic_fw_flash_get_minidump_temp(adapter, (u8 *)tmp_buf, | ||
875 | temp_size); | ||
876 | |||
877 | if (err) { | ||
878 | dev_err(&adapter->pdev->dev, | ||
879 | "Failed to get minidump template header %d\n", | ||
880 | err); | ||
881 | vfree(ahw->fw_dump.tmpl_hdr); | ||
882 | ahw->fw_dump.tmpl_hdr = NULL; | ||
883 | return -EIO; | ||
884 | } | ||
885 | } | ||
886 | |||
887 | csum = qlcnic_temp_checksum((uint32_t *)tmp_buf, temp_size); | ||
888 | |||
889 | if (csum) { | ||
890 | dev_err(&adapter->pdev->dev, | ||
891 | "Template header checksum validation failed\n"); | ||
892 | vfree(ahw->fw_dump.tmpl_hdr); | ||
893 | ahw->fw_dump.tmpl_hdr = NULL; | ||
894 | return -EIO; | ||
895 | } | ||
896 | |||
897 | tmpl_hdr = ahw->fw_dump.tmpl_hdr; | ||
898 | tmpl_hdr->drv_cap_mask = QLCNIC_DUMP_MASK_DEF; | ||
899 | ahw->fw_dump.enable = 1; | ||
900 | |||
901 | return 0; | ||
902 | } | ||
903 | |||
543 | int qlcnic_dump_fw(struct qlcnic_adapter *adapter) | 904 | int qlcnic_dump_fw(struct qlcnic_adapter *adapter) |
544 | { | 905 | { |
545 | __le32 *buffer; | 906 | __le32 *buffer; |
907 | u32 ocm_window; | ||
546 | char mesg[64]; | 908 | char mesg[64]; |
547 | char *msg[] = {mesg, NULL}; | 909 | char *msg[] = {mesg, NULL}; |
548 | int i, k, ops_cnt, ops_index, dump_size = 0; | 910 | int i, k, ops_cnt, ops_index, dump_size = 0; |
@@ -550,12 +912,23 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter) | |||
550 | struct qlcnic_dump_entry *entry; | 912 | struct qlcnic_dump_entry *entry; |
551 | struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; | 913 | struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump; |
552 | struct qlcnic_dump_template_hdr *tmpl_hdr = fw_dump->tmpl_hdr; | 914 | struct qlcnic_dump_template_hdr *tmpl_hdr = fw_dump->tmpl_hdr; |
915 | static const struct qlcnic_dump_operations *fw_dump_ops; | ||
916 | struct qlcnic_hardware_context *ahw; | ||
917 | |||
918 | ahw = adapter->ahw; | ||
919 | |||
920 | if (!fw_dump->enable) { | ||
921 | dev_info(&adapter->pdev->dev, "Dump not enabled\n"); | ||
922 | return -EIO; | ||
923 | } | ||
553 | 924 | ||
554 | if (fw_dump->clr) { | 925 | if (fw_dump->clr) { |
555 | dev_info(&adapter->pdev->dev, | 926 | dev_info(&adapter->pdev->dev, |
556 | "Previous dump not cleared, not capturing dump\n"); | 927 | "Previous dump not cleared, not capturing dump\n"); |
557 | return -EIO; | 928 | return -EIO; |
558 | } | 929 | } |
930 | |||
931 | netif_info(adapter->ahw, drv, adapter->netdev, "Take FW dump\n"); | ||
559 | /* Calculate the size for dump data area only */ | 932 | /* Calculate the size for dump data area only */ |
560 | for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++) | 933 | for (i = 2, k = 1; (i & QLCNIC_DUMP_MASK_MAX); i <<= 1, k++) |
561 | if (i & tmpl_hdr->drv_cap_mask) | 934 | if (i & tmpl_hdr->drv_cap_mask) |
@@ -564,20 +937,27 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter) | |||
564 | return -EIO; | 937 | return -EIO; |
565 | 938 | ||
566 | fw_dump->data = vzalloc(dump_size); | 939 | fw_dump->data = vzalloc(dump_size); |
567 | if (!fw_dump->data) { | 940 | if (!fw_dump->data) |
568 | dev_info(&adapter->pdev->dev, | ||
569 | "Unable to allocate (%d KB) for fw dump\n", | ||
570 | dump_size / 1024); | ||
571 | return -ENOMEM; | 941 | return -ENOMEM; |
572 | } | 942 | |
573 | buffer = fw_dump->data; | 943 | buffer = fw_dump->data; |
574 | fw_dump->size = dump_size; | 944 | fw_dump->size = dump_size; |
575 | no_entries = tmpl_hdr->num_entries; | 945 | no_entries = tmpl_hdr->num_entries; |
576 | ops_cnt = ARRAY_SIZE(fw_dump_ops); | ||
577 | entry_offset = tmpl_hdr->offset; | 946 | entry_offset = tmpl_hdr->offset; |
578 | tmpl_hdr->sys_info[0] = QLCNIC_DRIVER_VERSION; | 947 | tmpl_hdr->sys_info[0] = QLCNIC_DRIVER_VERSION; |
579 | tmpl_hdr->sys_info[1] = adapter->fw_version; | 948 | tmpl_hdr->sys_info[1] = adapter->fw_version; |
580 | 949 | ||
950 | if (qlcnic_82xx_check(adapter)) { | ||
951 | ops_cnt = ARRAY_SIZE(qlcnic_fw_dump_ops); | ||
952 | fw_dump_ops = qlcnic_fw_dump_ops; | ||
953 | } else { | ||
954 | ops_cnt = ARRAY_SIZE(qlcnic_83xx_fw_dump_ops); | ||
955 | fw_dump_ops = qlcnic_83xx_fw_dump_ops; | ||
956 | ocm_window = tmpl_hdr->ocm_wnd_reg[adapter->ahw->pci_func]; | ||
957 | tmpl_hdr->saved_state[QLC_83XX_OCM_INDEX] = ocm_window; | ||
958 | tmpl_hdr->saved_state[QLC_83XX_PCI_INDEX] = ahw->pci_func; | ||
959 | } | ||
960 | |||
581 | for (i = 0; i < no_entries; i++) { | 961 | for (i = 0; i < no_entries; i++) { |
582 | entry = (void *)tmpl_hdr + entry_offset; | 962 | entry = (void *)tmpl_hdr + entry_offset; |
583 | if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) { | 963 | if (!(entry->hdr.mask & tmpl_hdr->drv_cap_mask)) { |
@@ -585,6 +965,7 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter) | |||
585 | entry_offset += entry->hdr.offset; | 965 | entry_offset += entry->hdr.offset; |
586 | continue; | 966 | continue; |
587 | } | 967 | } |
968 | |||
588 | /* Find the handler for this entry */ | 969 | /* Find the handler for this entry */ |
589 | ops_index = 0; | 970 | ops_index = 0; |
590 | while (ops_index < ops_cnt) { | 971 | while (ops_index < ops_cnt) { |
@@ -592,16 +973,17 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter) | |||
592 | break; | 973 | break; |
593 | ops_index++; | 974 | ops_index++; |
594 | } | 975 | } |
976 | |||
595 | if (ops_index == ops_cnt) { | 977 | if (ops_index == ops_cnt) { |
596 | dev_info(&adapter->pdev->dev, | 978 | dev_info(&adapter->pdev->dev, |
597 | "Invalid entry type %d, exiting dump\n", | 979 | "Invalid entry type %d, exiting dump\n", |
598 | entry->hdr.type); | 980 | entry->hdr.type); |
599 | goto error; | 981 | goto error; |
600 | } | 982 | } |
983 | |||
601 | /* Collect dump for this entry */ | 984 | /* Collect dump for this entry */ |
602 | dump = fw_dump_ops[ops_index].handler(adapter, entry, buffer); | 985 | dump = fw_dump_ops[ops_index].handler(adapter, entry, buffer); |
603 | if (dump && !qlcnic_valid_dump_entry(&adapter->pdev->dev, entry, | 986 | if (!qlcnic_valid_dump_entry(&adapter->pdev->dev, entry, dump)) |
604 | dump)) | ||
605 | entry->hdr.flags |= QLCNIC_DUMP_SKIP; | 987 | entry->hdr.flags |= QLCNIC_DUMP_SKIP; |
606 | buf_offset += entry->hdr.cap_size; | 988 | buf_offset += entry->hdr.cap_size; |
607 | entry_offset += entry->hdr.offset; | 989 | entry_offset += entry->hdr.offset; |
@@ -616,8 +998,8 @@ int qlcnic_dump_fw(struct qlcnic_adapter *adapter) | |||
616 | fw_dump->clr = 1; | 998 | fw_dump->clr = 1; |
617 | snprintf(mesg, sizeof(mesg), "FW_DUMP=%s", | 999 | snprintf(mesg, sizeof(mesg), "FW_DUMP=%s", |
618 | adapter->netdev->name); | 1000 | adapter->netdev->name); |
619 | dev_info(&adapter->pdev->dev, "Dump data, %d bytes captured\n", | 1001 | dev_info(&adapter->pdev->dev, "%s: Dump data, %d bytes captured\n", |
620 | fw_dump->size); | 1002 | adapter->netdev->name, fw_dump->size); |
621 | /* Send a udev event to notify availability of FW dump */ | 1003 | /* Send a udev event to notify availability of FW dump */ |
622 | kobject_uevent_env(&adapter->pdev->dev.kobj, KOBJ_CHANGE, msg); | 1004 | kobject_uevent_env(&adapter->pdev->dev.kobj, KOBJ_CHANGE, msg); |
623 | return 0; | 1005 | return 0; |
@@ -626,3 +1008,21 @@ error: | |||
626 | vfree(fw_dump->data); | 1008 | vfree(fw_dump->data); |
627 | return -EINVAL; | 1009 | return -EINVAL; |
628 | } | 1010 | } |
1011 | |||
1012 | void qlcnic_83xx_get_minidump_template(struct qlcnic_adapter *adapter) | ||
1013 | { | ||
1014 | u32 prev_version, current_version; | ||
1015 | struct qlcnic_hardware_context *ahw = adapter->ahw; | ||
1016 | struct qlcnic_fw_dump *fw_dump = &ahw->fw_dump; | ||
1017 | struct pci_dev *pdev = adapter->pdev; | ||
1018 | |||
1019 | prev_version = adapter->fw_version; | ||
1020 | current_version = qlcnic_83xx_get_fw_version(adapter); | ||
1021 | |||
1022 | if (fw_dump->tmpl_hdr == NULL || current_version > prev_version) { | ||
1023 | if (fw_dump->tmpl_hdr) | ||
1024 | vfree(fw_dump->tmpl_hdr); | ||
1025 | if (!qlcnic_fw_cmd_get_minidump_temp(adapter)) | ||
1026 | dev_info(&pdev->dev, "Supports FW dump capability\n"); | ||
1027 | } | ||
1028 | } | ||
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c index 341d37c867ff..987fb6f8adc3 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c | |||
@@ -1,8 +1,16 @@ | |||
1 | /* | ||
2 | * QLogic qlcnic NIC Driver | ||
3 | * Copyright (c) 2009-2013 QLogic Corporation | ||
4 | * | ||
5 | * See LICENSE.qlcnic for copyright and licensing details. | ||
6 | */ | ||
7 | |||
1 | #include <linux/slab.h> | 8 | #include <linux/slab.h> |
2 | #include <linux/vmalloc.h> | 9 | #include <linux/vmalloc.h> |
3 | #include <linux/interrupt.h> | 10 | #include <linux/interrupt.h> |
4 | 11 | ||
5 | #include "qlcnic.h" | 12 | #include "qlcnic.h" |
13 | #include "qlcnic_hw.h" | ||
6 | 14 | ||
7 | #include <linux/swab.h> | 15 | #include <linux/swab.h> |
8 | #include <linux/dma-mapping.h> | 16 | #include <linux/dma-mapping.h> |
@@ -13,6 +21,10 @@ | |||
13 | #include <linux/aer.h> | 21 | #include <linux/aer.h> |
14 | #include <linux/log2.h> | 22 | #include <linux/log2.h> |
15 | 23 | ||
24 | #include <linux/sysfs.h> | ||
25 | |||
26 | #define QLC_STATUS_UNSUPPORTED_CMD -2 | ||
27 | |||
16 | int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable) | 28 | int qlcnicvf_config_bridged_mode(struct qlcnic_adapter *adapter, u32 enable) |
17 | { | 29 | { |
18 | return -EOPNOTSUPP; | 30 | return -EOPNOTSUPP; |
@@ -40,7 +52,7 @@ static ssize_t qlcnic_store_bridged_mode(struct device *dev, | |||
40 | if (strict_strtoul(buf, 2, &new)) | 52 | if (strict_strtoul(buf, 2, &new)) |
41 | goto err_out; | 53 | goto err_out; |
42 | 54 | ||
43 | if (!adapter->nic_ops->config_bridged_mode(adapter, !!new)) | 55 | if (!qlcnic_config_bridged_mode(adapter, !!new)) |
44 | ret = len; | 56 | ret = len; |
45 | 57 | ||
46 | err_out: | 58 | err_out: |
@@ -80,9 +92,7 @@ static ssize_t qlcnic_show_diag_mode(struct device *dev, | |||
80 | struct device_attribute *attr, char *buf) | 92 | struct device_attribute *attr, char *buf) |
81 | { | 93 | { |
82 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | 94 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); |
83 | 95 | return sprintf(buf, "%d\n", !!(adapter->flags & QLCNIC_DIAG_ENABLED)); | |
84 | return sprintf(buf, "%d\n", | ||
85 | !!(adapter->flags & QLCNIC_DIAG_ENABLED)); | ||
86 | } | 96 | } |
87 | 97 | ||
88 | static int qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon, | 98 | static int qlcnic_validate_beacon(struct qlcnic_adapter *adapter, u16 beacon, |
@@ -111,10 +121,11 @@ static ssize_t qlcnic_store_beacon(struct device *dev, | |||
111 | const char *buf, size_t len) | 121 | const char *buf, size_t len) |
112 | { | 122 | { |
113 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | 123 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); |
114 | int max_sds_rings = adapter->max_sds_rings; | 124 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
125 | int err, max_sds_rings = adapter->max_sds_rings; | ||
115 | u16 beacon; | 126 | u16 beacon; |
116 | u8 b_state, b_rate; | 127 | u8 b_state, b_rate; |
117 | int err; | 128 | unsigned long h_beacon; |
118 | 129 | ||
119 | if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { | 130 | if (adapter->ahw->op_mode == QLCNIC_NON_PRIV_FUNC) { |
120 | dev_warn(dev, | 131 | dev_warn(dev, |
@@ -122,6 +133,41 @@ static ssize_t qlcnic_store_beacon(struct device *dev, | |||
122 | return -EOPNOTSUPP; | 133 | return -EOPNOTSUPP; |
123 | } | 134 | } |
124 | 135 | ||
136 | if (qlcnic_83xx_check(adapter) && | ||
137 | !test_bit(__QLCNIC_RESETTING, &adapter->state)) { | ||
138 | if (kstrtoul(buf, 2, &h_beacon)) | ||
139 | return -EINVAL; | ||
140 | |||
141 | if (ahw->beacon_state == h_beacon) | ||
142 | return len; | ||
143 | |||
144 | rtnl_lock(); | ||
145 | if (!ahw->beacon_state) { | ||
146 | if (test_and_set_bit(__QLCNIC_LED_ENABLE, | ||
147 | &adapter->state)) { | ||
148 | rtnl_unlock(); | ||
149 | return -EBUSY; | ||
150 | } | ||
151 | } | ||
152 | if (h_beacon) { | ||
153 | err = qlcnic_83xx_config_led(adapter, 1, h_beacon); | ||
154 | if (err) | ||
155 | goto beacon_err; | ||
156 | } else { | ||
157 | err = qlcnic_83xx_config_led(adapter, 0, !h_beacon); | ||
158 | if (err) | ||
159 | goto beacon_err; | ||
160 | } | ||
161 | /* set the current beacon state */ | ||
162 | ahw->beacon_state = h_beacon; | ||
163 | beacon_err: | ||
164 | if (!ahw->beacon_state) | ||
165 | clear_bit(__QLCNIC_LED_ENABLE, &adapter->state); | ||
166 | |||
167 | rtnl_unlock(); | ||
168 | return len; | ||
169 | } | ||
170 | |||
125 | if (len != sizeof(u16)) | 171 | if (len != sizeof(u16)) |
126 | return QL_STATUS_INVALID_PARAM; | 172 | return QL_STATUS_INVALID_PARAM; |
127 | 173 | ||
@@ -154,11 +200,10 @@ static ssize_t qlcnic_store_beacon(struct device *dev, | |||
154 | } | 200 | } |
155 | 201 | ||
156 | err = qlcnic_config_led(adapter, b_state, b_rate); | 202 | err = qlcnic_config_led(adapter, b_state, b_rate); |
157 | 203 | if (!err) | |
158 | if (!err) { | ||
159 | err = len; | 204 | err = len; |
160 | adapter->ahw->beacon_state = b_state; | 205 | else |
161 | } | 206 | ahw->beacon_state = b_state; |
162 | 207 | ||
163 | if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) | 208 | if (test_and_clear_bit(__QLCNIC_DIAG_RES_ALLOC, &adapter->state)) |
164 | qlcnic_diag_free_res(adapter->netdev, max_sds_rings); | 209 | qlcnic_diag_free_res(adapter->netdev, max_sds_rings); |
@@ -207,21 +252,13 @@ static ssize_t qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj, | |||
207 | { | 252 | { |
208 | struct device *dev = container_of(kobj, struct device, kobj); | 253 | struct device *dev = container_of(kobj, struct device, kobj); |
209 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | 254 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); |
210 | u32 data; | ||
211 | u64 qmdata; | ||
212 | int ret; | 255 | int ret; |
213 | 256 | ||
214 | ret = qlcnic_sysfs_validate_crb(adapter, offset, size); | 257 | ret = qlcnic_sysfs_validate_crb(adapter, offset, size); |
215 | if (ret != 0) | 258 | if (ret != 0) |
216 | return ret; | 259 | return ret; |
260 | qlcnic_read_crb(adapter, buf, offset, size); | ||
217 | 261 | ||
218 | if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) { | ||
219 | qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata); | ||
220 | memcpy(buf, &qmdata, size); | ||
221 | } else { | ||
222 | data = QLCRD32(adapter, offset); | ||
223 | memcpy(buf, &data, size); | ||
224 | } | ||
225 | return size; | 262 | return size; |
226 | } | 263 | } |
227 | 264 | ||
@@ -231,21 +268,13 @@ static ssize_t qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj, | |||
231 | { | 268 | { |
232 | struct device *dev = container_of(kobj, struct device, kobj); | 269 | struct device *dev = container_of(kobj, struct device, kobj); |
233 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | 270 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); |
234 | u32 data; | ||
235 | u64 qmdata; | ||
236 | int ret; | 271 | int ret; |
237 | 272 | ||
238 | ret = qlcnic_sysfs_validate_crb(adapter, offset, size); | 273 | ret = qlcnic_sysfs_validate_crb(adapter, offset, size); |
239 | if (ret != 0) | 274 | if (ret != 0) |
240 | return ret; | 275 | return ret; |
241 | 276 | ||
242 | if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) { | 277 | qlcnic_write_crb(adapter, buf, offset, size); |
243 | memcpy(&qmdata, buf, size); | ||
244 | qlcnic_pci_camqm_write_2M(adapter, offset, qmdata); | ||
245 | } else { | ||
246 | memcpy(&data, buf, size); | ||
247 | QLCWR32(adapter, offset, data); | ||
248 | } | ||
249 | return size; | 278 | return size; |
250 | } | 279 | } |
251 | 280 | ||
@@ -303,33 +332,44 @@ static ssize_t qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj, | |||
303 | return size; | 332 | return size; |
304 | } | 333 | } |
305 | 334 | ||
335 | static int qlcnic_is_valid_nic_func(struct qlcnic_adapter *adapter, u8 pci_func) | ||
336 | { | ||
337 | int i; | ||
338 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { | ||
339 | if (adapter->npars[i].pci_func == pci_func) | ||
340 | return i; | ||
341 | } | ||
342 | |||
343 | return -1; | ||
344 | } | ||
345 | |||
306 | static int validate_pm_config(struct qlcnic_adapter *adapter, | 346 | static int validate_pm_config(struct qlcnic_adapter *adapter, |
307 | struct qlcnic_pm_func_cfg *pm_cfg, int count) | 347 | struct qlcnic_pm_func_cfg *pm_cfg, int count) |
308 | { | 348 | { |
309 | u8 src_pci_func, s_esw_id, d_esw_id, dest_pci_func; | 349 | u8 src_pci_func, s_esw_id, d_esw_id; |
310 | int i; | 350 | u8 dest_pci_func; |
351 | int i, src_index, dest_index; | ||
311 | 352 | ||
312 | for (i = 0; i < count; i++) { | 353 | for (i = 0; i < count; i++) { |
313 | src_pci_func = pm_cfg[i].pci_func; | 354 | src_pci_func = pm_cfg[i].pci_func; |
314 | dest_pci_func = pm_cfg[i].dest_npar; | 355 | dest_pci_func = pm_cfg[i].dest_npar; |
315 | if (src_pci_func >= QLCNIC_MAX_PCI_FUNC || | 356 | src_index = qlcnic_is_valid_nic_func(adapter, src_pci_func); |
316 | dest_pci_func >= QLCNIC_MAX_PCI_FUNC) | ||
317 | return QL_STATUS_INVALID_PARAM; | ||
318 | 357 | ||
319 | if (adapter->npars[src_pci_func].type != QLCNIC_TYPE_NIC) | 358 | if (src_index < 0) |
320 | return QL_STATUS_INVALID_PARAM; | 359 | return QL_STATUS_INVALID_PARAM; |
321 | 360 | ||
322 | if (adapter->npars[dest_pci_func].type != QLCNIC_TYPE_NIC) | 361 | dest_index = qlcnic_is_valid_nic_func(adapter, dest_pci_func); |
362 | if (dest_index < 0) | ||
323 | return QL_STATUS_INVALID_PARAM; | 363 | return QL_STATUS_INVALID_PARAM; |
324 | 364 | ||
325 | s_esw_id = adapter->npars[src_pci_func].phy_port; | 365 | s_esw_id = adapter->npars[src_index].phy_port; |
326 | d_esw_id = adapter->npars[dest_pci_func].phy_port; | 366 | d_esw_id = adapter->npars[dest_index].phy_port; |
327 | 367 | ||
328 | if (s_esw_id != d_esw_id) | 368 | if (s_esw_id != d_esw_id) |
329 | return QL_STATUS_INVALID_PARAM; | 369 | return QL_STATUS_INVALID_PARAM; |
330 | } | 370 | } |
331 | return 0; | ||
332 | 371 | ||
372 | return 0; | ||
333 | } | 373 | } |
334 | 374 | ||
335 | static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp, | 375 | static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp, |
@@ -342,7 +382,7 @@ static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp, | |||
342 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | 382 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); |
343 | struct qlcnic_pm_func_cfg *pm_cfg; | 383 | struct qlcnic_pm_func_cfg *pm_cfg; |
344 | u32 id, action, pci_func; | 384 | u32 id, action, pci_func; |
345 | int count, rem, i, ret; | 385 | int count, rem, i, ret, index; |
346 | 386 | ||
347 | count = size / sizeof(struct qlcnic_pm_func_cfg); | 387 | count = size / sizeof(struct qlcnic_pm_func_cfg); |
348 | rem = size % sizeof(struct qlcnic_pm_func_cfg); | 388 | rem = size % sizeof(struct qlcnic_pm_func_cfg); |
@@ -350,26 +390,32 @@ static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp, | |||
350 | return QL_STATUS_INVALID_PARAM; | 390 | return QL_STATUS_INVALID_PARAM; |
351 | 391 | ||
352 | pm_cfg = (struct qlcnic_pm_func_cfg *)buf; | 392 | pm_cfg = (struct qlcnic_pm_func_cfg *)buf; |
353 | |||
354 | ret = validate_pm_config(adapter, pm_cfg, count); | 393 | ret = validate_pm_config(adapter, pm_cfg, count); |
394 | |||
355 | if (ret) | 395 | if (ret) |
356 | return ret; | 396 | return ret; |
357 | for (i = 0; i < count; i++) { | 397 | for (i = 0; i < count; i++) { |
358 | pci_func = pm_cfg[i].pci_func; | 398 | pci_func = pm_cfg[i].pci_func; |
359 | action = !!pm_cfg[i].action; | 399 | action = !!pm_cfg[i].action; |
360 | id = adapter->npars[pci_func].phy_port; | 400 | index = qlcnic_is_valid_nic_func(adapter, pci_func); |
361 | ret = qlcnic_config_port_mirroring(adapter, id, action, | 401 | if (index < 0) |
362 | pci_func); | 402 | return QL_STATUS_INVALID_PARAM; |
403 | |||
404 | id = adapter->npars[index].phy_port; | ||
405 | ret = qlcnic_config_port_mirroring(adapter, id, | ||
406 | action, pci_func); | ||
363 | if (ret) | 407 | if (ret) |
364 | return ret; | 408 | return ret; |
365 | } | 409 | } |
366 | 410 | ||
367 | for (i = 0; i < count; i++) { | 411 | for (i = 0; i < count; i++) { |
368 | pci_func = pm_cfg[i].pci_func; | 412 | pci_func = pm_cfg[i].pci_func; |
369 | id = adapter->npars[pci_func].phy_port; | 413 | index = qlcnic_is_valid_nic_func(adapter, pci_func); |
370 | adapter->npars[pci_func].enable_pm = !!pm_cfg[i].action; | 414 | id = adapter->npars[index].phy_port; |
371 | adapter->npars[pci_func].dest_npar = id; | 415 | adapter->npars[index].enable_pm = !!pm_cfg[i].action; |
416 | adapter->npars[index].dest_npar = id; | ||
372 | } | 417 | } |
418 | |||
373 | return size; | 419 | return size; |
374 | } | 420 | } |
375 | 421 | ||
@@ -383,16 +429,19 @@ static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp, | |||
383 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | 429 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); |
384 | struct qlcnic_pm_func_cfg pm_cfg[QLCNIC_MAX_PCI_FUNC]; | 430 | struct qlcnic_pm_func_cfg pm_cfg[QLCNIC_MAX_PCI_FUNC]; |
385 | int i; | 431 | int i; |
432 | u8 pci_func; | ||
386 | 433 | ||
387 | if (size != sizeof(pm_cfg)) | 434 | if (size != sizeof(pm_cfg)) |
388 | return QL_STATUS_INVALID_PARAM; | 435 | return QL_STATUS_INVALID_PARAM; |
389 | 436 | ||
390 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { | 437 | memset(&pm_cfg, 0, |
391 | if (adapter->npars[i].type != QLCNIC_TYPE_NIC) | 438 | sizeof(struct qlcnic_pm_func_cfg) * QLCNIC_MAX_PCI_FUNC); |
392 | continue; | 439 | |
393 | pm_cfg[i].action = adapter->npars[i].enable_pm; | 440 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { |
394 | pm_cfg[i].dest_npar = 0; | 441 | pci_func = adapter->npars[i].pci_func; |
395 | pm_cfg[i].pci_func = i; | 442 | pm_cfg[pci_func].action = adapter->npars[i].enable_pm; |
443 | pm_cfg[pci_func].dest_npar = 0; | ||
444 | pm_cfg[pci_func].pci_func = i; | ||
396 | } | 445 | } |
397 | memcpy(buf, &pm_cfg, size); | 446 | memcpy(buf, &pm_cfg, size); |
398 | 447 | ||
@@ -404,24 +453,33 @@ static int validate_esw_config(struct qlcnic_adapter *adapter, | |||
404 | { | 453 | { |
405 | u32 op_mode; | 454 | u32 op_mode; |
406 | u8 pci_func; | 455 | u8 pci_func; |
407 | int i; | 456 | int i, ret; |
408 | 457 | ||
409 | op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE); | 458 | if (qlcnic_82xx_check(adapter)) |
459 | op_mode = readl(adapter->ahw->pci_base0 + QLCNIC_DRV_OP_MODE); | ||
460 | else | ||
461 | op_mode = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE); | ||
410 | 462 | ||
411 | for (i = 0; i < count; i++) { | 463 | for (i = 0; i < count; i++) { |
412 | pci_func = esw_cfg[i].pci_func; | 464 | pci_func = esw_cfg[i].pci_func; |
413 | if (pci_func >= QLCNIC_MAX_PCI_FUNC) | 465 | if (pci_func >= QLCNIC_MAX_PCI_FUNC) |
414 | return QL_STATUS_INVALID_PARAM; | 466 | return QL_STATUS_INVALID_PARAM; |
415 | 467 | ||
416 | if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) { | 468 | if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) |
417 | if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC) | 469 | if (qlcnic_is_valid_nic_func(adapter, pci_func) < 0) |
418 | return QL_STATUS_INVALID_PARAM; | 470 | return QL_STATUS_INVALID_PARAM; |
419 | } | ||
420 | 471 | ||
421 | switch (esw_cfg[i].op_mode) { | 472 | switch (esw_cfg[i].op_mode) { |
422 | case QLCNIC_PORT_DEFAULTS: | 473 | case QLCNIC_PORT_DEFAULTS: |
423 | if (QLC_DEV_GET_DRV(op_mode, pci_func) != | 474 | if (qlcnic_82xx_check(adapter)) { |
424 | QLCNIC_NON_PRIV_FUNC) { | 475 | ret = QLC_DEV_GET_DRV(op_mode, pci_func); |
476 | } else { | ||
477 | ret = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode, | ||
478 | pci_func); | ||
479 | esw_cfg[i].offload_flags = 0; | ||
480 | } | ||
481 | |||
482 | if (ret != QLCNIC_NON_PRIV_FUNC) { | ||
425 | if (esw_cfg[i].mac_anti_spoof != 0) | 483 | if (esw_cfg[i].mac_anti_spoof != 0) |
426 | return QL_STATUS_INVALID_PARAM; | 484 | return QL_STATUS_INVALID_PARAM; |
427 | if (esw_cfg[i].mac_override != 1) | 485 | if (esw_cfg[i].mac_override != 1) |
@@ -444,6 +502,7 @@ static int validate_esw_config(struct qlcnic_adapter *adapter, | |||
444 | return QL_STATUS_INVALID_PARAM; | 502 | return QL_STATUS_INVALID_PARAM; |
445 | } | 503 | } |
446 | } | 504 | } |
505 | |||
447 | return 0; | 506 | return 0; |
448 | } | 507 | } |
449 | 508 | ||
@@ -458,7 +517,8 @@ static ssize_t qlcnic_sysfs_write_esw_config(struct file *file, | |||
458 | struct qlcnic_esw_func_cfg *esw_cfg; | 517 | struct qlcnic_esw_func_cfg *esw_cfg; |
459 | struct qlcnic_npar_info *npar; | 518 | struct qlcnic_npar_info *npar; |
460 | int count, rem, i, ret; | 519 | int count, rem, i, ret; |
461 | u8 pci_func, op_mode = 0; | 520 | int index; |
521 | u8 op_mode = 0, pci_func; | ||
462 | 522 | ||
463 | count = size / sizeof(struct qlcnic_esw_func_cfg); | 523 | count = size / sizeof(struct qlcnic_esw_func_cfg); |
464 | rem = size % sizeof(struct qlcnic_esw_func_cfg); | 524 | rem = size % sizeof(struct qlcnic_esw_func_cfg); |
@@ -471,10 +531,9 @@ static ssize_t qlcnic_sysfs_write_esw_config(struct file *file, | |||
471 | return ret; | 531 | return ret; |
472 | 532 | ||
473 | for (i = 0; i < count; i++) { | 533 | for (i = 0; i < count; i++) { |
474 | if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) { | 534 | if (adapter->ahw->op_mode == QLCNIC_MGMT_FUNC) |
475 | if (qlcnic_config_switch_port(adapter, &esw_cfg[i])) | 535 | if (qlcnic_config_switch_port(adapter, &esw_cfg[i])) |
476 | return QL_STATUS_INVALID_PARAM; | 536 | return QL_STATUS_INVALID_PARAM; |
477 | } | ||
478 | 537 | ||
479 | if (adapter->ahw->pci_func != esw_cfg[i].pci_func) | 538 | if (adapter->ahw->pci_func != esw_cfg[i].pci_func) |
480 | continue; | 539 | continue; |
@@ -503,7 +562,8 @@ static ssize_t qlcnic_sysfs_write_esw_config(struct file *file, | |||
503 | 562 | ||
504 | for (i = 0; i < count; i++) { | 563 | for (i = 0; i < count; i++) { |
505 | pci_func = esw_cfg[i].pci_func; | 564 | pci_func = esw_cfg[i].pci_func; |
506 | npar = &adapter->npars[pci_func]; | 565 | index = qlcnic_is_valid_nic_func(adapter, pci_func); |
566 | npar = &adapter->npars[index]; | ||
507 | switch (esw_cfg[i].op_mode) { | 567 | switch (esw_cfg[i].op_mode) { |
508 | case QLCNIC_PORT_DEFAULTS: | 568 | case QLCNIC_PORT_DEFAULTS: |
509 | npar->promisc_mode = esw_cfg[i].promisc_mode; | 569 | npar->promisc_mode = esw_cfg[i].promisc_mode; |
@@ -533,18 +593,21 @@ static ssize_t qlcnic_sysfs_read_esw_config(struct file *file, | |||
533 | struct device *dev = container_of(kobj, struct device, kobj); | 593 | struct device *dev = container_of(kobj, struct device, kobj); |
534 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | 594 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); |
535 | struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC]; | 595 | struct qlcnic_esw_func_cfg esw_cfg[QLCNIC_MAX_PCI_FUNC]; |
536 | u8 i; | 596 | u8 i, pci_func; |
537 | 597 | ||
538 | if (size != sizeof(esw_cfg)) | 598 | if (size != sizeof(esw_cfg)) |
539 | return QL_STATUS_INVALID_PARAM; | 599 | return QL_STATUS_INVALID_PARAM; |
540 | 600 | ||
541 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { | 601 | memset(&esw_cfg, 0, |
542 | if (adapter->npars[i].type != QLCNIC_TYPE_NIC) | 602 | sizeof(struct qlcnic_esw_func_cfg) * QLCNIC_MAX_PCI_FUNC); |
543 | continue; | 603 | |
544 | esw_cfg[i].pci_func = i; | 604 | for (i = 0; i < adapter->ahw->act_pci_func; i++) { |
545 | if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[i])) | 605 | pci_func = adapter->npars[i].pci_func; |
606 | esw_cfg[pci_func].pci_func = pci_func; | ||
607 | if (qlcnic_get_eswitch_port_config(adapter, &esw_cfg[pci_func])) | ||
546 | return QL_STATUS_INVALID_PARAM; | 608 | return QL_STATUS_INVALID_PARAM; |
547 | } | 609 | } |
610 | |||
548 | memcpy(buf, &esw_cfg, size); | 611 | memcpy(buf, &esw_cfg, size); |
549 | 612 | ||
550 | return size; | 613 | return size; |
@@ -558,10 +621,7 @@ static int validate_npar_config(struct qlcnic_adapter *adapter, | |||
558 | 621 | ||
559 | for (i = 0; i < count; i++) { | 622 | for (i = 0; i < count; i++) { |
560 | pci_func = np_cfg[i].pci_func; | 623 | pci_func = np_cfg[i].pci_func; |
561 | if (pci_func >= QLCNIC_MAX_PCI_FUNC) | 624 | if (qlcnic_is_valid_nic_func(adapter, pci_func) < 0) |
562 | return QL_STATUS_INVALID_PARAM; | ||
563 | |||
564 | if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC) | ||
565 | return QL_STATUS_INVALID_PARAM; | 625 | return QL_STATUS_INVALID_PARAM; |
566 | 626 | ||
567 | if (!IS_VALID_BW(np_cfg[i].min_bw) || | 627 | if (!IS_VALID_BW(np_cfg[i].min_bw) || |
@@ -581,7 +641,7 @@ static ssize_t qlcnic_sysfs_write_npar_config(struct file *file, | |||
581 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | 641 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); |
582 | struct qlcnic_info nic_info; | 642 | struct qlcnic_info nic_info; |
583 | struct qlcnic_npar_func_cfg *np_cfg; | 643 | struct qlcnic_npar_func_cfg *np_cfg; |
584 | int i, count, rem, ret; | 644 | int i, count, rem, ret, index; |
585 | u8 pci_func; | 645 | u8 pci_func; |
586 | 646 | ||
587 | count = size / sizeof(struct qlcnic_npar_func_cfg); | 647 | count = size / sizeof(struct qlcnic_npar_func_cfg); |
@@ -594,8 +654,10 @@ static ssize_t qlcnic_sysfs_write_npar_config(struct file *file, | |||
594 | if (ret) | 654 | if (ret) |
595 | return ret; | 655 | return ret; |
596 | 656 | ||
597 | for (i = 0; i < count ; i++) { | 657 | for (i = 0; i < count; i++) { |
598 | pci_func = np_cfg[i].pci_func; | 658 | pci_func = np_cfg[i].pci_func; |
659 | |||
660 | memset(&nic_info, 0, sizeof(struct qlcnic_info)); | ||
599 | ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func); | 661 | ret = qlcnic_get_nic_info(adapter, &nic_info, pci_func); |
600 | if (ret) | 662 | if (ret) |
601 | return ret; | 663 | return ret; |
@@ -605,12 +667,12 @@ static ssize_t qlcnic_sysfs_write_npar_config(struct file *file, | |||
605 | ret = qlcnic_set_nic_info(adapter, &nic_info); | 667 | ret = qlcnic_set_nic_info(adapter, &nic_info); |
606 | if (ret) | 668 | if (ret) |
607 | return ret; | 669 | return ret; |
608 | adapter->npars[i].min_bw = nic_info.min_tx_bw; | 670 | index = qlcnic_is_valid_nic_func(adapter, pci_func); |
609 | adapter->npars[i].max_bw = nic_info.max_tx_bw; | 671 | adapter->npars[index].min_bw = nic_info.min_tx_bw; |
672 | adapter->npars[index].max_bw = nic_info.max_tx_bw; | ||
610 | } | 673 | } |
611 | 674 | ||
612 | return size; | 675 | return size; |
613 | |||
614 | } | 676 | } |
615 | 677 | ||
616 | static ssize_t qlcnic_sysfs_read_npar_config(struct file *file, | 678 | static ssize_t qlcnic_sysfs_read_npar_config(struct file *file, |
@@ -628,8 +690,12 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file, | |||
628 | if (size != sizeof(np_cfg)) | 690 | if (size != sizeof(np_cfg)) |
629 | return QL_STATUS_INVALID_PARAM; | 691 | return QL_STATUS_INVALID_PARAM; |
630 | 692 | ||
693 | memset(&nic_info, 0, sizeof(struct qlcnic_info)); | ||
694 | memset(&np_cfg, 0, | ||
695 | sizeof(struct qlcnic_npar_func_cfg) * QLCNIC_MAX_PCI_FUNC); | ||
696 | |||
631 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { | 697 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { |
632 | if (adapter->npars[i].type != QLCNIC_TYPE_NIC) | 698 | if (qlcnic_is_valid_nic_func(adapter, i) < 0) |
633 | continue; | 699 | continue; |
634 | ret = qlcnic_get_nic_info(adapter, &nic_info, i); | 700 | ret = qlcnic_get_nic_info(adapter, &nic_info, i); |
635 | if (ret) | 701 | if (ret) |
@@ -644,6 +710,7 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file, | |||
644 | np_cfg[i].max_tx_queues = nic_info.max_tx_ques; | 710 | np_cfg[i].max_tx_queues = nic_info.max_tx_ques; |
645 | np_cfg[i].max_rx_queues = nic_info.max_rx_ques; | 711 | np_cfg[i].max_rx_queues = nic_info.max_rx_ques; |
646 | } | 712 | } |
713 | |||
647 | memcpy(buf, &np_cfg, size); | 714 | memcpy(buf, &np_cfg, size); |
648 | return size; | 715 | return size; |
649 | } | 716 | } |
@@ -659,6 +726,9 @@ static ssize_t qlcnic_sysfs_get_port_stats(struct file *file, | |||
659 | struct qlcnic_esw_statistics port_stats; | 726 | struct qlcnic_esw_statistics port_stats; |
660 | int ret; | 727 | int ret; |
661 | 728 | ||
729 | if (qlcnic_83xx_check(adapter)) | ||
730 | return QLC_STATUS_UNSUPPORTED_CMD; | ||
731 | |||
662 | if (size != sizeof(struct qlcnic_esw_statistics)) | 732 | if (size != sizeof(struct qlcnic_esw_statistics)) |
663 | return QL_STATUS_INVALID_PARAM; | 733 | return QL_STATUS_INVALID_PARAM; |
664 | 734 | ||
@@ -691,6 +761,9 @@ static ssize_t qlcnic_sysfs_get_esw_stats(struct file *file, | |||
691 | struct qlcnic_esw_statistics esw_stats; | 761 | struct qlcnic_esw_statistics esw_stats; |
692 | int ret; | 762 | int ret; |
693 | 763 | ||
764 | if (qlcnic_83xx_check(adapter)) | ||
765 | return QLC_STATUS_UNSUPPORTED_CMD; | ||
766 | |||
694 | if (size != sizeof(struct qlcnic_esw_statistics)) | 767 | if (size != sizeof(struct qlcnic_esw_statistics)) |
695 | return QL_STATUS_INVALID_PARAM; | 768 | return QL_STATUS_INVALID_PARAM; |
696 | 769 | ||
@@ -722,6 +795,9 @@ static ssize_t qlcnic_sysfs_clear_esw_stats(struct file *file, | |||
722 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | 795 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); |
723 | int ret; | 796 | int ret; |
724 | 797 | ||
798 | if (qlcnic_83xx_check(adapter)) | ||
799 | return QLC_STATUS_UNSUPPORTED_CMD; | ||
800 | |||
725 | if (offset >= QLCNIC_NIU_MAX_XG_PORTS) | 801 | if (offset >= QLCNIC_NIU_MAX_XG_PORTS) |
726 | return QL_STATUS_INVALID_PARAM; | 802 | return QL_STATUS_INVALID_PARAM; |
727 | 803 | ||
@@ -744,10 +820,14 @@ static ssize_t qlcnic_sysfs_clear_port_stats(struct file *file, | |||
744 | char *buf, loff_t offset, | 820 | char *buf, loff_t offset, |
745 | size_t size) | 821 | size_t size) |
746 | { | 822 | { |
823 | |||
747 | struct device *dev = container_of(kobj, struct device, kobj); | 824 | struct device *dev = container_of(kobj, struct device, kobj); |
748 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | 825 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); |
749 | int ret; | 826 | int ret; |
750 | 827 | ||
828 | if (qlcnic_83xx_check(adapter)) | ||
829 | return QLC_STATUS_UNSUPPORTED_CMD; | ||
830 | |||
751 | if (offset >= QLCNIC_MAX_PCI_FUNC) | 831 | if (offset >= QLCNIC_MAX_PCI_FUNC) |
752 | return QL_STATUS_INVALID_PARAM; | 832 | return QL_STATUS_INVALID_PARAM; |
753 | 833 | ||
@@ -789,7 +869,10 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file, | |||
789 | return ret; | 869 | return ret; |
790 | } | 870 | } |
791 | 871 | ||
792 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC ; i++) { | 872 | memset(&pci_cfg, 0, |
873 | sizeof(struct qlcnic_pci_func_cfg) * QLCNIC_MAX_PCI_FUNC); | ||
874 | |||
875 | for (i = 0; i < QLCNIC_MAX_PCI_FUNC; i++) { | ||
793 | pci_cfg[i].pci_func = pci_info[i].id; | 876 | pci_cfg[i].pci_func = pci_info[i].id; |
794 | pci_cfg[i].func_type = pci_info[i].type; | 877 | pci_cfg[i].func_type = pci_info[i].type; |
795 | pci_cfg[i].port_num = pci_info[i].default_port; | 878 | pci_cfg[i].port_num = pci_info[i].default_port; |
@@ -797,6 +880,7 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file, | |||
797 | pci_cfg[i].max_bw = pci_info[i].tx_max_bw; | 880 | pci_cfg[i].max_bw = pci_info[i].tx_max_bw; |
798 | memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN); | 881 | memcpy(&pci_cfg[i].def_mac_addr, &pci_info[i].mac, ETH_ALEN); |
799 | } | 882 | } |
883 | |||
800 | memcpy(buf, &pci_cfg, size); | 884 | memcpy(buf, &pci_cfg, size); |
801 | kfree(pci_info); | 885 | kfree(pci_info); |
802 | return size; | 886 | return size; |
@@ -897,7 +981,6 @@ void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter) | |||
897 | void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter) | 981 | void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter) |
898 | { | 982 | { |
899 | struct device *dev = &adapter->pdev->dev; | 983 | struct device *dev = &adapter->pdev->dev; |
900 | u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); | ||
901 | 984 | ||
902 | if (device_create_bin_file(dev, &bin_attr_port_stats)) | 985 | if (device_create_bin_file(dev, &bin_attr_port_stats)) |
903 | dev_info(dev, "failed to create port stats sysfs entry"); | 986 | dev_info(dev, "failed to create port stats sysfs entry"); |
@@ -911,9 +994,6 @@ void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter) | |||
911 | if (device_create_bin_file(dev, &bin_attr_mem)) | 994 | if (device_create_bin_file(dev, &bin_attr_mem)) |
912 | dev_info(dev, "failed to create mem sysfs entry\n"); | 995 | dev_info(dev, "failed to create mem sysfs entry\n"); |
913 | 996 | ||
914 | if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) | ||
915 | return; | ||
916 | |||
917 | if (device_create_bin_file(dev, &bin_attr_pci_config)) | 997 | if (device_create_bin_file(dev, &bin_attr_pci_config)) |
918 | dev_info(dev, "failed to create pci config sysfs entry"); | 998 | dev_info(dev, "failed to create pci config sysfs entry"); |
919 | if (device_create_file(dev, &dev_attr_beacon)) | 999 | if (device_create_file(dev, &dev_attr_beacon)) |
@@ -936,7 +1016,6 @@ void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter) | |||
936 | void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter) | 1016 | void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter) |
937 | { | 1017 | { |
938 | struct device *dev = &adapter->pdev->dev; | 1018 | struct device *dev = &adapter->pdev->dev; |
939 | u32 state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); | ||
940 | 1019 | ||
941 | device_remove_bin_file(dev, &bin_attr_port_stats); | 1020 | device_remove_bin_file(dev, &bin_attr_port_stats); |
942 | 1021 | ||
@@ -945,8 +1024,6 @@ void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter) | |||
945 | device_remove_file(dev, &dev_attr_diag_mode); | 1024 | device_remove_file(dev, &dev_attr_diag_mode); |
946 | device_remove_bin_file(dev, &bin_attr_crb); | 1025 | device_remove_bin_file(dev, &bin_attr_crb); |
947 | device_remove_bin_file(dev, &bin_attr_mem); | 1026 | device_remove_bin_file(dev, &bin_attr_mem); |
948 | if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD)) | ||
949 | return; | ||
950 | device_remove_bin_file(dev, &bin_attr_pci_config); | 1027 | device_remove_bin_file(dev, &bin_attr_pci_config); |
951 | device_remove_file(dev, &dev_attr_beacon); | 1028 | device_remove_file(dev, &dev_attr_beacon); |
952 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) | 1029 | if (!(adapter->flags & QLCNIC_ESWITCH_ENABLED)) |
@@ -958,3 +1035,23 @@ void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter) | |||
958 | device_remove_bin_file(dev, &bin_attr_pm_config); | 1035 | device_remove_bin_file(dev, &bin_attr_pm_config); |
959 | device_remove_bin_file(dev, &bin_attr_esw_stats); | 1036 | device_remove_bin_file(dev, &bin_attr_esw_stats); |
960 | } | 1037 | } |
1038 | |||
1039 | void qlcnic_82xx_add_sysfs(struct qlcnic_adapter *adapter) | ||
1040 | { | ||
1041 | qlcnic_create_diag_entries(adapter); | ||
1042 | } | ||
1043 | |||
1044 | void qlcnic_82xx_remove_sysfs(struct qlcnic_adapter *adapter) | ||
1045 | { | ||
1046 | qlcnic_remove_diag_entries(adapter); | ||
1047 | } | ||
1048 | |||
1049 | void qlcnic_83xx_add_sysfs(struct qlcnic_adapter *adapter) | ||
1050 | { | ||
1051 | qlcnic_create_diag_entries(adapter); | ||
1052 | } | ||
1053 | |||
1054 | void qlcnic_83xx_remove_sysfs(struct qlcnic_adapter *adapter) | ||
1055 | { | ||
1056 | qlcnic_remove_diag_entries(adapter); | ||
1057 | } | ||
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index 3e73742024b0..b13ab544a7eb 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c | |||
@@ -2920,14 +2920,11 @@ static int ql_alloc_rx_resources(struct ql_adapter *qdev, | |||
2920 | /* | 2920 | /* |
2921 | * Allocate small buffer queue control blocks. | 2921 | * Allocate small buffer queue control blocks. |
2922 | */ | 2922 | */ |
2923 | rx_ring->sbq = | 2923 | rx_ring->sbq = kmalloc_array(rx_ring->sbq_len, |
2924 | kmalloc(rx_ring->sbq_len * sizeof(struct bq_desc), | 2924 | sizeof(struct bq_desc), |
2925 | GFP_KERNEL); | 2925 | GFP_KERNEL); |
2926 | if (rx_ring->sbq == NULL) { | 2926 | if (rx_ring->sbq == NULL) |
2927 | netif_err(qdev, ifup, qdev->ndev, | ||
2928 | "Small buffer queue control block allocation failed.\n"); | ||
2929 | goto err_mem; | 2927 | goto err_mem; |
2930 | } | ||
2931 | 2928 | ||
2932 | ql_init_sbq_ring(qdev, rx_ring); | 2929 | ql_init_sbq_ring(qdev, rx_ring); |
2933 | } | 2930 | } |
@@ -2948,14 +2945,11 @@ static int ql_alloc_rx_resources(struct ql_adapter *qdev, | |||
2948 | /* | 2945 | /* |
2949 | * Allocate large buffer queue control blocks. | 2946 | * Allocate large buffer queue control blocks. |
2950 | */ | 2947 | */ |
2951 | rx_ring->lbq = | 2948 | rx_ring->lbq = kmalloc_array(rx_ring->lbq_len, |
2952 | kmalloc(rx_ring->lbq_len * sizeof(struct bq_desc), | 2949 | sizeof(struct bq_desc), |
2953 | GFP_KERNEL); | 2950 | GFP_KERNEL); |
2954 | if (rx_ring->lbq == NULL) { | 2951 | if (rx_ring->lbq == NULL) |
2955 | netif_err(qdev, ifup, qdev->ndev, | ||
2956 | "Large buffer queue control block allocation failed.\n"); | ||
2957 | goto err_mem; | 2952 | goto err_mem; |
2958 | } | ||
2959 | 2953 | ||
2960 | ql_init_lbq_ring(qdev, rx_ring); | 2954 | ql_init_lbq_ring(qdev, rx_ring); |
2961 | } | 2955 | } |
@@ -4572,7 +4566,6 @@ static int ql_init_device(struct pci_dev *pdev, struct net_device *ndev, | |||
4572 | qdev->mpi_coredump = | 4566 | qdev->mpi_coredump = |
4573 | vmalloc(sizeof(struct ql_mpi_coredump)); | 4567 | vmalloc(sizeof(struct ql_mpi_coredump)); |
4574 | if (qdev->mpi_coredump == NULL) { | 4568 | if (qdev->mpi_coredump == NULL) { |
4575 | dev_err(&pdev->dev, "Coredump alloc failed.\n"); | ||
4576 | err = -ENOMEM; | 4569 | err = -ENOMEM; |
4577 | goto err_out2; | 4570 | goto err_out2; |
4578 | } | 4571 | } |
@@ -4586,7 +4579,6 @@ static int ql_init_device(struct pci_dev *pdev, struct net_device *ndev, | |||
4586 | goto err_out2; | 4579 | goto err_out2; |
4587 | } | 4580 | } |
4588 | 4581 | ||
4589 | memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len); | ||
4590 | /* Keep local copy of current mac address. */ | 4582 | /* Keep local copy of current mac address. */ |
4591 | memcpy(qdev->current_mac_addr, ndev->dev_addr, ndev->addr_len); | 4583 | memcpy(qdev->current_mac_addr, ndev->dev_addr, ndev->addr_len); |
4592 | 4584 | ||