Caller passing down the SKIP_EOPNOTSUPP switchdev flag expects that -EOPNOTSUPP cannot be returned. But in case of direct op call without recurtion, this may happen. So fix this by checking it always on the end of __switchdev_port_attr_set function.
Unified · Split
| @@ -225,8 +225,10 @@ static int __switchdev_port_attr_set(struct net_device *dev, · 224 unmodified lines | |||
| 225 | struct list_head *iter; | 225 | struct list_head *iter; |
| 226 | int err = -EOPNOTSUPP; | 226 | int err = -EOPNOTSUPP; |
| 227 | 227 | ||
| 228 | if (ops && ops->switchdev_port_attr_set) | 228 | if (ops && ops->switchdev_port_attr_set) { |
| 229 | return ops->switchdev_port_attr_set(dev, attr, trans); | 229 | err = ops->switchdev_port_attr_set(dev, attr, trans); |
| 230 | goto done; | ||
| 231 | } | ||
| 230 | 232 | ||
| 231 | if (attr->flags & SWITCHDEV_F_NO_RECURSE) | 233 | if (attr->flags & SWITCHDEV_F_NO_RECURSE) |
| 232 | goto done; | 234 | goto done; |
| @@ -238,9 +240,6 @@ static int __switchdev_port_attr_set(struct net_device *dev, · 5 unmodified lines | |||
| 238 | 240 | ||
| 239 | netdev_for_each_lower_dev(dev, lower_dev, iter) { | 241 | netdev_for_each_lower_dev(dev, lower_dev, iter) { |
| 240 | err = __switchdev_port_attr_set(lower_dev, attr, trans); | 242 | err = __switchdev_port_attr_set(lower_dev, attr, trans); |
| 241 | if (err == -EOPNOTSUPP && | ||
| 242 | attr->flags & SWITCHDEV_F_SKIP_EOPNOTSUPP) | ||
| 243 | continue; | ||
| 244 | if (err) | 243 | if (err) |
| 245 | break; | 244 | break; |
| 246 | } | 245 | } |