aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/cxgb3/cxgb3_offload.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/cxgb3/cxgb3_offload.c')
-rw-r--r--drivers/net/cxgb3/cxgb3_offload.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
index 805076c54f1b..da5a5d9b8aff 100644
--- a/drivers/net/cxgb3/cxgb3_offload.c
+++ b/drivers/net/cxgb3/cxgb3_offload.c
@@ -1146,12 +1146,14 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new)
1146 if (te && te->ctx && te->client && te->client->redirect) { 1146 if (te && te->ctx && te->client && te->client->redirect) {
1147 update_tcb = te->client->redirect(te->ctx, old, new, e); 1147 update_tcb = te->client->redirect(te->ctx, old, new, e);
1148 if (update_tcb) { 1148 if (update_tcb) {
1149 rcu_read_lock();
1149 l2t_hold(L2DATA(tdev), e); 1150 l2t_hold(L2DATA(tdev), e);
1151 rcu_read_unlock();
1150 set_l2t_ix(tdev, tid, e); 1152 set_l2t_ix(tdev, tid, e);
1151 } 1153 }
1152 } 1154 }
1153 } 1155 }
1154 l2t_release(L2DATA(tdev), e); 1156 l2t_release(tdev, e);
1155} 1157}
1156 1158
1157/* 1159/*
@@ -1264,7 +1266,7 @@ int cxgb3_offload_activate(struct adapter *adapter)
1264 goto out_free; 1266 goto out_free;
1265 1267
1266 err = -ENOMEM; 1268 err = -ENOMEM;
1267 L2DATA(dev) = t3_init_l2t(l2t_capacity); 1269 RCU_INIT_POINTER(dev->l2opt, t3_init_l2t(l2t_capacity));
1268 if (!L2DATA(dev)) 1270 if (!L2DATA(dev))
1269 goto out_free; 1271 goto out_free;
1270 1272
@@ -1298,16 +1300,24 @@ int cxgb3_offload_activate(struct adapter *adapter)
1298 1300
1299out_free_l2t: 1301out_free_l2t:
1300 t3_free_l2t(L2DATA(dev)); 1302 t3_free_l2t(L2DATA(dev));
1301 L2DATA(dev) = NULL; 1303 rcu_assign_pointer(dev->l2opt, NULL);
1302out_free: 1304out_free:
1303 kfree(t); 1305 kfree(t);
1304 return err; 1306 return err;
1305} 1307}
1306 1308
1309static void clean_l2_data(struct rcu_head *head)
1310{
1311 struct l2t_data *d = container_of(head, struct l2t_data, rcu_head);
1312 t3_free_l2t(d);
1313}
1314
1315
1307void cxgb3_offload_deactivate(struct adapter *adapter) 1316void cxgb3_offload_deactivate(struct adapter *adapter)
1308{ 1317{
1309 struct t3cdev *tdev = &adapter->tdev; 1318 struct t3cdev *tdev = &adapter->tdev;
1310 struct t3c_data *t = T3C_DATA(tdev); 1319 struct t3c_data *t = T3C_DATA(tdev);
1320 struct l2t_data *d;
1311 1321
1312 remove_adapter(adapter); 1322 remove_adapter(adapter);
1313 if (list_empty(&adapter_list)) 1323 if (list_empty(&adapter_list))
@@ -1315,8 +1325,11 @@ void cxgb3_offload_deactivate(struct adapter *adapter)
1315 1325
1316 free_tid_maps(&t->tid_maps); 1326 free_tid_maps(&t->tid_maps);
1317 T3C_DATA(tdev) = NULL; 1327 T3C_DATA(tdev) = NULL;
1318 t3_free_l2t(L2DATA(tdev)); 1328 rcu_read_lock();
1319 L2DATA(tdev) = NULL; 1329 d = L2DATA(tdev);
1330 rcu_read_unlock();
1331 rcu_assign_pointer(tdev->l2opt, NULL);
1332 call_rcu(&d->rcu_head, clean_l2_data);
1320 if (t->nofail_skb) 1333 if (t->nofail_skb)
1321 kfree_skb(t->nofail_skb); 1334 kfree_skb(t->nofail_skb);
1322 kfree(t); 1335 kfree(t);