diff options
| author | Eliezer Tamir <eliezert@broadcom.com> | 2008-02-28 14:56:57 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2008-02-28 14:56:57 -0500 |
| commit | 228241eb58ad13e7cf2ddd9c92eabb5c3055cf5c (patch) | |
| tree | 765d0de072a2eab6575ff735a05e8ea492c4d08a | |
| parent | 877e9aa4c31d8d1670b21824b819929435f46579 (diff) | |
[BNX2X]: fix slowpath races and locking
Fixed locking between fastpath and slowpath operations.
Corrected order of traffic disabling to prevent race when going down
under traffic.
- first have the microcode drop all incoming packets
- then do the slowpath stuff
- only then reset the MAC
Got rid of in_reset_task.
Remove_one() and friends would deference a null pointer if init_one
failed.
Signed-off-by: Eliezer Tamir <eliezert@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | drivers/net/bnx2x.c | 213 | ||||
| -rw-r--r-- | drivers/net/bnx2x.h | 3 |
2 files changed, 116 insertions, 100 deletions
diff --git a/drivers/net/bnx2x.c b/drivers/net/bnx2x.c index b99e3b72fac6..d21599cfeb89 100644 --- a/drivers/net/bnx2x.c +++ b/drivers/net/bnx2x.c | |||
| @@ -6881,14 +6881,11 @@ static void bnx2x_free_msix_irqs(struct bnx2x *bp) | |||
| 6881 | "state(%x)\n", i, bp->msix_table[i + 1].vector, | 6881 | "state(%x)\n", i, bp->msix_table[i + 1].vector, |
| 6882 | bnx2x_fp(bp, i, state)); | 6882 | bnx2x_fp(bp, i, state)); |
| 6883 | 6883 | ||
| 6884 | if (bnx2x_fp(bp, i, state) != BNX2X_FP_STATE_CLOSED) { | 6884 | if (bnx2x_fp(bp, i, state) != BNX2X_FP_STATE_CLOSED) |
| 6885 | 6885 | BNX2X_ERR("IRQ of fp #%d being freed while " | |
| 6886 | free_irq(bp->msix_table[i + 1].vector, &bp->fp[i]); | 6886 | "state != closed\n", i); |
| 6887 | bnx2x_fp(bp, i, state) = BNX2X_FP_STATE_CLOSED; | ||
| 6888 | |||
| 6889 | } else | ||
| 6890 | DP(NETIF_MSG_IFDOWN, "irq not freed\n"); | ||
| 6891 | 6887 | ||
| 6888 | free_irq(bp->msix_table[i + 1].vector, &bp->fp[i]); | ||
| 6892 | } | 6889 | } |
| 6893 | 6890 | ||
| 6894 | } | 6891 | } |
| @@ -6918,7 +6915,7 @@ static int bnx2x_enable_msix(struct bnx2x *bp) | |||
| 6918 | 6915 | ||
| 6919 | if (pci_enable_msix(bp->pdev, &bp->msix_table[0], | 6916 | if (pci_enable_msix(bp->pdev, &bp->msix_table[0], |
| 6920 | bp->num_queues + 1)){ | 6917 | bp->num_queues + 1)){ |
| 6921 | BNX2X_ERR("failed to enable msix\n"); | 6918 | BNX2X_LOG("failed to enable MSI-X\n"); |
| 6922 | return -1; | 6919 | return -1; |
| 6923 | 6920 | ||
| 6924 | } | 6921 | } |
| @@ -6935,8 +6932,6 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp) | |||
| 6935 | 6932 | ||
| 6936 | int i, rc; | 6933 | int i, rc; |
| 6937 | 6934 | ||
| 6938 | DP(NETIF_MSG_IFUP, "about to request sp irq\n"); | ||
| 6939 | |||
| 6940 | rc = request_irq(bp->msix_table[0].vector, bnx2x_msix_sp_int, 0, | 6935 | rc = request_irq(bp->msix_table[0].vector, bnx2x_msix_sp_int, 0, |
| 6941 | bp->dev->name, bp->dev); | 6936 | bp->dev->name, bp->dev); |
| 6942 | 6937 | ||
| @@ -6951,7 +6946,8 @@ static int bnx2x_req_msix_irqs(struct bnx2x *bp) | |||
| 6951 | bp->dev->name, &bp->fp[i]); | 6946 | bp->dev->name, &bp->fp[i]); |
| 6952 | 6947 | ||
| 6953 | if (rc) { | 6948 | if (rc) { |
| 6954 | BNX2X_ERR("request fp #%d irq failed\n", i); | 6949 | BNX2X_ERR("request fp #%d irq failed " |
| 6950 | "rc %d\n", i, rc); | ||
| 6955 | bnx2x_free_msix_irqs(bp); | 6951 | bnx2x_free_msix_irqs(bp); |
| 6956 | return -EBUSY; | 6952 | return -EBUSY; |
| 6957 | } | 6953 | } |
| @@ -7084,12 +7080,13 @@ static int bnx2x_setup_multi(struct bnx2x *bp, int index) | |||
| 7084 | /* reset IGU state */ | 7080 | /* reset IGU state */ |
| 7085 | bnx2x_ack_sb(bp, index, CSTORM_ID, 0, IGU_INT_ENABLE, 0); | 7081 | bnx2x_ack_sb(bp, index, CSTORM_ID, 0, IGU_INT_ENABLE, 0); |
| 7086 | 7082 | ||
| 7083 | /* SETUP ramrod */ | ||
| 7087 | bp->fp[index].state = BNX2X_FP_STATE_OPENING; | 7084 | bp->fp[index].state = BNX2X_FP_STATE_OPENING; |
| 7088 | bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_SETUP, index, 0, index, 0); | 7085 | bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_CLIENT_SETUP, index, 0, index, 0); |
| 7089 | 7086 | ||
| 7090 | /* Wait for completion */ | 7087 | /* Wait for completion */ |
| 7091 | return bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_OPEN, index, | 7088 | return bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_OPEN, index, |
| 7092 | &(bp->fp[index].state), 1); | 7089 | &(bp->fp[index].state), 0); |
| 7093 | 7090 | ||
| 7094 | } | 7091 | } |
| 7095 | 7092 | ||
| @@ -7099,8 +7096,8 @@ static void bnx2x_set_rx_mode(struct net_device *dev); | |||
| 7099 | 7096 | ||
| 7100 | static int bnx2x_nic_load(struct bnx2x *bp, int req_irq) | 7097 | static int bnx2x_nic_load(struct bnx2x *bp, int req_irq) |
| 7101 | { | 7098 | { |
| 7102 | int rc; | 7099 | u32 load_code; |
| 7103 | int i = 0; | 7100 | int i; |
| 7104 | 7101 | ||
| 7105 | bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD; | 7102 | bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD; |
| 7106 | 7103 | ||
| @@ -7110,12 +7107,17 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq) | |||
| 7110 | initialized, otherwise - not. | 7107 | initialized, otherwise - not. |
| 7111 | */ | 7108 | */ |
| 7112 | if (!nomcp) { | 7109 | if (!nomcp) { |
| 7113 | rc = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ); | 7110 | load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ); |
| 7114 | if (rc == FW_MSG_CODE_DRV_LOAD_REFUSED) { | 7111 | if (!load_code) { |
| 7112 | BNX2X_ERR("MCP response failure, unloading\n"); | ||
| 7113 | return -EBUSY; | ||
| 7114 | } | ||
| 7115 | if (load_code == FW_MSG_CODE_DRV_LOAD_REFUSED) { | ||
| 7116 | BNX2X_ERR("MCP refused load request, unloading\n"); | ||
| 7115 | return -EBUSY; /* other port in diagnostic mode */ | 7117 | return -EBUSY; /* other port in diagnostic mode */ |
| 7116 | } | 7118 | } |
| 7117 | } else { | 7119 | } else { |
| 7118 | rc = FW_MSG_CODE_DRV_LOAD_COMMON; | 7120 | load_code = FW_MSG_CODE_DRV_LOAD_COMMON; |
| 7119 | } | 7121 | } |
| 7120 | 7122 | ||
| 7121 | /* if we can't use msix we only need one fp, | 7123 | /* if we can't use msix we only need one fp, |
| @@ -7153,13 +7155,13 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq) | |||
| 7153 | if (bp->flags & USING_MSIX_FLAG) { | 7155 | if (bp->flags & USING_MSIX_FLAG) { |
| 7154 | if (bnx2x_req_msix_irqs(bp)) { | 7156 | if (bnx2x_req_msix_irqs(bp)) { |
| 7155 | pci_disable_msix(bp->pdev); | 7157 | pci_disable_msix(bp->pdev); |
| 7156 | goto out_error; | 7158 | goto load_error; |
| 7157 | } | 7159 | } |
| 7158 | 7160 | ||
| 7159 | } else { | 7161 | } else { |
| 7160 | if (bnx2x_req_irq(bp)) { | 7162 | if (bnx2x_req_irq(bp)) { |
| 7161 | BNX2X_ERR("IRQ request failed, aborting\n"); | 7163 | BNX2X_ERR("IRQ request failed, aborting\n"); |
| 7162 | goto out_error; | 7164 | goto load_error; |
| 7163 | } | 7165 | } |
| 7164 | } | 7166 | } |
| 7165 | } | 7167 | } |
| @@ -7170,9 +7172,10 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq) | |||
| 7170 | 7172 | ||
| 7171 | 7173 | ||
| 7172 | /* Initialize HW */ | 7174 | /* Initialize HW */ |
| 7173 | if (bnx2x_function_init(bp, (rc == FW_MSG_CODE_DRV_LOAD_COMMON))) { | 7175 | if (bnx2x_function_init(bp, |
| 7176 | (load_code == FW_MSG_CODE_DRV_LOAD_COMMON))) { | ||
| 7174 | BNX2X_ERR("HW init failed, aborting\n"); | 7177 | BNX2X_ERR("HW init failed, aborting\n"); |
| 7175 | goto out_error; | 7178 | goto load_error; |
| 7176 | } | 7179 | } |
| 7177 | 7180 | ||
| 7178 | 7181 | ||
| @@ -7184,11 +7187,10 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq) | |||
| 7184 | 7187 | ||
| 7185 | /* Send LOAD_DONE command to MCP */ | 7188 | /* Send LOAD_DONE command to MCP */ |
| 7186 | if (!nomcp) { | 7189 | if (!nomcp) { |
| 7187 | rc = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE); | 7190 | load_code = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_DONE); |
| 7188 | DP(NETIF_MSG_IFUP, "rc = 0x%x\n", rc); | 7191 | if (!load_code) { |
| 7189 | if (!rc) { | ||
| 7190 | BNX2X_ERR("MCP response failure, unloading\n"); | 7192 | BNX2X_ERR("MCP response failure, unloading\n"); |
| 7191 | goto int_disable; | 7193 | goto load_int_disable; |
| 7192 | } | 7194 | } |
| 7193 | } | 7195 | } |
| 7194 | 7196 | ||
| @@ -7200,11 +7202,11 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq) | |||
| 7200 | napi_enable(&bnx2x_fp(bp, i, napi)); | 7202 | napi_enable(&bnx2x_fp(bp, i, napi)); |
| 7201 | 7203 | ||
| 7202 | if (bnx2x_setup_leading(bp)) | 7204 | if (bnx2x_setup_leading(bp)) |
| 7203 | goto stop_netif; | 7205 | goto load_stop_netif; |
| 7204 | 7206 | ||
| 7205 | for_each_nondefault_queue(bp, i) | 7207 | for_each_nondefault_queue(bp, i) |
| 7206 | if (bnx2x_setup_multi(bp, i)) | 7208 | if (bnx2x_setup_multi(bp, i)) |
| 7207 | goto stop_netif; | 7209 | goto load_stop_netif; |
| 7208 | 7210 | ||
| 7209 | bnx2x_set_mac_addr(bp); | 7211 | bnx2x_set_mac_addr(bp); |
| 7210 | 7212 | ||
| @@ -7228,42 +7230,24 @@ static int bnx2x_nic_load(struct bnx2x *bp, int req_irq) | |||
| 7228 | 7230 | ||
| 7229 | return 0; | 7231 | return 0; |
| 7230 | 7232 | ||
| 7231 | stop_netif: | 7233 | load_stop_netif: |
| 7232 | for_each_queue(bp, i) | 7234 | for_each_queue(bp, i) |
| 7233 | napi_disable(&bnx2x_fp(bp, i, napi)); | 7235 | napi_disable(&bnx2x_fp(bp, i, napi)); |
| 7234 | 7236 | ||
| 7235 | int_disable: | 7237 | load_int_disable: |
| 7236 | bnx2x_int_disable_sync(bp); | 7238 | bnx2x_int_disable_sync(bp); |
| 7237 | 7239 | ||
| 7238 | bnx2x_free_skbs(bp); | 7240 | bnx2x_free_skbs(bp); |
| 7239 | bnx2x_free_irq(bp); | 7241 | bnx2x_free_irq(bp); |
| 7240 | 7242 | ||
| 7241 | out_error: | 7243 | load_error: |
| 7242 | bnx2x_free_mem(bp); | 7244 | bnx2x_free_mem(bp); |
| 7243 | 7245 | ||
| 7244 | /* TBD we really need to reset the chip | 7246 | /* TBD we really need to reset the chip |
| 7245 | if we want to recover from this */ | 7247 | if we want to recover from this */ |
| 7246 | return rc; | 7248 | return -EBUSY; |
| 7247 | } | 7249 | } |
| 7248 | 7250 | ||
| 7249 | static void bnx2x_netif_stop(struct bnx2x *bp) | ||
| 7250 | { | ||
| 7251 | int i; | ||
| 7252 | |||
| 7253 | bp->rx_mode = BNX2X_RX_MODE_NONE; | ||
| 7254 | bnx2x_set_storm_rx_mode(bp); | ||
| 7255 | |||
| 7256 | bnx2x_int_disable_sync(bp); | ||
| 7257 | bnx2x_link_reset(bp); | ||
| 7258 | |||
| 7259 | for_each_queue(bp, i) | ||
| 7260 | napi_disable(&bnx2x_fp(bp, i, napi)); | ||
| 7261 | |||
| 7262 | if (netif_running(bp->dev)) { | ||
| 7263 | netif_tx_disable(bp->dev); | ||
| 7264 | bp->dev->trans_start = jiffies; /* prevent tx timeout */ | ||
| 7265 | } | ||
| 7266 | } | ||
| 7267 | 7251 | ||
| 7268 | static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code) | 7252 | static void bnx2x_reset_chip(struct bnx2x *bp, u32 reset_code) |
| 7269 | { | 7253 | { |
| @@ -7354,7 +7338,7 @@ static void bnx2x_stop_leading(struct bnx2x *bp) | |||
| 7354 | 7338 | ||
| 7355 | dsb_sp_prod_idx = *bp->dsb_sp_prod; | 7339 | dsb_sp_prod_idx = *bp->dsb_sp_prod; |
| 7356 | 7340 | ||
| 7357 | /* Send CFC_DELETE ramrod */ | 7341 | /* Send PORT_DELETE ramrod */ |
| 7358 | bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_PORT_DEL, 0, 0, 0, 1); | 7342 | bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_PORT_DEL, 0, 0, 0, 1); |
| 7359 | 7343 | ||
| 7360 | /* Wait for completion to arrive on default status block | 7344 | /* Wait for completion to arrive on default status block |
| @@ -7375,35 +7359,48 @@ static void bnx2x_stop_leading(struct bnx2x *bp) | |||
| 7375 | } | 7359 | } |
| 7376 | 7360 | ||
| 7377 | 7361 | ||
| 7378 | static int bnx2x_nic_unload(struct bnx2x *bp, int fre_irq) | 7362 | static int bnx2x_nic_unload(struct bnx2x *bp, int free_irq) |
| 7379 | { | 7363 | { |
| 7380 | u32 reset_code = 0; | 7364 | u32 reset_code = 0; |
| 7381 | int rc; | 7365 | int i, timeout; |
| 7382 | int i; | ||
| 7383 | 7366 | ||
| 7384 | bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT; | 7367 | bp->state = BNX2X_STATE_CLOSING_WAIT4_HALT; |
| 7385 | 7368 | ||
| 7386 | /* Calling flush_scheduled_work() may deadlock because | 7369 | del_timer_sync(&bp->timer); |
| 7387 | * linkwatch_event() may be on the workqueue and it will try to get | ||
| 7388 | * the rtnl_lock which we are holding. | ||
| 7389 | */ | ||
| 7390 | 7370 | ||
| 7391 | while (bp->in_reset_task) | 7371 | bp->rx_mode = BNX2X_RX_MODE_NONE; |
| 7392 | msleep(1); | 7372 | bnx2x_set_storm_rx_mode(bp); |
| 7393 | 7373 | ||
| 7394 | /* Delete the timer: do it before disabling interrupts, as it | 7374 | if (netif_running(bp->dev)) { |
| 7395 | may be still STAT_QUERY ramrod pending after stopping the timer */ | 7375 | netif_tx_disable(bp->dev); |
| 7396 | del_timer_sync(&bp->timer); | 7376 | bp->dev->trans_start = jiffies; /* prevent tx timeout */ |
| 7377 | } | ||
| 7378 | |||
| 7379 | /* Wait until all fast path tasks complete */ | ||
| 7380 | for_each_queue(bp, i) { | ||
| 7381 | struct bnx2x_fastpath *fp = &bp->fp[i]; | ||
| 7382 | |||
| 7383 | timeout = 1000; | ||
| 7384 | while (bnx2x_has_work(fp) && (timeout--)) | ||
| 7385 | msleep(1); | ||
| 7386 | if (!timeout) | ||
| 7387 | BNX2X_ERR("timeout waiting for queue[%d]\n", i); | ||
| 7388 | } | ||
| 7397 | 7389 | ||
| 7398 | /* Wait until stat ramrod returns and all SP tasks complete */ | 7390 | /* Wait until stat ramrod returns and all SP tasks complete */ |
| 7399 | while (bp->stat_pending && (bp->spq_left != MAX_SPQ_PENDING)) | 7391 | timeout = 1000; |
| 7392 | while ((bp->stat_pending || (bp->spq_left != MAX_SPQ_PENDING)) && | ||
| 7393 | (timeout--)) | ||
| 7400 | msleep(1); | 7394 | msleep(1); |
| 7401 | 7395 | ||
| 7402 | /* Stop fast path, disable MAC, disable interrupts, disable napi */ | 7396 | for_each_queue(bp, i) |
| 7403 | bnx2x_netif_stop(bp); | 7397 | napi_disable(&bnx2x_fp(bp, i, napi)); |
| 7398 | /* Disable interrupts after Tx and Rx are disabled on stack level */ | ||
| 7399 | bnx2x_int_disable_sync(bp); | ||
| 7404 | 7400 | ||
| 7405 | if (bp->flags & NO_WOL_FLAG) | 7401 | if (bp->flags & NO_WOL_FLAG) |
| 7406 | reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP; | 7402 | reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP; |
| 7403 | |||
| 7407 | else if (bp->wol) { | 7404 | else if (bp->wol) { |
| 7408 | u32 emac_base = bp->port ? GRCBASE_EMAC0 : GRCBASE_EMAC1; | 7405 | u32 emac_base = bp->port ? GRCBASE_EMAC0 : GRCBASE_EMAC1; |
| 7409 | u8 *mac_addr = bp->dev->dev_addr; | 7406 | u8 *mac_addr = bp->dev->dev_addr; |
| @@ -7420,28 +7417,37 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int fre_irq) | |||
| 7420 | EMAC_WR(EMAC_REG_EMAC_MAC_MATCH + 4, val); | 7417 | EMAC_WR(EMAC_REG_EMAC_MAC_MATCH + 4, val); |
| 7421 | 7418 | ||
| 7422 | reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_EN; | 7419 | reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_EN; |
| 7420 | |||
| 7423 | } else | 7421 | } else |
| 7424 | reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; | 7422 | reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; |
| 7425 | 7423 | ||
| 7424 | /* Close multi and leading connections */ | ||
| 7426 | for_each_nondefault_queue(bp, i) | 7425 | for_each_nondefault_queue(bp, i) |
| 7427 | if (bnx2x_stop_multi(bp, i)) | 7426 | if (bnx2x_stop_multi(bp, i)) |
| 7428 | goto error; | 7427 | goto unload_error; |
| 7429 | |||
| 7430 | 7428 | ||
| 7431 | bnx2x_stop_leading(bp); | 7429 | bnx2x_stop_leading(bp); |
| 7430 | if ((bp->state != BNX2X_STATE_CLOSING_WAIT4_UNLOAD) || | ||
| 7431 | (bp->fp[0].state != BNX2X_FP_STATE_CLOSED)) { | ||
| 7432 | DP(NETIF_MSG_IFDOWN, "failed to close leading properly!" | ||
| 7433 | "state 0x%x fp[0].state 0x%x", | ||
| 7434 | bp->state, bp->fp[0].state); | ||
| 7435 | } | ||
| 7436 | |||
| 7437 | unload_error: | ||
| 7438 | bnx2x_link_reset(bp); | ||
| 7432 | 7439 | ||
| 7433 | error: | ||
| 7434 | if (!nomcp) | 7440 | if (!nomcp) |
| 7435 | rc = bnx2x_fw_command(bp, reset_code); | 7441 | reset_code = bnx2x_fw_command(bp, reset_code); |
| 7436 | else | 7442 | else |
| 7437 | rc = FW_MSG_CODE_DRV_UNLOAD_COMMON; | 7443 | reset_code = FW_MSG_CODE_DRV_UNLOAD_COMMON; |
| 7438 | 7444 | ||
| 7439 | /* Release IRQs */ | 7445 | /* Release IRQs */ |
| 7440 | if (fre_irq) | 7446 | if (free_irq) |
| 7441 | bnx2x_free_irq(bp); | 7447 | bnx2x_free_irq(bp); |
| 7442 | 7448 | ||
| 7443 | /* Reset the chip */ | 7449 | /* Reset the chip */ |
| 7444 | bnx2x_reset_chip(bp, rc); | 7450 | bnx2x_reset_chip(bp, reset_code); |
| 7445 | 7451 | ||
| 7446 | /* Report UNLOAD_DONE to MCP */ | 7452 | /* Report UNLOAD_DONE to MCP */ |
| 7447 | if (!nomcp) | 7453 | if (!nomcp) |
| @@ -7452,8 +7458,7 @@ error: | |||
| 7452 | bnx2x_free_mem(bp); | 7458 | bnx2x_free_mem(bp); |
| 7453 | 7459 | ||
| 7454 | bp->state = BNX2X_STATE_CLOSED; | 7460 | bp->state = BNX2X_STATE_CLOSED; |
| 7455 | /* Set link down */ | 7461 | |
| 7456 | bp->link_up = 0; | ||
| 7457 | netif_carrier_off(bp->dev); | 7462 | netif_carrier_off(bp->dev); |
| 7458 | 7463 | ||
| 7459 | return 0; | 7464 | return 0; |
| @@ -9468,16 +9473,13 @@ static int bnx2x_open(struct net_device *dev) | |||
| 9468 | /* Called with rtnl_lock */ | 9473 | /* Called with rtnl_lock */ |
| 9469 | static int bnx2x_close(struct net_device *dev) | 9474 | static int bnx2x_close(struct net_device *dev) |
| 9470 | { | 9475 | { |
| 9471 | int rc; | ||
| 9472 | struct bnx2x *bp = netdev_priv(dev); | 9476 | struct bnx2x *bp = netdev_priv(dev); |
| 9473 | 9477 | ||
| 9474 | /* Unload the driver, release IRQs */ | 9478 | /* Unload the driver, release IRQs */ |
| 9475 | rc = bnx2x_nic_unload(bp, 1); | 9479 | bnx2x_nic_unload(bp, 1); |
| 9476 | if (rc) { | 9480 | |
| 9477 | BNX2X_ERR("bnx2x_nic_unload failed: %d\n", rc); | 9481 | if (!CHIP_REV_IS_SLOW(bp)) |
| 9478 | return rc; | 9482 | bnx2x_set_power_state(bp, PCI_D3hot); |
| 9479 | } | ||
| 9480 | bnx2x_set_power_state(bp, PCI_D3hot); | ||
| 9481 | 9483 | ||
| 9482 | return 0; | 9484 | return 0; |
| 9483 | } | 9485 | } |
| @@ -9620,14 +9622,18 @@ static void bnx2x_reset_task(struct work_struct *work) | |||
| 9620 | if (!netif_running(bp->dev)) | 9622 | if (!netif_running(bp->dev)) |
| 9621 | return; | 9623 | return; |
| 9622 | 9624 | ||
| 9623 | bp->in_reset_task = 1; | 9625 | rtnl_lock(); |
| 9624 | 9626 | ||
| 9625 | bnx2x_netif_stop(bp); | 9627 | if (bp->state != BNX2X_STATE_OPEN) { |
| 9628 | DP(NETIF_MSG_TX_ERR, "state is %x, returning\n", bp->state); | ||
| 9629 | goto reset_task_exit; | ||
| 9630 | } | ||
| 9626 | 9631 | ||
| 9627 | bnx2x_nic_unload(bp, 0); | 9632 | bnx2x_nic_unload(bp, 0); |
| 9628 | bnx2x_nic_load(bp, 0); | 9633 | bnx2x_nic_load(bp, 0); |
| 9629 | 9634 | ||
| 9630 | bp->in_reset_task = 0; | 9635 | reset_task_exit: |
| 9636 | rtnl_unlock(); | ||
| 9631 | } | 9637 | } |
| 9632 | 9638 | ||
| 9633 | static int __devinit bnx2x_init_board(struct pci_dev *pdev, | 9639 | static int __devinit bnx2x_init_board(struct pci_dev *pdev, |
| @@ -9708,8 +9714,6 @@ static int __devinit bnx2x_init_board(struct pci_dev *pdev, | |||
| 9708 | 9714 | ||
| 9709 | spin_lock_init(&bp->phy_lock); | 9715 | spin_lock_init(&bp->phy_lock); |
| 9710 | 9716 | ||
| 9711 | bp->in_reset_task = 0; | ||
| 9712 | |||
| 9713 | INIT_WORK(&bp->reset_task, bnx2x_reset_task); | 9717 | INIT_WORK(&bp->reset_task, bnx2x_reset_task); |
| 9714 | INIT_WORK(&bp->sp_task, bnx2x_sp_task); | 9718 | INIT_WORK(&bp->sp_task, bnx2x_sp_task); |
| 9715 | 9719 | ||
| @@ -9916,10 +9920,16 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev, | |||
| 9916 | static void __devexit bnx2x_remove_one(struct pci_dev *pdev) | 9920 | static void __devexit bnx2x_remove_one(struct pci_dev *pdev) |
| 9917 | { | 9921 | { |
| 9918 | struct net_device *dev = pci_get_drvdata(pdev); | 9922 | struct net_device *dev = pci_get_drvdata(pdev); |
| 9919 | struct bnx2x *bp = netdev_priv(dev); | 9923 | struct bnx2x *bp; |
| 9924 | |||
| 9925 | if (!dev) { | ||
| 9926 | /* we get here if init_one() fails */ | ||
| 9927 | printk(KERN_ERR PFX "BAD net device from bnx2x_init_one\n"); | ||
| 9928 | return; | ||
| 9929 | } | ||
| 9930 | |||
| 9931 | bp = netdev_priv(dev); | ||
| 9920 | 9932 | ||
| 9921 | flush_scheduled_work(); | ||
| 9922 | /*tasklet_kill(&bp->sp_task);*/ | ||
| 9923 | unregister_netdev(dev); | 9933 | unregister_netdev(dev); |
| 9924 | 9934 | ||
| 9925 | if (bp->regview) | 9935 | if (bp->regview) |
| @@ -9937,34 +9947,43 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev) | |||
| 9937 | static int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state) | 9947 | static int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state) |
| 9938 | { | 9948 | { |
| 9939 | struct net_device *dev = pci_get_drvdata(pdev); | 9949 | struct net_device *dev = pci_get_drvdata(pdev); |
| 9940 | struct bnx2x *bp = netdev_priv(dev); | 9950 | struct bnx2x *bp; |
| 9941 | int rc; | 9951 | |
| 9952 | if (!dev) | ||
| 9953 | return 0; | ||
| 9942 | 9954 | ||
| 9943 | if (!netif_running(dev)) | 9955 | if (!netif_running(dev)) |
| 9944 | return 0; | 9956 | return 0; |
| 9945 | 9957 | ||
| 9946 | rc = bnx2x_nic_unload(bp, 0); | 9958 | bp = netdev_priv(dev); |
| 9947 | if (!rc) | 9959 | |
| 9948 | return rc; | 9960 | bnx2x_nic_unload(bp, 0); |
| 9949 | 9961 | ||
| 9950 | netif_device_detach(dev); | 9962 | netif_device_detach(dev); |
| 9951 | pci_save_state(pdev); | ||
| 9952 | 9963 | ||
| 9964 | pci_save_state(pdev); | ||
| 9953 | bnx2x_set_power_state(bp, pci_choose_state(pdev, state)); | 9965 | bnx2x_set_power_state(bp, pci_choose_state(pdev, state)); |
| 9966 | |||
| 9954 | return 0; | 9967 | return 0; |
| 9955 | } | 9968 | } |
| 9956 | 9969 | ||
| 9957 | static int bnx2x_resume(struct pci_dev *pdev) | 9970 | static int bnx2x_resume(struct pci_dev *pdev) |
| 9958 | { | 9971 | { |
| 9959 | struct net_device *dev = pci_get_drvdata(pdev); | 9972 | struct net_device *dev = pci_get_drvdata(pdev); |
| 9960 | struct bnx2x *bp = netdev_priv(dev); | 9973 | struct bnx2x *bp; |
| 9961 | int rc; | 9974 | int rc; |
| 9962 | 9975 | ||
| 9976 | if (!dev) { | ||
| 9977 | printk(KERN_ERR PFX "BAD net device from bnx2x_init_one\n"); | ||
| 9978 | return -ENODEV; | ||
| 9979 | } | ||
| 9980 | |||
| 9963 | if (!netif_running(dev)) | 9981 | if (!netif_running(dev)) |
| 9964 | return 0; | 9982 | return 0; |
| 9965 | 9983 | ||
| 9966 | pci_restore_state(pdev); | 9984 | bp = netdev_priv(dev); |
| 9967 | 9985 | ||
| 9986 | pci_restore_state(pdev); | ||
| 9968 | bnx2x_set_power_state(bp, PCI_D0); | 9987 | bnx2x_set_power_state(bp, PCI_D0); |
| 9969 | netif_device_attach(dev); | 9988 | netif_device_attach(dev); |
| 9970 | 9989 | ||
diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index e2a36e850fc2..6a86afbc7525 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h | |||
| @@ -545,8 +545,6 @@ struct bnx2x { | |||
| 545 | spinlock_t phy_lock; | 545 | spinlock_t phy_lock; |
| 546 | 546 | ||
| 547 | struct work_struct reset_task; | 547 | struct work_struct reset_task; |
| 548 | u16 in_reset_task; | ||
| 549 | |||
| 550 | struct work_struct sp_task; | 548 | struct work_struct sp_task; |
| 551 | 549 | ||
| 552 | struct timer_list timer; | 550 | struct timer_list timer; |
| @@ -560,7 +558,6 @@ struct bnx2x { | |||
| 560 | #define CHIP_ID(bp) (((bp)->chip_id) & 0xfffffff0) | 558 | #define CHIP_ID(bp) (((bp)->chip_id) & 0xfffffff0) |
| 561 | 559 | ||
| 562 | #define CHIP_NUM(bp) (((bp)->chip_id) & 0xffff0000) | 560 | #define CHIP_NUM(bp) (((bp)->chip_id) & 0xffff0000) |
| 563 | #define CHIP_NUM_5710 0x57100000 | ||
| 564 | 561 | ||
| 565 | #define CHIP_REV(bp) (((bp)->chip_id) & 0x0000f000) | 562 | #define CHIP_REV(bp) (((bp)->chip_id) & 0x0000f000) |
| 566 | #define CHIP_REV_Ax 0x00000000 | 563 | #define CHIP_REV_Ax 0x00000000 |
