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 | |
| 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>
| -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 |
