diff options
Diffstat (limited to 'drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c')
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | 65 |
1 files changed, 40 insertions, 25 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c index 89208e5b25d6..918e18ddf038 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c | |||
@@ -740,6 +740,7 @@ static int qlcnic_83xx_idc_unknown_state(struct qlcnic_adapter *adapter) | |||
740 | adapter->ahw->idc.err_code = -EIO; | 740 | adapter->ahw->idc.err_code = -EIO; |
741 | dev_err(&adapter->pdev->dev, | 741 | dev_err(&adapter->pdev->dev, |
742 | "%s: Device in unknown state\n", __func__); | 742 | "%s: Device in unknown state\n", __func__); |
743 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | ||
743 | return 0; | 744 | return 0; |
744 | } | 745 | } |
745 | 746 | ||
@@ -818,7 +819,6 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter) | |||
818 | struct qlcnic_hardware_context *ahw = adapter->ahw; | 819 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
819 | struct qlcnic_mailbox *mbx = ahw->mailbox; | 820 | struct qlcnic_mailbox *mbx = ahw->mailbox; |
820 | int ret = 0; | 821 | int ret = 0; |
821 | u32 owner; | ||
822 | u32 val; | 822 | u32 val; |
823 | 823 | ||
824 | /* Perform NIC configuration based ready state entry actions */ | 824 | /* Perform NIC configuration based ready state entry actions */ |
@@ -848,9 +848,9 @@ static int qlcnic_83xx_idc_ready_state(struct qlcnic_adapter *adapter) | |||
848 | set_bit(__QLCNIC_RESETTING, &adapter->state); | 848 | set_bit(__QLCNIC_RESETTING, &adapter->state); |
849 | qlcnic_83xx_idc_enter_need_reset_state(adapter, 1); | 849 | qlcnic_83xx_idc_enter_need_reset_state(adapter, 1); |
850 | } else { | 850 | } else { |
851 | owner = qlcnic_83xx_idc_find_reset_owner_id(adapter); | 851 | netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n", |
852 | if (ahw->pci_func == owner) | 852 | __func__); |
853 | qlcnic_dump_fw(adapter); | 853 | qlcnic_83xx_idc_enter_failed_state(adapter, 1); |
854 | } | 854 | } |
855 | return -EIO; | 855 | return -EIO; |
856 | } | 856 | } |
@@ -948,13 +948,26 @@ static int qlcnic_83xx_idc_need_quiesce_state(struct qlcnic_adapter *adapter) | |||
948 | return 0; | 948 | return 0; |
949 | } | 949 | } |
950 | 950 | ||
951 | static int qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter) | 951 | static void qlcnic_83xx_idc_failed_state(struct qlcnic_adapter *adapter) |
952 | { | 952 | { |
953 | dev_err(&adapter->pdev->dev, "%s: please restart!!\n", __func__); | 953 | struct qlcnic_hardware_context *ahw = adapter->ahw; |
954 | u32 val, owner; | ||
955 | |||
956 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); | ||
957 | if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) { | ||
958 | owner = qlcnic_83xx_idc_find_reset_owner_id(adapter); | ||
959 | if (ahw->pci_func == owner) { | ||
960 | qlcnic_83xx_stop_hw(adapter); | ||
961 | qlcnic_dump_fw(adapter); | ||
962 | } | ||
963 | } | ||
964 | |||
965 | netdev_warn(adapter->netdev, "%s: Reboot will be required to recover the adapter!!\n", | ||
966 | __func__); | ||
954 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 967 | clear_bit(__QLCNIC_RESETTING, &adapter->state); |
955 | adapter->ahw->idc.err_code = -EIO; | 968 | ahw->idc.err_code = -EIO; |
956 | 969 | ||
957 | return 0; | 970 | return; |
958 | } | 971 | } |
959 | 972 | ||
960 | static int qlcnic_83xx_idc_quiesce_state(struct qlcnic_adapter *adapter) | 973 | static int qlcnic_83xx_idc_quiesce_state(struct qlcnic_adapter *adapter) |
@@ -1063,12 +1076,6 @@ void qlcnic_83xx_idc_poll_dev_state(struct work_struct *work) | |||
1063 | adapter->ahw->idc.prev_state = adapter->ahw->idc.curr_state; | 1076 | adapter->ahw->idc.prev_state = adapter->ahw->idc.curr_state; |
1064 | qlcnic_83xx_periodic_tasks(adapter); | 1077 | qlcnic_83xx_periodic_tasks(adapter); |
1065 | 1078 | ||
1066 | /* Do not reschedule if firmaware is in hanged state and auto | ||
1067 | * recovery is disabled | ||
1068 | */ | ||
1069 | if ((adapter->flags & QLCNIC_FW_HANG) && !qlcnic_auto_fw_reset) | ||
1070 | return; | ||
1071 | |||
1072 | /* Re-schedule the function */ | 1079 | /* Re-schedule the function */ |
1073 | if (test_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status)) | 1080 | if (test_bit(QLC_83XX_MODULE_LOADED, &adapter->ahw->idc.status)) |
1074 | qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state, | 1081 | qlcnic_schedule_work(adapter, qlcnic_83xx_idc_poll_dev_state, |
@@ -1219,10 +1226,10 @@ void qlcnic_83xx_idc_request_reset(struct qlcnic_adapter *adapter, u32 key) | |||
1219 | } | 1226 | } |
1220 | 1227 | ||
1221 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); | 1228 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); |
1222 | if ((val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) || | 1229 | if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) { |
1223 | !qlcnic_auto_fw_reset) { | 1230 | netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n", |
1224 | dev_err(&adapter->pdev->dev, | 1231 | __func__); |
1225 | "%s:failed, device in non reset mode\n", __func__); | 1232 | qlcnic_83xx_idc_enter_failed_state(adapter, 0); |
1226 | qlcnic_83xx_unlock_driver(adapter); | 1233 | qlcnic_83xx_unlock_driver(adapter); |
1227 | return; | 1234 | return; |
1228 | } | 1235 | } |
@@ -1254,24 +1261,24 @@ static int qlcnic_83xx_copy_bootloader(struct qlcnic_adapter *adapter) | |||
1254 | if (size & 0xF) | 1261 | if (size & 0xF) |
1255 | size = (size + 16) & ~0xF; | 1262 | size = (size + 16) & ~0xF; |
1256 | 1263 | ||
1257 | p_cache = kzalloc(size, GFP_KERNEL); | 1264 | p_cache = vzalloc(size); |
1258 | if (p_cache == NULL) | 1265 | if (p_cache == NULL) |
1259 | return -ENOMEM; | 1266 | return -ENOMEM; |
1260 | 1267 | ||
1261 | ret = qlcnic_83xx_lockless_flash_read32(adapter, src, p_cache, | 1268 | ret = qlcnic_83xx_lockless_flash_read32(adapter, src, p_cache, |
1262 | size / sizeof(u32)); | 1269 | size / sizeof(u32)); |
1263 | if (ret) { | 1270 | if (ret) { |
1264 | kfree(p_cache); | 1271 | vfree(p_cache); |
1265 | return ret; | 1272 | return ret; |
1266 | } | 1273 | } |
1267 | /* 16 byte write to MS memory */ | 1274 | /* 16 byte write to MS memory */ |
1268 | ret = qlcnic_83xx_ms_mem_write128(adapter, dest, (u32 *)p_cache, | 1275 | ret = qlcnic_83xx_ms_mem_write128(adapter, dest, (u32 *)p_cache, |
1269 | size / 16); | 1276 | size / 16); |
1270 | if (ret) { | 1277 | if (ret) { |
1271 | kfree(p_cache); | 1278 | vfree(p_cache); |
1272 | return ret; | 1279 | return ret; |
1273 | } | 1280 | } |
1274 | kfree(p_cache); | 1281 | vfree(p_cache); |
1275 | 1282 | ||
1276 | return ret; | 1283 | return ret; |
1277 | } | 1284 | } |
@@ -1939,7 +1946,7 @@ static void qlcnic_83xx_exec_template_cmd(struct qlcnic_adapter *p_dev, | |||
1939 | p_dev->ahw->reset.seq_index = index; | 1946 | p_dev->ahw->reset.seq_index = index; |
1940 | } | 1947 | } |
1941 | 1948 | ||
1942 | static void qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev) | 1949 | void qlcnic_83xx_stop_hw(struct qlcnic_adapter *p_dev) |
1943 | { | 1950 | { |
1944 | p_dev->ahw->reset.seq_index = 0; | 1951 | p_dev->ahw->reset.seq_index = 0; |
1945 | 1952 | ||
@@ -1994,6 +2001,14 @@ static int qlcnic_83xx_restart_hw(struct qlcnic_adapter *adapter) | |||
1994 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); | 2001 | val = QLCRDX(adapter->ahw, QLC_83XX_IDC_CTRL); |
1995 | if (!(val & QLC_83XX_IDC_GRACEFULL_RESET)) | 2002 | if (!(val & QLC_83XX_IDC_GRACEFULL_RESET)) |
1996 | qlcnic_dump_fw(adapter); | 2003 | qlcnic_dump_fw(adapter); |
2004 | |||
2005 | if (val & QLC_83XX_IDC_DISABLE_FW_RESET_RECOVERY) { | ||
2006 | netdev_info(adapter->netdev, "%s: Auto firmware recovery is disabled\n", | ||
2007 | __func__); | ||
2008 | qlcnic_83xx_idc_enter_failed_state(adapter, 1); | ||
2009 | return err; | ||
2010 | } | ||
2011 | |||
1997 | qlcnic_83xx_init_hw(adapter); | 2012 | qlcnic_83xx_init_hw(adapter); |
1998 | 2013 | ||
1999 | if (qlcnic_83xx_copy_bootloader(adapter)) | 2014 | if (qlcnic_83xx_copy_bootloader(adapter)) |
@@ -2073,8 +2088,8 @@ int qlcnic_83xx_configure_opmode(struct qlcnic_adapter *adapter) | |||
2073 | ahw->nic_mode = QLCNIC_DEFAULT_MODE; | 2088 | ahw->nic_mode = QLCNIC_DEFAULT_MODE; |
2074 | adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver; | 2089 | adapter->nic_ops->init_driver = qlcnic_83xx_init_default_driver; |
2075 | ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; | 2090 | ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry; |
2076 | adapter->max_sds_rings = ahw->max_rx_ques; | 2091 | adapter->max_sds_rings = QLCNIC_MAX_SDS_RINGS; |
2077 | adapter->max_tx_rings = ahw->max_tx_ques; | 2092 | adapter->max_tx_rings = QLCNIC_MAX_TX_RINGS; |
2078 | } else { | 2093 | } else { |
2079 | return -EIO; | 2094 | return -EIO; |
2080 | } | 2095 | } |