diff options
author | Jon Mason <jon.mason@intel.com> | 2013-01-19 04:02:19 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-01-20 18:45:51 -0500 |
commit | 7b4f2d3c3b8285fe63cae6b92c7b7030d1d1aa7c (patch) | |
tree | c333b933cbedd409b8ed2c3b668d7134d707c3c8 /drivers/ntb | |
parent | ef114ed5064d35982c16f5cbb338fb586ef48bf7 (diff) |
NTB: No sleeping in interrupt context
Move all cancel_delayed_work_sync to a work thread to prevent sleeping
in interrupt context (when the NTB link goes down). Caught via
'Sleep inside atomic section checking'
Signed-off-by: Jon Mason <jon.mason@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/ntb')
-rw-r--r-- | drivers/ntb/ntb_transport.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c index 2823087a1338..bf7ade14c742 100644 --- a/drivers/ntb/ntb_transport.c +++ b/drivers/ntb/ntb_transport.c | |||
@@ -110,6 +110,7 @@ struct ntb_transport_qp { | |||
110 | 110 | ||
111 | void (*event_handler) (void *data, int status); | 111 | void (*event_handler) (void *data, int status); |
112 | struct delayed_work link_work; | 112 | struct delayed_work link_work; |
113 | struct work_struct link_cleanup; | ||
113 | 114 | ||
114 | struct dentry *debugfs_dir; | 115 | struct dentry *debugfs_dir; |
115 | struct dentry *debugfs_stats; | 116 | struct dentry *debugfs_stats; |
@@ -148,6 +149,7 @@ struct ntb_transport { | |||
148 | unsigned long qp_bitmap; | 149 | unsigned long qp_bitmap; |
149 | bool transport_link; | 150 | bool transport_link; |
150 | struct delayed_work link_work; | 151 | struct delayed_work link_work; |
152 | struct work_struct link_cleanup; | ||
151 | struct dentry *debugfs_dir; | 153 | struct dentry *debugfs_dir; |
152 | }; | 154 | }; |
153 | 155 | ||
@@ -510,8 +512,11 @@ static int ntb_set_mw(struct ntb_transport *nt, int num_mw, unsigned int size) | |||
510 | return 0; | 512 | return 0; |
511 | } | 513 | } |
512 | 514 | ||
513 | static void ntb_qp_link_down(struct ntb_transport_qp *qp) | 515 | static void ntb_qp_link_cleanup(struct work_struct *work) |
514 | { | 516 | { |
517 | struct ntb_transport_qp *qp = container_of(work, | ||
518 | struct ntb_transport_qp, | ||
519 | link_cleanup); | ||
515 | struct ntb_transport *nt = qp->transport; | 520 | struct ntb_transport *nt = qp->transport; |
516 | struct pci_dev *pdev = ntb_query_pdev(nt->ndev); | 521 | struct pci_dev *pdev = ntb_query_pdev(nt->ndev); |
517 | 522 | ||
@@ -531,8 +536,15 @@ static void ntb_qp_link_down(struct ntb_transport_qp *qp) | |||
531 | msecs_to_jiffies(NTB_LINK_DOWN_TIMEOUT)); | 536 | msecs_to_jiffies(NTB_LINK_DOWN_TIMEOUT)); |
532 | } | 537 | } |
533 | 538 | ||
534 | static void ntb_transport_conn_down(struct ntb_transport *nt) | 539 | static void ntb_qp_link_down(struct ntb_transport_qp *qp) |
540 | { | ||
541 | schedule_work(&qp->link_cleanup); | ||
542 | } | ||
543 | |||
544 | static void ntb_transport_link_cleanup(struct work_struct *work) | ||
535 | { | 545 | { |
546 | struct ntb_transport *nt = container_of(work, struct ntb_transport, | ||
547 | link_cleanup); | ||
536 | int i; | 548 | int i; |
537 | 549 | ||
538 | if (nt->transport_link == NTB_LINK_DOWN) | 550 | if (nt->transport_link == NTB_LINK_DOWN) |
@@ -562,7 +574,7 @@ static void ntb_transport_event_callback(void *data, enum ntb_hw_event event) | |||
562 | schedule_delayed_work(&nt->link_work, 0); | 574 | schedule_delayed_work(&nt->link_work, 0); |
563 | break; | 575 | break; |
564 | case NTB_EVENT_HW_LINK_DOWN: | 576 | case NTB_EVENT_HW_LINK_DOWN: |
565 | ntb_transport_conn_down(nt); | 577 | schedule_work(&nt->link_cleanup); |
566 | break; | 578 | break; |
567 | default: | 579 | default: |
568 | BUG(); | 580 | BUG(); |
@@ -769,6 +781,7 @@ static void ntb_transport_init_queue(struct ntb_transport *nt, | |||
769 | } | 781 | } |
770 | 782 | ||
771 | INIT_DELAYED_WORK(&qp->link_work, ntb_qp_link_work); | 783 | INIT_DELAYED_WORK(&qp->link_work, ntb_qp_link_work); |
784 | INIT_WORK(&qp->link_cleanup, ntb_qp_link_cleanup); | ||
772 | 785 | ||
773 | spin_lock_init(&qp->ntb_rx_pend_q_lock); | 786 | spin_lock_init(&qp->ntb_rx_pend_q_lock); |
774 | spin_lock_init(&qp->ntb_rx_free_q_lock); | 787 | spin_lock_init(&qp->ntb_rx_free_q_lock); |
@@ -814,6 +827,7 @@ int ntb_transport_init(struct pci_dev *pdev) | |||
814 | ntb_transport_init_queue(nt, i); | 827 | ntb_transport_init_queue(nt, i); |
815 | 828 | ||
816 | INIT_DELAYED_WORK(&nt->link_work, ntb_transport_link_work); | 829 | INIT_DELAYED_WORK(&nt->link_work, ntb_transport_link_work); |
830 | INIT_WORK(&nt->link_cleanup, ntb_transport_link_cleanup); | ||
817 | 831 | ||
818 | rc = ntb_register_event_callback(nt->ndev, | 832 | rc = ntb_register_event_callback(nt->ndev, |
819 | ntb_transport_event_callback); | 833 | ntb_transport_event_callback); |