| .. | .. |
|---|
| 14 | 14 | |
|---|
| 15 | 15 | /* dev is yet to be added to the port list. */ |
|---|
| 16 | 16 | list_for_each_entry(p, &br->port_list, list) { |
|---|
| 17 | | - if (switchdev_port_same_parent_id(dev, p->dev)) |
|---|
| 17 | + if (netdev_port_same_parent_id(dev, p->dev)) |
|---|
| 18 | 18 | return p->offload_fwd_mark; |
|---|
| 19 | 19 | } |
|---|
| 20 | 20 | |
|---|
| .. | .. |
|---|
| 23 | 23 | |
|---|
| 24 | 24 | int nbp_switchdev_mark_set(struct net_bridge_port *p) |
|---|
| 25 | 25 | { |
|---|
| 26 | | - struct switchdev_attr attr = { |
|---|
| 27 | | - .orig_dev = p->dev, |
|---|
| 28 | | - .id = SWITCHDEV_ATTR_ID_PORT_PARENT_ID, |
|---|
| 29 | | - }; |
|---|
| 26 | + struct netdev_phys_item_id ppid = { }; |
|---|
| 30 | 27 | int err; |
|---|
| 31 | 28 | |
|---|
| 32 | 29 | ASSERT_RTNL(); |
|---|
| 33 | 30 | |
|---|
| 34 | | - err = switchdev_port_attr_get(p->dev, &attr); |
|---|
| 31 | + err = dev_get_port_parent_id(p->dev, &ppid, true); |
|---|
| 35 | 32 | if (err) { |
|---|
| 36 | 33 | if (err == -EOPNOTSUPP) |
|---|
| 37 | 34 | return 0; |
|---|
| .. | .. |
|---|
| 67 | 64 | { |
|---|
| 68 | 65 | struct switchdev_attr attr = { |
|---|
| 69 | 66 | .orig_dev = p->dev, |
|---|
| 70 | | - .id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS_SUPPORT, |
|---|
| 67 | + .id = SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS, |
|---|
| 68 | + .u.brport_flags = mask, |
|---|
| 69 | + }; |
|---|
| 70 | + struct switchdev_notifier_port_attr_info info = { |
|---|
| 71 | + .attr = &attr, |
|---|
| 71 | 72 | }; |
|---|
| 72 | 73 | int err; |
|---|
| 73 | 74 | |
|---|
| 74 | 75 | if (mask & ~BR_PORT_FLAGS_HW_OFFLOAD) |
|---|
| 75 | 76 | return 0; |
|---|
| 76 | 77 | |
|---|
| 77 | | - err = switchdev_port_attr_get(p->dev, &attr); |
|---|
| 78 | + /* We run from atomic context here */ |
|---|
| 79 | + err = call_switchdev_notifiers(SWITCHDEV_PORT_ATTR_SET, p->dev, |
|---|
| 80 | + &info.info, NULL); |
|---|
| 81 | + err = notifier_to_errno(err); |
|---|
| 78 | 82 | if (err == -EOPNOTSUPP) |
|---|
| 79 | 83 | return 0; |
|---|
| 80 | | - if (err) |
|---|
| 81 | | - return err; |
|---|
| 82 | 84 | |
|---|
| 83 | | - /* Check if specific bridge flag attribute offload is supported */ |
|---|
| 84 | | - if (!(attr.u.brport_flags_support & mask)) { |
|---|
| 85 | + if (err) { |
|---|
| 85 | 86 | br_warn(p->br, "bridge flag offload is not supported %u(%s)\n", |
|---|
| 86 | 87 | (unsigned int)p->port_no, p->dev->name); |
|---|
| 87 | 88 | return -EOPNOTSUPP; |
|---|
| .. | .. |
|---|
| 90 | 91 | attr.id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS; |
|---|
| 91 | 92 | attr.flags = SWITCHDEV_F_DEFER; |
|---|
| 92 | 93 | attr.u.brport_flags = flags; |
|---|
| 94 | + |
|---|
| 93 | 95 | err = switchdev_port_attr_set(p->dev, &attr); |
|---|
| 94 | 96 | if (err) { |
|---|
| 95 | 97 | br_warn(p->br, "error setting offload flag on port %u(%s)\n", |
|---|
| .. | .. |
|---|
| 103 | 105 | static void |
|---|
| 104 | 106 | br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac, |
|---|
| 105 | 107 | u16 vid, struct net_device *dev, |
|---|
| 106 | | - bool added_by_user) |
|---|
| 108 | + bool added_by_user, bool offloaded) |
|---|
| 107 | 109 | { |
|---|
| 108 | 110 | struct switchdev_notifier_fdb_info info; |
|---|
| 109 | 111 | unsigned long notifier_type; |
|---|
| .. | .. |
|---|
| 111 | 113 | info.addr = mac; |
|---|
| 112 | 114 | info.vid = vid; |
|---|
| 113 | 115 | info.added_by_user = added_by_user; |
|---|
| 116 | + info.offloaded = offloaded; |
|---|
| 114 | 117 | notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE; |
|---|
| 115 | | - call_switchdev_notifiers(notifier_type, dev, &info.info); |
|---|
| 118 | + call_switchdev_notifiers(notifier_type, dev, &info.info, NULL); |
|---|
| 116 | 119 | } |
|---|
| 117 | 120 | |
|---|
| 118 | 121 | void |
|---|
| .. | .. |
|---|
| 120 | 123 | { |
|---|
| 121 | 124 | if (!fdb->dst) |
|---|
| 122 | 125 | return; |
|---|
| 126 | + if (test_bit(BR_FDB_LOCAL, &fdb->flags)) |
|---|
| 127 | + return; |
|---|
| 123 | 128 | |
|---|
| 124 | 129 | switch (type) { |
|---|
| 125 | 130 | case RTM_DELNEIGH: |
|---|
| 126 | 131 | br_switchdev_fdb_call_notifiers(false, fdb->key.addr.addr, |
|---|
| 127 | 132 | fdb->key.vlan_id, |
|---|
| 128 | 133 | fdb->dst->dev, |
|---|
| 129 | | - fdb->added_by_user); |
|---|
| 134 | + test_bit(BR_FDB_ADDED_BY_USER, |
|---|
| 135 | + &fdb->flags), |
|---|
| 136 | + test_bit(BR_FDB_OFFLOADED, |
|---|
| 137 | + &fdb->flags)); |
|---|
| 130 | 138 | break; |
|---|
| 131 | 139 | case RTM_NEWNEIGH: |
|---|
| 132 | 140 | br_switchdev_fdb_call_notifiers(true, fdb->key.addr.addr, |
|---|
| 133 | 141 | fdb->key.vlan_id, |
|---|
| 134 | 142 | fdb->dst->dev, |
|---|
| 135 | | - fdb->added_by_user); |
|---|
| 143 | + test_bit(BR_FDB_ADDED_BY_USER, |
|---|
| 144 | + &fdb->flags), |
|---|
| 145 | + test_bit(BR_FDB_OFFLOADED, |
|---|
| 146 | + &fdb->flags)); |
|---|
| 136 | 147 | break; |
|---|
| 137 | 148 | } |
|---|
| 138 | 149 | } |
|---|
| 139 | 150 | |
|---|
| 140 | | -int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags) |
|---|
| 151 | +int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags, |
|---|
| 152 | + struct netlink_ext_ack *extack) |
|---|
| 141 | 153 | { |
|---|
| 142 | 154 | struct switchdev_obj_port_vlan v = { |
|---|
| 143 | 155 | .obj.orig_dev = dev, |
|---|
| .. | .. |
|---|
| 147 | 159 | .vid_end = vid, |
|---|
| 148 | 160 | }; |
|---|
| 149 | 161 | |
|---|
| 150 | | - return switchdev_port_obj_add(dev, &v.obj); |
|---|
| 162 | + return switchdev_port_obj_add(dev, &v.obj, extack); |
|---|
| 151 | 163 | } |
|---|
| 152 | 164 | |
|---|
| 153 | 165 | int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid) |
|---|