Commit db7019557cb48508f3ff9d6b40c2e967702897a6

Authored by Ido Schimmel
Committed by David S. Miller
1 parent c1bb279cfa

rocker: Implement FIB offload in deferred work

Convert rocker to offload FIBs in deferred work in a similar fashion to
mlxsw, which was converted in the previous commits.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 2 changed files with 51 additions and 8 deletions Side-by-side Diff

drivers/net/ethernet/rocker/rocker_main.c
... ... @@ -2166,28 +2166,70 @@
2166 2166 .switchdev_port_obj_dump = rocker_port_obj_dump,
2167 2167 };
2168 2168  
2169   -static int rocker_router_fib_event(struct notifier_block *nb,
2170   - unsigned long event, void *ptr)
  2169 +struct rocker_fib_event_work {
  2170 + struct work_struct work;
  2171 + struct fib_entry_notifier_info fen_info;
  2172 + struct rocker *rocker;
  2173 + unsigned long event;
  2174 +};
  2175 +
  2176 +static void rocker_router_fib_event_work(struct work_struct *work)
2171 2177 {
2172   - struct rocker *rocker = container_of(nb, struct rocker, fib_nb);
2173   - struct fib_entry_notifier_info *fen_info = ptr;
  2178 + struct rocker_fib_event_work *fib_work =
  2179 + container_of(work, struct rocker_fib_event_work, work);
  2180 + struct rocker *rocker = fib_work->rocker;
2174 2181 int err;
2175 2182  
2176   - switch (event) {
  2183 + /* Protect internal structures from changes */
  2184 + rtnl_lock();
  2185 + switch (fib_work->event) {
2177 2186 case FIB_EVENT_ENTRY_ADD:
2178   - err = rocker_world_fib4_add(rocker, fen_info);
  2187 + err = rocker_world_fib4_add(rocker, &fib_work->fen_info);
2179 2188 if (err)
2180 2189 rocker_world_fib4_abort(rocker);
2181   - else
  2190 + fib_info_put(fib_work->fen_info.fi);
2182 2191 break;
2183 2192 case FIB_EVENT_ENTRY_DEL:
2184   - rocker_world_fib4_del(rocker, fen_info);
  2193 + rocker_world_fib4_del(rocker, &fib_work->fen_info);
  2194 + fib_info_put(fib_work->fen_info.fi);
2185 2195 break;
2186 2196 case FIB_EVENT_RULE_ADD: /* fall through */
2187 2197 case FIB_EVENT_RULE_DEL:
2188 2198 rocker_world_fib4_abort(rocker);
2189 2199 break;
2190 2200 }
  2201 + rtnl_unlock();
  2202 + kfree(fib_work);
  2203 +}
  2204 +
  2205 +/* Called with rcu_read_lock() */
  2206 +static int rocker_router_fib_event(struct notifier_block *nb,
  2207 + unsigned long event, void *ptr)
  2208 +{
  2209 + struct rocker *rocker = container_of(nb, struct rocker, fib_nb);
  2210 + struct rocker_fib_event_work *fib_work;
  2211 +
  2212 + fib_work = kzalloc(sizeof(*fib_work), GFP_ATOMIC);
  2213 + if (WARN_ON(!fib_work))
  2214 + return NOTIFY_BAD;
  2215 +
  2216 + INIT_WORK(&fib_work->work, rocker_router_fib_event_work);
  2217 + fib_work->rocker = rocker;
  2218 + fib_work->event = event;
  2219 +
  2220 + switch (event) {
  2221 + case FIB_EVENT_ENTRY_ADD: /* fall through */
  2222 + case FIB_EVENT_ENTRY_DEL:
  2223 + memcpy(&fib_work->fen_info, ptr, sizeof(fib_work->fen_info));
  2224 + /* Take referece on fib_info to prevent it from being
  2225 + * freed while work is queued. Release it afterwards.
  2226 + */
  2227 + fib_info_hold(fib_work->fen_info.fi);
  2228 + break;
  2229 + }
  2230 +
  2231 + queue_work(rocker->rocker_owq, &fib_work->work);
  2232 +
2191 2233 return NOTIFY_DONE;
2192 2234 }
2193 2235  
drivers/net/ethernet/rocker/rocker_ofdpa.c
... ... @@ -2516,6 +2516,7 @@
2516 2516 int bkt;
2517 2517  
2518 2518 del_timer_sync(&ofdpa->fdb_cleanup_timer);
  2519 + flush_workqueue(rocker->rocker_owq);
2519 2520  
2520 2521 spin_lock_irqsave(&ofdpa->flow_tbl_lock, flags);
2521 2522 hash_for_each_safe(ofdpa->flow_tbl, bkt, tmp, flow_entry, entry)