aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTadeusz Struk <tadeusz.struk@intel.com>2016-07-06 17:14:47 -0400
committerDoug Ledford <dledford@redhat.com>2016-07-12 10:46:24 -0400
commit98f179a5eaf77eaac49df3d0c217c6eaaba8c0db (patch)
tree4b15d13bca8be3cb662896164d3bf04bac91ede9
parent896ce45da2c2f4abc508d443fdecde7de0b3fa7e (diff)
IB/hfi1: Fix sleep inside atomic issue in init_asic_data
The critical section should protect only the list traversal and dd->asic_data modification, not the memory allocation. The fix pulls the allocation out of the critical section. Reviewed-by: Dennis Dalessandro <dennis.dalessandro@intel.com> Reviewed-by: Sebastian Sanchez <sebastian.sanchez@intel.com> Reviewed-by: Dean Luick <dean.luick@intel.com> Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com> Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com> Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/hw/hfi1/chip.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c
index f5de85178055..dad4d0ebbdff 100644
--- a/drivers/infiniband/hw/hfi1/chip.c
+++ b/drivers/infiniband/hw/hfi1/chip.c
@@ -14113,8 +14113,14 @@ static int init_asic_data(struct hfi1_devdata *dd)
14113{ 14113{
14114 unsigned long flags; 14114 unsigned long flags;
14115 struct hfi1_devdata *tmp, *peer = NULL; 14115 struct hfi1_devdata *tmp, *peer = NULL;
14116 struct hfi1_asic_data *asic_data;
14116 int ret = 0; 14117 int ret = 0;
14117 14118
14119 /* pre-allocate the asic structure in case we are the first device */
14120 asic_data = kzalloc(sizeof(*dd->asic_data), GFP_KERNEL);
14121 if (!asic_data)
14122 return -ENOMEM;
14123
14118 spin_lock_irqsave(&hfi1_devs_lock, flags); 14124 spin_lock_irqsave(&hfi1_devs_lock, flags);
14119 /* Find our peer device */ 14125 /* Find our peer device */
14120 list_for_each_entry(tmp, &hfi1_dev_list, list) { 14126 list_for_each_entry(tmp, &hfi1_dev_list, list) {
@@ -14126,18 +14132,14 @@ static int init_asic_data(struct hfi1_devdata *dd)
14126 } 14132 }
14127 14133
14128 if (peer) { 14134 if (peer) {
14135 /* use already allocated structure */
14129 dd->asic_data = peer->asic_data; 14136 dd->asic_data = peer->asic_data;
14137 kfree(asic_data);
14130 } else { 14138 } else {
14131 dd->asic_data = kzalloc(sizeof(*dd->asic_data), GFP_KERNEL); 14139 dd->asic_data = asic_data;
14132 if (!dd->asic_data) {
14133 ret = -ENOMEM;
14134 goto done;
14135 }
14136 mutex_init(&dd->asic_data->asic_resource_mutex); 14140 mutex_init(&dd->asic_data->asic_resource_mutex);
14137 } 14141 }
14138 dd->asic_data->dds[dd->hfi1_id] = dd; /* self back-pointer */ 14142 dd->asic_data->dds[dd->hfi1_id] = dd; /* self back-pointer */
14139
14140done:
14141 spin_unlock_irqrestore(&hfi1_devs_lock, flags); 14143 spin_unlock_irqrestore(&hfi1_devs_lock, flags);
14142 return ret; 14144 return ret;
14143} 14145}