diff options
Diffstat (limited to 'drivers/net/qlcnic/qlcnic_main.c')
-rw-r--r-- | drivers/net/qlcnic/qlcnic_main.c | 198 |
1 files changed, 135 insertions, 63 deletions
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index fc721564e69e..ee573fe52a8e 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c | |||
@@ -22,6 +22,7 @@ | |||
22 | * | 22 | * |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <linux/slab.h> | ||
25 | #include <linux/vmalloc.h> | 26 | #include <linux/vmalloc.h> |
26 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
27 | 28 | ||
@@ -207,6 +208,9 @@ qlcnic_napi_enable(struct qlcnic_adapter *adapter) | |||
207 | struct qlcnic_host_sds_ring *sds_ring; | 208 | struct qlcnic_host_sds_ring *sds_ring; |
208 | struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; | 209 | struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; |
209 | 210 | ||
211 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) | ||
212 | return; | ||
213 | |||
210 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | 214 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
211 | sds_ring = &recv_ctx->sds_rings[ring]; | 215 | sds_ring = &recv_ctx->sds_rings[ring]; |
212 | napi_enable(&sds_ring->napi); | 216 | napi_enable(&sds_ring->napi); |
@@ -221,6 +225,9 @@ qlcnic_napi_disable(struct qlcnic_adapter *adapter) | |||
221 | struct qlcnic_host_sds_ring *sds_ring; | 225 | struct qlcnic_host_sds_ring *sds_ring; |
222 | struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; | 226 | struct qlcnic_recv_context *recv_ctx = &adapter->recv_ctx; |
223 | 227 | ||
228 | if (adapter->is_up != QLCNIC_ADAPTER_UP_MAGIC) | ||
229 | return; | ||
230 | |||
224 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | 231 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
225 | sds_ring = &recv_ctx->sds_rings[ring]; | 232 | sds_ring = &recv_ctx->sds_rings[ring]; |
226 | qlcnic_disable_int(sds_ring); | 233 | qlcnic_disable_int(sds_ring); |
@@ -649,7 +656,10 @@ qlcnic_start_firmware(struct qlcnic_adapter *adapter) | |||
649 | if (err) | 656 | if (err) |
650 | return err; | 657 | return err; |
651 | 658 | ||
652 | if (!qlcnic_can_start_firmware(adapter)) | 659 | err = qlcnic_can_start_firmware(adapter); |
660 | if (err < 0) | ||
661 | return err; | ||
662 | else if (!err) | ||
653 | goto wait_init; | 663 | goto wait_init; |
654 | 664 | ||
655 | first_boot = QLCRD32(adapter, QLCNIC_CAM_RAM(0x1fc)); | 665 | first_boot = QLCRD32(adapter, QLCNIC_CAM_RAM(0x1fc)); |
@@ -949,11 +959,11 @@ void qlcnic_diag_free_res(struct net_device *netdev, int max_sds_rings) | |||
949 | adapter->max_sds_rings = max_sds_rings; | 959 | adapter->max_sds_rings = max_sds_rings; |
950 | 960 | ||
951 | if (qlcnic_attach(adapter)) | 961 | if (qlcnic_attach(adapter)) |
952 | return; | 962 | goto out; |
953 | 963 | ||
954 | if (netif_running(netdev)) | 964 | if (netif_running(netdev)) |
955 | __qlcnic_up(adapter, netdev); | 965 | __qlcnic_up(adapter, netdev); |
956 | 966 | out: | |
957 | netif_device_attach(netdev); | 967 | netif_device_attach(netdev); |
958 | } | 968 | } |
959 | 969 | ||
@@ -975,8 +985,10 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test) | |||
975 | adapter->diag_test = test; | 985 | adapter->diag_test = test; |
976 | 986 | ||
977 | ret = qlcnic_attach(adapter); | 987 | ret = qlcnic_attach(adapter); |
978 | if (ret) | 988 | if (ret) { |
989 | netif_device_attach(netdev); | ||
979 | return ret; | 990 | return ret; |
991 | } | ||
980 | 992 | ||
981 | if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) { | 993 | if (adapter->diag_test == QLCNIC_INTERRUPT_TEST) { |
982 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { | 994 | for (ring = 0; ring < adapter->max_sds_rings; ring++) { |
@@ -1009,16 +1021,12 @@ qlcnic_reset_context(struct qlcnic_adapter *adapter) | |||
1009 | if (netif_running(netdev)) { | 1021 | if (netif_running(netdev)) { |
1010 | err = qlcnic_attach(adapter); | 1022 | err = qlcnic_attach(adapter); |
1011 | if (!err) | 1023 | if (!err) |
1012 | err = __qlcnic_up(adapter, netdev); | 1024 | __qlcnic_up(adapter, netdev); |
1013 | |||
1014 | if (err) | ||
1015 | goto done; | ||
1016 | } | 1025 | } |
1017 | 1026 | ||
1018 | netif_device_attach(netdev); | 1027 | netif_device_attach(netdev); |
1019 | } | 1028 | } |
1020 | 1029 | ||
1021 | done: | ||
1022 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 1030 | clear_bit(__QLCNIC_RESETTING, &adapter->state); |
1023 | return err; | 1031 | return err; |
1024 | } | 1032 | } |
@@ -1138,6 +1146,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1138 | goto err_out_iounmap; | 1146 | goto err_out_iounmap; |
1139 | } | 1147 | } |
1140 | 1148 | ||
1149 | qlcnic_setup_idc_param(adapter); | ||
1141 | 1150 | ||
1142 | err = qlcnic_start_firmware(adapter); | 1151 | err = qlcnic_start_firmware(adapter); |
1143 | if (err) | 1152 | if (err) |
@@ -1333,6 +1342,7 @@ err_out_detach: | |||
1333 | qlcnic_detach(adapter); | 1342 | qlcnic_detach(adapter); |
1334 | err_out: | 1343 | err_out: |
1335 | qlcnic_clr_all_drv_state(adapter); | 1344 | qlcnic_clr_all_drv_state(adapter); |
1345 | netif_device_attach(netdev); | ||
1336 | return err; | 1346 | return err; |
1337 | } | 1347 | } |
1338 | #endif | 1348 | #endif |
@@ -1569,6 +1579,11 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
1569 | int frag_count, no_of_desc; | 1579 | int frag_count, no_of_desc; |
1570 | u32 num_txd = tx_ring->num_desc; | 1580 | u32 num_txd = tx_ring->num_desc; |
1571 | 1581 | ||
1582 | if (!test_bit(__QLCNIC_DEV_UP, &adapter->state)) { | ||
1583 | netif_stop_queue(netdev); | ||
1584 | return NETDEV_TX_BUSY; | ||
1585 | } | ||
1586 | |||
1572 | frag_count = skb_shinfo(skb)->nr_frags + 1; | 1587 | frag_count = skb_shinfo(skb)->nr_frags + 1; |
1573 | 1588 | ||
1574 | /* 4 fragments per cmd des */ | 1589 | /* 4 fragments per cmd des */ |
@@ -1585,8 +1600,10 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) | |||
1585 | 1600 | ||
1586 | pdev = adapter->pdev; | 1601 | pdev = adapter->pdev; |
1587 | 1602 | ||
1588 | if (qlcnic_map_tx_skb(pdev, skb, pbuf)) | 1603 | if (qlcnic_map_tx_skb(pdev, skb, pbuf)) { |
1604 | adapter->stats.tx_dma_map_error++; | ||
1589 | goto drop_packet; | 1605 | goto drop_packet; |
1606 | } | ||
1590 | 1607 | ||
1591 | pbuf->skb = skb; | 1608 | pbuf->skb = skb; |
1592 | pbuf->frag_count = frag_count; | 1609 | pbuf->frag_count = frag_count; |
@@ -1738,6 +1755,7 @@ static void qlcnic_tx_timeout_task(struct work_struct *work) | |||
1738 | request_reset: | 1755 | request_reset: |
1739 | adapter->need_fw_reset = 1; | 1756 | adapter->need_fw_reset = 1; |
1740 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 1757 | clear_bit(__QLCNIC_RESETTING, &adapter->state); |
1758 | QLCDB(adapter, DRV, "Resetting adapter\n"); | ||
1741 | } | 1759 | } |
1742 | 1760 | ||
1743 | static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev) | 1761 | static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev) |
@@ -1942,8 +1960,8 @@ static void qlcnic_poll_controller(struct net_device *netdev) | |||
1942 | } | 1960 | } |
1943 | #endif | 1961 | #endif |
1944 | 1962 | ||
1945 | static void | 1963 | static int |
1946 | qlcnic_set_drv_state(struct qlcnic_adapter *adapter, int state) | 1964 | qlcnic_set_drv_state(struct qlcnic_adapter *adapter, u8 state) |
1947 | { | 1965 | { |
1948 | u32 val; | 1966 | u32 val; |
1949 | 1967 | ||
@@ -1951,18 +1969,20 @@ qlcnic_set_drv_state(struct qlcnic_adapter *adapter, int state) | |||
1951 | state != QLCNIC_DEV_NEED_QUISCENT); | 1969 | state != QLCNIC_DEV_NEED_QUISCENT); |
1952 | 1970 | ||
1953 | if (qlcnic_api_lock(adapter)) | 1971 | if (qlcnic_api_lock(adapter)) |
1954 | return ; | 1972 | return -EIO; |
1955 | 1973 | ||
1956 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); | 1974 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); |
1957 | 1975 | ||
1958 | if (state == QLCNIC_DEV_NEED_RESET) | 1976 | if (state == QLCNIC_DEV_NEED_RESET) |
1959 | val |= ((u32)0x1 << (adapter->portnum * 4)); | 1977 | QLC_DEV_SET_RST_RDY(val, adapter->portnum); |
1960 | else if (state == QLCNIC_DEV_NEED_QUISCENT) | 1978 | else if (state == QLCNIC_DEV_NEED_QUISCENT) |
1961 | val |= ((u32)0x1 << ((adapter->portnum * 4) + 1)); | 1979 | QLC_DEV_SET_QSCNT_RDY(val, adapter->portnum); |
1962 | 1980 | ||
1963 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); | 1981 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); |
1964 | 1982 | ||
1965 | qlcnic_api_unlock(adapter); | 1983 | qlcnic_api_unlock(adapter); |
1984 | |||
1985 | return 0; | ||
1966 | } | 1986 | } |
1967 | 1987 | ||
1968 | static int | 1988 | static int |
@@ -1974,7 +1994,7 @@ qlcnic_clr_drv_state(struct qlcnic_adapter *adapter) | |||
1974 | return -EBUSY; | 1994 | return -EBUSY; |
1975 | 1995 | ||
1976 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); | 1996 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); |
1977 | val &= ~((u32)0x3 << (adapter->portnum * 4)); | 1997 | QLC_DEV_CLR_RST_QSCNT(val, adapter->portnum); |
1978 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); | 1998 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); |
1979 | 1999 | ||
1980 | qlcnic_api_unlock(adapter); | 2000 | qlcnic_api_unlock(adapter); |
@@ -1991,14 +2011,14 @@ qlcnic_clr_all_drv_state(struct qlcnic_adapter *adapter) | |||
1991 | goto err; | 2011 | goto err; |
1992 | 2012 | ||
1993 | val = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT); | 2013 | val = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT); |
1994 | val &= ~((u32)0x1 << (adapter->portnum * 4)); | 2014 | QLC_DEV_CLR_REF_CNT(val, adapter->portnum); |
1995 | QLCWR32(adapter, QLCNIC_CRB_DEV_REF_COUNT, val); | 2015 | QLCWR32(adapter, QLCNIC_CRB_DEV_REF_COUNT, val); |
1996 | 2016 | ||
1997 | if (!(val & 0x11111111)) | 2017 | if (!(val & 0x11111111)) |
1998 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_COLD); | 2018 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_COLD); |
1999 | 2019 | ||
2000 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); | 2020 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); |
2001 | val &= ~((u32)0x3 << (adapter->portnum * 4)); | 2021 | QLC_DEV_CLR_RST_QSCNT(val, adapter->portnum); |
2002 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); | 2022 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); |
2003 | 2023 | ||
2004 | qlcnic_api_unlock(adapter); | 2024 | qlcnic_api_unlock(adapter); |
@@ -2008,6 +2028,7 @@ err: | |||
2008 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 2028 | clear_bit(__QLCNIC_RESETTING, &adapter->state); |
2009 | } | 2029 | } |
2010 | 2030 | ||
2031 | /* Grab api lock, before checking state */ | ||
2011 | static int | 2032 | static int |
2012 | qlcnic_check_drv_state(struct qlcnic_adapter *adapter) | 2033 | qlcnic_check_drv_state(struct qlcnic_adapter *adapter) |
2013 | { | 2034 | { |
@@ -2027,26 +2048,27 @@ static int | |||
2027 | qlcnic_can_start_firmware(struct qlcnic_adapter *adapter) | 2048 | qlcnic_can_start_firmware(struct qlcnic_adapter *adapter) |
2028 | { | 2049 | { |
2029 | u32 val, prev_state; | 2050 | u32 val, prev_state; |
2030 | int cnt = 0; | 2051 | u8 dev_init_timeo = adapter->dev_init_timeo; |
2031 | int portnum = adapter->portnum; | 2052 | u8 portnum = adapter->portnum; |
2053 | |||
2054 | if (test_and_clear_bit(__QLCNIC_START_FW, &adapter->state)) | ||
2055 | return 1; | ||
2032 | 2056 | ||
2033 | if (qlcnic_api_lock(adapter)) | 2057 | if (qlcnic_api_lock(adapter)) |
2034 | return -1; | 2058 | return -1; |
2035 | 2059 | ||
2036 | val = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT); | 2060 | val = QLCRD32(adapter, QLCNIC_CRB_DEV_REF_COUNT); |
2037 | if (!(val & ((int)0x1 << (portnum * 4)))) { | 2061 | if (!(val & (1 << (portnum * 4)))) { |
2038 | val |= ((u32)0x1 << (portnum * 4)); | 2062 | QLC_DEV_SET_REF_CNT(val, portnum); |
2039 | QLCWR32(adapter, QLCNIC_CRB_DEV_REF_COUNT, val); | 2063 | QLCWR32(adapter, QLCNIC_CRB_DEV_REF_COUNT, val); |
2040 | } else if (test_and_clear_bit(__QLCNIC_START_FW, &adapter->state)) { | ||
2041 | goto start_fw; | ||
2042 | } | 2064 | } |
2043 | 2065 | ||
2044 | prev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); | 2066 | prev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); |
2067 | QLCDB(adapter, HW, "Device state = %u\n", prev_state); | ||
2045 | 2068 | ||
2046 | switch (prev_state) { | 2069 | switch (prev_state) { |
2047 | case QLCNIC_DEV_COLD: | 2070 | case QLCNIC_DEV_COLD: |
2048 | start_fw: | 2071 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITIALIZING); |
2049 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_INITALIZING); | ||
2050 | qlcnic_api_unlock(adapter); | 2072 | qlcnic_api_unlock(adapter); |
2051 | return 1; | 2073 | return 1; |
2052 | 2074 | ||
@@ -2056,35 +2078,43 @@ start_fw: | |||
2056 | 2078 | ||
2057 | case QLCNIC_DEV_NEED_RESET: | 2079 | case QLCNIC_DEV_NEED_RESET: |
2058 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); | 2080 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); |
2059 | val |= ((u32)0x1 << (portnum * 4)); | 2081 | QLC_DEV_SET_RST_RDY(val, portnum); |
2060 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); | 2082 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); |
2061 | break; | 2083 | break; |
2062 | 2084 | ||
2063 | case QLCNIC_DEV_NEED_QUISCENT: | 2085 | case QLCNIC_DEV_NEED_QUISCENT: |
2064 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); | 2086 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); |
2065 | val |= ((u32)0x1 << ((portnum * 4) + 1)); | 2087 | QLC_DEV_SET_QSCNT_RDY(val, portnum); |
2066 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); | 2088 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); |
2067 | break; | 2089 | break; |
2068 | 2090 | ||
2069 | case QLCNIC_DEV_FAILED: | 2091 | case QLCNIC_DEV_FAILED: |
2070 | qlcnic_api_unlock(adapter); | 2092 | qlcnic_api_unlock(adapter); |
2071 | return -1; | 2093 | return -1; |
2094 | |||
2095 | case QLCNIC_DEV_INITIALIZING: | ||
2096 | case QLCNIC_DEV_QUISCENT: | ||
2097 | break; | ||
2072 | } | 2098 | } |
2073 | 2099 | ||
2074 | qlcnic_api_unlock(adapter); | 2100 | qlcnic_api_unlock(adapter); |
2075 | msleep(1000); | 2101 | |
2076 | while ((QLCRD32(adapter, QLCNIC_CRB_DEV_STATE) != QLCNIC_DEV_READY) && | 2102 | do { |
2077 | ++cnt < 20) | ||
2078 | msleep(1000); | 2103 | msleep(1000); |
2104 | } while ((QLCRD32(adapter, QLCNIC_CRB_DEV_STATE) != QLCNIC_DEV_READY) | ||
2105 | && --dev_init_timeo); | ||
2079 | 2106 | ||
2080 | if (cnt >= 20) | 2107 | if (!dev_init_timeo) { |
2108 | dev_err(&adapter->pdev->dev, | ||
2109 | "Waiting for device to initialize timeout\n"); | ||
2081 | return -1; | 2110 | return -1; |
2111 | } | ||
2082 | 2112 | ||
2083 | if (qlcnic_api_lock(adapter)) | 2113 | if (qlcnic_api_lock(adapter)) |
2084 | return -1; | 2114 | return -1; |
2085 | 2115 | ||
2086 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); | 2116 | val = QLCRD32(adapter, QLCNIC_CRB_DRV_STATE); |
2087 | val &= ~((u32)0x3 << (portnum * 4)); | 2117 | QLC_DEV_CLR_RST_QSCNT(val, portnum); |
2088 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); | 2118 | QLCWR32(adapter, QLCNIC_CRB_DRV_STATE, val); |
2089 | 2119 | ||
2090 | qlcnic_api_unlock(adapter); | 2120 | qlcnic_api_unlock(adapter); |
@@ -2097,44 +2127,60 @@ qlcnic_fwinit_work(struct work_struct *work) | |||
2097 | { | 2127 | { |
2098 | struct qlcnic_adapter *adapter = container_of(work, | 2128 | struct qlcnic_adapter *adapter = container_of(work, |
2099 | struct qlcnic_adapter, fw_work.work); | 2129 | struct qlcnic_adapter, fw_work.work); |
2100 | int dev_state; | 2130 | u32 dev_state = 0xf; |
2101 | 2131 | ||
2102 | if (++adapter->fw_wait_cnt > FW_POLL_THRESH) | 2132 | if (qlcnic_api_lock(adapter)) |
2103 | goto err_ret; | 2133 | goto err_ret; |
2104 | 2134 | ||
2105 | if (test_bit(__QLCNIC_START_FW, &adapter->state)) { | 2135 | if (adapter->fw_wait_cnt++ > adapter->reset_ack_timeo) { |
2136 | dev_err(&adapter->pdev->dev, "Reset:Failed to get ack %d sec\n", | ||
2137 | adapter->reset_ack_timeo); | ||
2138 | goto skip_ack_check; | ||
2139 | } | ||
2106 | 2140 | ||
2107 | if (qlcnic_check_drv_state(adapter)) { | 2141 | if (!qlcnic_check_drv_state(adapter)) { |
2108 | qlcnic_schedule_work(adapter, | 2142 | skip_ack_check: |
2109 | qlcnic_fwinit_work, FW_POLL_DELAY); | 2143 | dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); |
2110 | return; | 2144 | if (dev_state == QLCNIC_DEV_NEED_RESET) { |
2145 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, | ||
2146 | QLCNIC_DEV_INITIALIZING); | ||
2147 | set_bit(__QLCNIC_START_FW, &adapter->state); | ||
2148 | QLCDB(adapter, DRV, "Restarting fw\n"); | ||
2111 | } | 2149 | } |
2112 | 2150 | ||
2151 | qlcnic_api_unlock(adapter); | ||
2152 | |||
2113 | if (!qlcnic_start_firmware(adapter)) { | 2153 | if (!qlcnic_start_firmware(adapter)) { |
2114 | qlcnic_schedule_work(adapter, qlcnic_attach_work, 0); | 2154 | qlcnic_schedule_work(adapter, qlcnic_attach_work, 0); |
2115 | return; | 2155 | return; |
2116 | } | 2156 | } |
2117 | |||
2118 | goto err_ret; | 2157 | goto err_ret; |
2119 | } | 2158 | } |
2120 | 2159 | ||
2160 | qlcnic_api_unlock(adapter); | ||
2161 | |||
2121 | dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); | 2162 | dev_state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); |
2163 | QLCDB(adapter, HW, "Func waiting: Device state=%u\n", dev_state); | ||
2164 | |||
2122 | switch (dev_state) { | 2165 | switch (dev_state) { |
2123 | case QLCNIC_DEV_READY: | 2166 | case QLCNIC_DEV_NEED_RESET: |
2124 | if (!qlcnic_start_firmware(adapter)) { | 2167 | qlcnic_schedule_work(adapter, |
2125 | qlcnic_schedule_work(adapter, qlcnic_attach_work, 0); | 2168 | qlcnic_fwinit_work, FW_POLL_DELAY); |
2126 | return; | 2169 | return; |
2127 | } | ||
2128 | case QLCNIC_DEV_FAILED: | 2170 | case QLCNIC_DEV_FAILED: |
2129 | break; | 2171 | break; |
2130 | 2172 | ||
2131 | default: | 2173 | default: |
2132 | qlcnic_schedule_work(adapter, | 2174 | if (!qlcnic_start_firmware(adapter)) { |
2133 | qlcnic_fwinit_work, 2 * FW_POLL_DELAY); | 2175 | qlcnic_schedule_work(adapter, qlcnic_attach_work, 0); |
2134 | return; | 2176 | return; |
2177 | } | ||
2135 | } | 2178 | } |
2136 | 2179 | ||
2137 | err_ret: | 2180 | err_ret: |
2181 | dev_err(&adapter->pdev->dev, "Fwinit work failed state=%u " | ||
2182 | "fw_wait_cnt=%u\n", dev_state, adapter->fw_wait_cnt); | ||
2183 | netif_device_attach(adapter->netdev); | ||
2138 | qlcnic_clr_all_drv_state(adapter); | 2184 | qlcnic_clr_all_drv_state(adapter); |
2139 | } | 2185 | } |
2140 | 2186 | ||
@@ -2162,7 +2208,8 @@ qlcnic_detach_work(struct work_struct *work) | |||
2162 | if (adapter->temp == QLCNIC_TEMP_PANIC) | 2208 | if (adapter->temp == QLCNIC_TEMP_PANIC) |
2163 | goto err_ret; | 2209 | goto err_ret; |
2164 | 2210 | ||
2165 | qlcnic_set_drv_state(adapter, adapter->dev_state); | 2211 | if (qlcnic_set_drv_state(adapter, adapter->dev_state)) |
2212 | goto err_ret; | ||
2166 | 2213 | ||
2167 | adapter->fw_wait_cnt = 0; | 2214 | adapter->fw_wait_cnt = 0; |
2168 | 2215 | ||
@@ -2171,10 +2218,14 @@ qlcnic_detach_work(struct work_struct *work) | |||
2171 | return; | 2218 | return; |
2172 | 2219 | ||
2173 | err_ret: | 2220 | err_ret: |
2221 | dev_err(&adapter->pdev->dev, "detach failed; status=%d temp=%d\n", | ||
2222 | status, adapter->temp); | ||
2223 | netif_device_attach(netdev); | ||
2174 | qlcnic_clr_all_drv_state(adapter); | 2224 | qlcnic_clr_all_drv_state(adapter); |
2175 | 2225 | ||
2176 | } | 2226 | } |
2177 | 2227 | ||
2228 | /*Transit to RESET state from READY state only */ | ||
2178 | static void | 2229 | static void |
2179 | qlcnic_dev_request_reset(struct qlcnic_adapter *adapter) | 2230 | qlcnic_dev_request_reset(struct qlcnic_adapter *adapter) |
2180 | { | 2231 | { |
@@ -2185,9 +2236,9 @@ qlcnic_dev_request_reset(struct qlcnic_adapter *adapter) | |||
2185 | 2236 | ||
2186 | state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); | 2237 | state = QLCRD32(adapter, QLCNIC_CRB_DEV_STATE); |
2187 | 2238 | ||
2188 | if (state != QLCNIC_DEV_INITALIZING && state != QLCNIC_DEV_NEED_RESET) { | 2239 | if (state == QLCNIC_DEV_READY) { |
2189 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_RESET); | 2240 | QLCWR32(adapter, QLCNIC_CRB_DEV_STATE, QLCNIC_DEV_NEED_RESET); |
2190 | set_bit(__QLCNIC_START_FW, &adapter->state); | 2241 | QLCDB(adapter, DRV, "NEED_RESET state set\n"); |
2191 | } | 2242 | } |
2192 | 2243 | ||
2193 | qlcnic_api_unlock(adapter); | 2244 | qlcnic_api_unlock(adapter); |
@@ -2232,9 +2283,8 @@ qlcnic_attach_work(struct work_struct *work) | |||
2232 | qlcnic_config_indev_addr(netdev, NETDEV_UP); | 2283 | qlcnic_config_indev_addr(netdev, NETDEV_UP); |
2233 | } | 2284 | } |
2234 | 2285 | ||
2235 | netif_device_attach(netdev); | ||
2236 | |||
2237 | done: | 2286 | done: |
2287 | netif_device_attach(netdev); | ||
2238 | adapter->fw_fail_cnt = 0; | 2288 | adapter->fw_fail_cnt = 0; |
2239 | clear_bit(__QLCNIC_RESETTING, &adapter->state); | 2289 | clear_bit(__QLCNIC_RESETTING, &adapter->state); |
2240 | 2290 | ||
@@ -2284,8 +2334,11 @@ detach: | |||
2284 | QLCNIC_DEV_NEED_RESET; | 2334 | QLCNIC_DEV_NEED_RESET; |
2285 | 2335 | ||
2286 | if ((auto_fw_reset == AUTO_FW_RESET_ENABLED) && | 2336 | if ((auto_fw_reset == AUTO_FW_RESET_ENABLED) && |
2287 | !test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) | 2337 | !test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) { |
2338 | |||
2288 | qlcnic_schedule_work(adapter, qlcnic_detach_work, 0); | 2339 | qlcnic_schedule_work(adapter, qlcnic_detach_work, 0); |
2340 | QLCDB(adapter, DRV, "fw recovery scheduled.\n"); | ||
2341 | } | ||
2289 | 2342 | ||
2290 | return 1; | 2343 | return 1; |
2291 | } | 2344 | } |
@@ -2386,14 +2439,21 @@ static int | |||
2386 | qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter, | 2439 | qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter, |
2387 | loff_t offset, size_t size) | 2440 | loff_t offset, size_t size) |
2388 | { | 2441 | { |
2442 | size_t crb_size = 4; | ||
2443 | |||
2389 | if (!(adapter->flags & QLCNIC_DIAG_ENABLED)) | 2444 | if (!(adapter->flags & QLCNIC_DIAG_ENABLED)) |
2390 | return -EIO; | 2445 | return -EIO; |
2391 | 2446 | ||
2392 | if ((size != 4) || (offset & 0x3)) | 2447 | if (offset < QLCNIC_PCI_CRBSPACE) { |
2393 | return -EINVAL; | 2448 | if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, |
2449 | QLCNIC_PCI_CAMQM_END)) | ||
2450 | crb_size = 8; | ||
2451 | else | ||
2452 | return -EINVAL; | ||
2453 | } | ||
2394 | 2454 | ||
2395 | if (offset < QLCNIC_PCI_CRBSPACE) | 2455 | if ((size != crb_size) || (offset & (crb_size-1))) |
2396 | return -EINVAL; | 2456 | return -EINVAL; |
2397 | 2457 | ||
2398 | return 0; | 2458 | return 0; |
2399 | } | 2459 | } |
@@ -2405,14 +2465,20 @@ qlcnic_sysfs_read_crb(struct kobject *kobj, struct bin_attribute *attr, | |||
2405 | struct device *dev = container_of(kobj, struct device, kobj); | 2465 | struct device *dev = container_of(kobj, struct device, kobj); |
2406 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | 2466 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); |
2407 | u32 data; | 2467 | u32 data; |
2468 | u64 qmdata; | ||
2408 | int ret; | 2469 | int ret; |
2409 | 2470 | ||
2410 | ret = qlcnic_sysfs_validate_crb(adapter, offset, size); | 2471 | ret = qlcnic_sysfs_validate_crb(adapter, offset, size); |
2411 | if (ret != 0) | 2472 | if (ret != 0) |
2412 | return ret; | 2473 | return ret; |
2413 | 2474 | ||
2414 | data = QLCRD32(adapter, offset); | 2475 | if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) { |
2415 | memcpy(buf, &data, size); | 2476 | qlcnic_pci_camqm_read_2M(adapter, offset, &qmdata); |
2477 | memcpy(buf, &qmdata, size); | ||
2478 | } else { | ||
2479 | data = QLCRD32(adapter, offset); | ||
2480 | memcpy(buf, &data, size); | ||
2481 | } | ||
2416 | return size; | 2482 | return size; |
2417 | } | 2483 | } |
2418 | 2484 | ||
@@ -2423,14 +2489,20 @@ qlcnic_sysfs_write_crb(struct kobject *kobj, struct bin_attribute *attr, | |||
2423 | struct device *dev = container_of(kobj, struct device, kobj); | 2489 | struct device *dev = container_of(kobj, struct device, kobj); |
2424 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); | 2490 | struct qlcnic_adapter *adapter = dev_get_drvdata(dev); |
2425 | u32 data; | 2491 | u32 data; |
2492 | u64 qmdata; | ||
2426 | int ret; | 2493 | int ret; |
2427 | 2494 | ||
2428 | ret = qlcnic_sysfs_validate_crb(adapter, offset, size); | 2495 | ret = qlcnic_sysfs_validate_crb(adapter, offset, size); |
2429 | if (ret != 0) | 2496 | if (ret != 0) |
2430 | return ret; | 2497 | return ret; |
2431 | 2498 | ||
2432 | memcpy(&data, buf, size); | 2499 | if (ADDR_IN_RANGE(offset, QLCNIC_PCI_CAMQM, QLCNIC_PCI_CAMQM_END)) { |
2433 | QLCWR32(adapter, offset, data); | 2500 | memcpy(&qmdata, buf, size); |
2501 | qlcnic_pci_camqm_write_2M(adapter, offset, qmdata); | ||
2502 | } else { | ||
2503 | memcpy(&data, buf, size); | ||
2504 | QLCWR32(adapter, offset, data); | ||
2505 | } | ||
2434 | return size; | 2506 | return size; |
2435 | } | 2507 | } |
2436 | 2508 | ||