diff options
author | Ingo Molnar <mingo@kernel.org> | 2012-04-14 13:18:27 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2012-04-14 13:19:04 +0200 |
commit | 6ac1ef482d7ae0c690f1640bf6eb818ff9a2d91e (patch) | |
tree | 021cc9f6b477146fcebe6f3be4752abfa2ba18a9 /drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | |
parent | 682968e0c425c60f0dde37977e5beb2b12ddc4cc (diff) | |
parent | a385ec4f11bdcf81af094c03e2444ee9b7fad2e5 (diff) |
Merge branch 'perf/core' into perf/uprobes
Merge in latest upstream (and the latest perf development tree),
to prepare for tooling changes, and also to pick up v3.4 MM
changes that the uprobes code needs to take care of.
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c')
-rw-r--r-- | drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | 138 |
1 files changed, 109 insertions, 29 deletions
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 7dd9a4b107e..65a718f9ccd 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -82,7 +82,6 @@ static void netxen_create_sysfs_entries(struct netxen_adapter *adapter); static void netxen_remove_sysfs_entries(struct netxen_adapter *adapter); static void netxen_create_diag_entries(struct netxen_adapter *adapter); static void netxen_remove_diag_entries(struct netxen_adapter *adapter); - static int nx_dev_request_aer(struct netxen_adapter *adapter); static int nx_decr_dev_ref_cnt(struct netxen_adapter *adapter); static int netxen_can_start_firmware(struct netxen_adapter *adapter); @@ -519,7 +518,7 @@ static int netxen_nic_set_mac(struct net_device *netdev, void *p) struct sockaddr *addr = p; if (!is_valid_ether_addr(addr->sa_data)) - return -EINVAL; + return -EADDRNOTAVAIL; if (netif_running(netdev)) { netif_device_detach(netdev); @@ -802,16 +801,16 @@ err_out: static void netxen_check_options(struct netxen_adapter *adapter) { - u32 fw_major, fw_minor, fw_build; + u32 fw_major, fw_minor, fw_build, prev_fw_version; char brd_name[NETXEN_MAX_SHORT_NAME]; char serial_num[32]; - int i, offset, val; - int *ptr32; + int i, offset, val, err; + __le32 *ptr32; struct pci_dev *pdev = adapter->pdev; adapter->driver_mismatch = 0; - ptr32 = (int *)&serial_num; + ptr32 = (__le32 *)&serial_num; offset = NX_FW_SERIAL_NUM_OFFSET; for (i = 0; i < 8; i++) { if (netxen_rom_fast_read(adapter, offset, &val) == -1) { @@ -826,9 +825,22 @@ netxen_check_options(struct netxen_adapter *adapter) fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR); fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR); fw_build = NXRD32(adapter, NETXEN_FW_VERSION_SUB); - + prev_fw_version = adapter->fw_version; adapter->fw_version = NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build); + /* Get FW Mini Coredump template and store it */ + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { + if (adapter->mdump.md_template == NULL || + adapter->fw_version > prev_fw_version) { + kfree(adapter->mdump.md_template); + adapter->mdump.md_template = NULL; + err = netxen_setup_minidump(adapter); + if (err) + dev_err(&adapter->pdev->dev, + "Failed to setup minidump rcode = %d\n", err); + } + } + if (adapter->portnum == 0) { get_brd_name_by_type(adapter->ahw.board_type, brd_name); @@ -909,7 +921,12 @@ netxen_start_firmware(struct netxen_adapter *adapter) if (err) return err; - if (!netxen_can_start_firmware(adapter)) + err = netxen_can_start_firmware(adapter); + + if (err < 0) + return err; + + if (!err) goto wait_init; first_boot = NXRD32(adapter, NETXEN_CAM_RAM(0x1fc)); @@ -1403,7 +1420,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev = alloc_etherdev(sizeof(struct netxen_adapter)); if(!netdev) { - dev_err(&pdev->dev, "failed to allocate net_device\n"); err = -ENOMEM; goto err_out_free_res; } @@ -1529,6 +1545,18 @@ err_out_disable_pdev: return err; } +static +void netxen_cleanup_minidump(struct netxen_adapter *adapter) +{ + kfree(adapter->mdump.md_template); + adapter->mdump.md_template = NULL; + + if (adapter->mdump.md_capture_buff) { + vfree(adapter->mdump.md_capture_buff); + adapter->mdump.md_capture_buff = NULL; + } +} + static void __devexit netxen_nic_remove(struct pci_dev *pdev) { struct netxen_adapter *adapter; @@ -1564,8 +1592,10 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) netxen_release_firmware(adapter); - if (NX_IS_REVISION_P3(pdev->revision)) + if (NX_IS_REVISION_P3(pdev->revision)) { + netxen_cleanup_minidump(adapter); pci_disable_pcie_error_reporting(pdev); + } pci_release_regions(pdev); pci_disable_device(pdev); @@ -2317,7 +2347,7 @@ nx_incr_dev_ref_cnt(struct netxen_adapter *adapter) static int nx_decr_dev_ref_cnt(struct netxen_adapter *adapter) { - int count; + int count, state; if (netxen_api_lock(adapter)) return -EIO; @@ -2325,8 +2355,9 @@ nx_decr_dev_ref_cnt(struct netxen_adapter *adapter) WARN_ON(count == 0); NXWR32(adapter, NX_CRB_DEV_REF_COUNT, --count); + state = NXRD32(adapter, NX_CRB_DEV_STATE); - if (count == 0) + if (count == 0 && state != NX_DEV_FAILED) NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_COLD); netxen_api_unlock(adapter); @@ -2355,7 +2386,7 @@ nx_dev_request_aer(struct netxen_adapter *adapter) return ret; } -static int +int nx_dev_request_reset(struct netxen_adapter *adapter) { u32 state; @@ -2366,10 +2397,11 @@ nx_dev_request_reset(struct netxen_adapter *adapter) state = NXRD32(adapter, NX_CRB_DEV_STATE); - if (state == NX_DEV_NEED_RESET) + if (state == NX_DEV_NEED_RESET || state == NX_DEV_FAILED) ret = 0; else if (state != NX_DEV_INITALIZING && state != NX_DEV_NEED_AER) { NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_NEED_RESET); + adapter->flags |= NETXEN_FW_RESET_OWNER; ret = 0; } @@ -2384,8 +2416,10 @@ netxen_can_start_firmware(struct netxen_adapter *adapter) int count; int can_start = 0; - if (netxen_api_lock(adapter)) - return 0; + if (netxen_api_lock(adapter)) { + nx_incr_dev_ref_cnt(adapter); + return -1; + } count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT); @@ -2457,8 +2491,31 @@ netxen_fwinit_work(struct work_struct *work) struct netxen_adapter *adapter = container_of(work, struct netxen_adapter, fw_work.work); int dev_state; - + int count; dev_state = NXRD32(adapter, NX_CRB_DEV_STATE); + if (adapter->flags & NETXEN_FW_RESET_OWNER) { + count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT); + WARN_ON(count == 0); + if (count == 1) { + if (adapter->mdump.md_enabled) { + rtnl_lock(); + netxen_dump_fw(adapter); + rtnl_unlock(); + } + adapter->flags &= ~NETXEN_FW_RESET_OWNER; + if (netxen_api_lock(adapter)) { + clear_bit(__NX_RESETTING, &adapter->state); + NXWR32(adapter, NX_CRB_DEV_STATE, + NX_DEV_FAILED); + return; + } + count = NXRD32(adapter, NX_CRB_DEV_REF_COUNT); + NXWR32(adapter, NX_CRB_DEV_REF_COUNT, --count); + NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_COLD); + dev_state = NX_DEV_COLD; + netxen_api_unlock(adapter); + } + } switch (dev_state) { case NX_DEV_COLD: @@ -2471,11 +2528,9 @@ netxen_fwinit_work(struct work_struct *work) case NX_DEV_NEED_RESET: case NX_DEV_INITALIZING: - if (++adapter->fw_wait_cnt < FW_POLL_THRESH) { netxen_schedule_work(adapter, netxen_fwinit_work, 2 * FW_POLL_DELAY); return; - } case NX_DEV_FAILED: default: @@ -2483,6 +2538,15 @@ netxen_fwinit_work(struct work_struct *work) break; } + if (netxen_api_lock(adapter)) { + clear_bit(__NX_RESETTING, &adapter->state); + return; + } + NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_FAILED); + netxen_api_unlock(adapter); + dev_err(&adapter->pdev->dev, "%s: Device initialization Failed\n", + adapter->netdev->name); + clear_bit(__NX_RESETTING, &adapter->state); } @@ -2492,7 +2556,7 @@ netxen_detach_work(struct work_struct *work) struct netxen_adapter *adapter = container_of(work, struct netxen_adapter, fw_work.work); struct net_device *netdev = adapter->netdev; - int ref_cnt, delay; + int ref_cnt = 0, delay; u32 status; netif_device_detach(netdev); @@ -2511,7 +2575,8 @@ netxen_detach_work(struct work_struct *work) if (adapter->temp == NX_TEMP_PANIC) goto err_ret; - ref_cnt = nx_decr_dev_ref_cnt(adapter); + if (!(adapter->flags & NETXEN_FW_RESET_OWNER)) + ref_cnt = nx_decr_dev_ref_cnt(adapter); if (ref_cnt == -EIO) goto err_ret; @@ -2531,6 +2596,7 @@ static int netxen_check_health(struct netxen_adapter *adapter) { u32 state, heartbit; + u32 peg_status; struct net_device *netdev = adapter->netdev; state = NXRD32(adapter, NX_CRB_DEV_STATE); @@ -2551,7 +2617,7 @@ netxen_check_health(struct netxen_adapter *adapter) * Send request to destroy context in case of tx timeout only * and doesn't required in case of Fw hang */ - if (state == NX_DEV_NEED_RESET) { + if (state == NX_DEV_NEED_RESET || state == NX_DEV_FAILED) { adapter->need_fw_reset = 1; if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) goto detach; @@ -2577,8 +2643,24 @@ netxen_check_health(struct netxen_adapter *adapter) clear_bit(__NX_FW_ATTACHED, &adapter->state); - dev_info(&netdev->dev, "firmware hang detected\n"); - + dev_err(&netdev->dev, "firmware hang detected\n"); + peg_status = NXRD32(adapter, NETXEN_PEG_HALT_STATUS1); + dev_err(&adapter->pdev->dev, "Dumping hw/fw registers\n" + "PEG_HALT_STATUS1: 0x%x, PEG_HALT_STATUS2: 0x%x,\n" + "PEG_NET_0_PC: 0x%x, PEG_NET_1_PC: 0x%x,\n" + "PEG_NET_2_PC: 0x%x, PEG_NET_3_PC: 0x%x,\n" + "PEG_NET_4_PC: 0x%x\n", + peg_status, + NXRD32(adapter, NETXEN_PEG_HALT_STATUS2), + NXRD32(adapter, NETXEN_CRB_PEG_NET_0 + 0x3c), + NXRD32(adapter, NETXEN_CRB_PEG_NET_1 + 0x3c), + NXRD32(adapter, NETXEN_CRB_PEG_NET_2 + 0x3c), + NXRD32(adapter, NETXEN_CRB_PEG_NET_3 + 0x3c), + NXRD32(adapter, NETXEN_CRB_PEG_NET_4 + 0x3c)); + if (NX_FWERROR_PEGSTAT1(peg_status) == 0x67) + dev_err(&adapter->pdev->dev, + "Firmware aborted with error code 0x00006700. " + "Device is being reset.\n"); detach: if ((auto_fw_reset == AUTO_FW_RESET_ENABLED) && !test_and_set_bit(__NX_RESETTING, &adapter->state)) @@ -2848,13 +2930,12 @@ static struct bin_attribute bin_attr_mem = { static void netxen_create_sysfs_entries(struct netxen_adapter *adapter) { - struct net_device *netdev = adapter->netdev; - struct device *dev = &netdev->dev; + struct device *dev = &adapter->pdev->dev; if (adapter->capabilities & NX_FW_CAPABILITY_BDG) { /* bridged_mode control */ if (device_create_file(dev, &dev_attr_bridged_mode)) { - dev_warn(&netdev->dev, + dev_warn(dev, "failed to create bridged_mode sysfs entry\n"); } } @@ -2863,8 +2944,7 @@ netxen_create_sysfs_entries(struct netxen_adapter *adapter) static void netxen_remove_sysfs_entries(struct netxen_adapter *adapter) { - struct net_device *netdev = adapter->netdev; - struct device *dev = &netdev->dev; + struct device *dev = &adapter->pdev->dev; if (adapter->capabilities & NX_FW_CAPABILITY_BDG) device_remove_file(dev, &dev_attr_bridged_mode); |