diff options
author | Faisal Latif <faisal.latif@intel.com> | 2010-07-03 20:17:59 -0400 |
---|---|---|
committer | Roland Dreier <rolandd@cisco.com> | 2010-07-28 18:14:27 -0400 |
commit | cd6860eb036ab4320d591fdd056f86172438fae4 (patch) | |
tree | 8c787e118cb85a6014a8d5771f9b7dbab75708f8 /drivers | |
parent | 0eec495ee69e3fbbe2ef2b244a0a988a4fe2e887 (diff) |
RDMA/nes: Fix hangs on ifdown
When ib_unregister_device() is called from netdev stop during ifdown,
it sometimes hangs. Changes made to indicate port_err to ib_dispatch_event()
during netdev stop and port_active during netdev open. The
ib_unregister_device() is only called during remove of the module.
Signed-off-by: Faisal Latif <faisal.latif@intel.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/infiniband/hw/nes/nes.h | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes_hw.c | 12 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes_nic.c | 13 | ||||
-rw-r--r-- | drivers/infiniband/hw/nes/nes_verbs.c | 12 |
4 files changed, 33 insertions, 6 deletions
diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index cc78fee1dd51..b3d145e82b4c 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h | |||
@@ -262,6 +262,7 @@ struct nes_device { | |||
262 | u16 base_doorbell_index; | 262 | u16 base_doorbell_index; |
263 | u16 currcq_count; | 263 | u16 currcq_count; |
264 | u16 deepcq_count; | 264 | u16 deepcq_count; |
265 | u8 iw_status; | ||
265 | u8 msi_enabled; | 266 | u8 msi_enabled; |
266 | u8 netdev_count; | 267 | u8 netdev_count; |
267 | u8 napi_isr_ran; | 268 | u8 napi_isr_ran; |
@@ -527,6 +528,7 @@ void nes_cm_disconn_worker(void *); | |||
527 | int nes_hw_modify_qp(struct nes_device *, struct nes_qp *, u32, u32, u32); | 528 | int nes_hw_modify_qp(struct nes_device *, struct nes_qp *, u32, u32, u32); |
528 | int nes_modify_qp(struct ib_qp *, struct ib_qp_attr *, int, struct ib_udata *); | 529 | int nes_modify_qp(struct ib_qp *, struct ib_qp_attr *, int, struct ib_udata *); |
529 | struct nes_ib_device *nes_init_ofa_device(struct net_device *); | 530 | struct nes_ib_device *nes_init_ofa_device(struct net_device *); |
531 | void nes_port_ibevent(struct nes_vnic *nesvnic); | ||
530 | void nes_destroy_ofa_device(struct nes_ib_device *); | 532 | void nes_destroy_ofa_device(struct nes_ib_device *); |
531 | int nes_register_ofa_device(struct nes_ib_device *); | 533 | int nes_register_ofa_device(struct nes_ib_device *); |
532 | 534 | ||
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index f41d890956a1..199107abf195 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c | |||
@@ -3283,9 +3283,15 @@ static void nes_terminate_connection(struct nes_device *nesdev, struct nes_qp *n | |||
3283 | else | 3283 | else |
3284 | mod_qp_flags |= NES_CQP_QP_TERM_DONT_SEND_TERM_MSG; | 3284 | mod_qp_flags |= NES_CQP_QP_TERM_DONT_SEND_TERM_MSG; |
3285 | 3285 | ||
3286 | nes_terminate_start_timer(nesqp); | 3286 | if (!nesdev->iw_status) { |
3287 | nesqp->term_flags |= NES_TERM_SENT; | 3287 | nesqp->term_flags = NES_TERM_DONE; |
3288 | nes_hw_modify_qp(nesdev, nesqp, mod_qp_flags, termlen, 0); | 3288 | nes_hw_modify_qp(nesdev, nesqp, NES_CQP_QP_IWARP_STATE_ERROR, 0, 0); |
3289 | nes_cm_disconn(nesqp); | ||
3290 | } else { | ||
3291 | nes_terminate_start_timer(nesqp); | ||
3292 | nesqp->term_flags |= NES_TERM_SENT; | ||
3293 | nes_hw_modify_qp(nesdev, nesqp, mod_qp_flags, termlen, 0); | ||
3294 | } | ||
3289 | } | 3295 | } |
3290 | 3296 | ||
3291 | static void nes_terminate_send_fin(struct nes_device *nesdev, | 3297 | static void nes_terminate_send_fin(struct nes_device *nesdev, |
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index 5cc0a9ae5bb1..c0c404ee3bc4 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c | |||
@@ -232,6 +232,13 @@ static int nes_netdev_open(struct net_device *netdev) | |||
232 | NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR)); | 232 | NES_MAC_INT_TX_UNDERFLOW | NES_MAC_INT_TX_ERROR)); |
233 | first_nesvnic = nesvnic; | 233 | first_nesvnic = nesvnic; |
234 | } | 234 | } |
235 | |||
236 | if (nesvnic->of_device_registered) { | ||
237 | nesdev->iw_status = 1; | ||
238 | nesdev->nesadapter->send_term_ok = 1; | ||
239 | nes_port_ibevent(nesvnic); | ||
240 | } | ||
241 | |||
235 | if (first_nesvnic->linkup) { | 242 | if (first_nesvnic->linkup) { |
236 | /* Enable network packets */ | 243 | /* Enable network packets */ |
237 | nesvnic->linkup = 1; | 244 | nesvnic->linkup = 1; |
@@ -309,9 +316,9 @@ static int nes_netdev_stop(struct net_device *netdev) | |||
309 | 316 | ||
310 | 317 | ||
311 | if (nesvnic->of_device_registered) { | 318 | if (nesvnic->of_device_registered) { |
312 | nes_destroy_ofa_device(nesvnic->nesibdev); | 319 | nesdev->nesadapter->send_term_ok = 0; |
313 | nesvnic->nesibdev = NULL; | 320 | nesdev->iw_status = 0; |
314 | nesvnic->of_device_registered = 0; | 321 | nes_port_ibevent(nesvnic); |
315 | } | 322 | } |
316 | nes_destroy_nic_qp(nesvnic); | 323 | nes_destroy_nic_qp(nesvnic); |
317 | 324 | ||
diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 9bc2d744b2ea..3b95d0473b70 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c | |||
@@ -3058,6 +3058,7 @@ int nes_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, | |||
3058 | nesqp->hte_added = 0; | 3058 | nesqp->hte_added = 0; |
3059 | } | 3059 | } |
3060 | if ((nesqp->hw_tcp_state > NES_AEQE_TCP_STATE_CLOSED) && | 3060 | if ((nesqp->hw_tcp_state > NES_AEQE_TCP_STATE_CLOSED) && |
3061 | (nesdev->iw_status) && | ||
3061 | (nesqp->hw_tcp_state != NES_AEQE_TCP_STATE_TIME_WAIT)) { | 3062 | (nesqp->hw_tcp_state != NES_AEQE_TCP_STATE_TIME_WAIT)) { |
3062 | next_iwarp_state |= NES_CQP_QP_RESET; | 3063 | next_iwarp_state |= NES_CQP_QP_RESET; |
3063 | } else { | 3064 | } else { |
@@ -3936,6 +3937,17 @@ struct nes_ib_device *nes_init_ofa_device(struct net_device *netdev) | |||
3936 | return nesibdev; | 3937 | return nesibdev; |
3937 | } | 3938 | } |
3938 | 3939 | ||
3940 | void nes_port_ibevent(struct nes_vnic *nesvnic) | ||
3941 | { | ||
3942 | struct nes_ib_device *nesibdev = nesvnic->nesibdev; | ||
3943 | struct nes_device *nesdev = nesvnic->nesdev; | ||
3944 | struct ib_event event; | ||
3945 | event.device = &nesibdev->ibdev; | ||
3946 | event.element.port_num = nesvnic->logical_port + 1; | ||
3947 | event.event = nesdev->iw_status ? IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR; | ||
3948 | ib_dispatch_event(&event); | ||
3949 | } | ||
3950 | |||
3939 | 3951 | ||
3940 | /** | 3952 | /** |
3941 | * nes_destroy_ofa_device | 3953 | * nes_destroy_ofa_device |