static int
swconfig_set_vlan_ports(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
{
+ struct switch_port *ports = val->value.ports;
int i;
if (val->port_vlan >= dev->vlans)
if (val->len > dev->ports)
return -EINVAL;
+ if (!dev->set_vlan_ports)
+ return -EOPNOTSUPP;
+
for (i = 0; i < val->len; i++) {
- if (val->value.ports[i].id >= dev->ports)
+ if (ports[i].id >= dev->ports)
return -EINVAL;
+
+ if (dev->set_port_pvid && !(ports[i].flags & (1 << SWITCH_PORT_FLAG_TAGGED)))
+ dev->set_port_pvid(dev, ports[i].id, val->port_vlan);
}
- if (!dev->set_vlan_ports)
+ return dev->set_vlan_ports(dev, val);
+}
+
+static int
+swconfig_set_pvid(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
+{
+ if (val->port_vlan >= dev->ports)
+ return -EINVAL;
+
+ if (!dev->set_port_pvid)
return -EOPNOTSUPP;
- return dev->set_vlan_ports(dev, val);
+ return dev->set_port_pvid(dev, val->port_vlan, val->value.i);
+}
+
+static int
+swconfig_get_pvid(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
+{
+ if (val->port_vlan >= dev->ports)
+ return -EINVAL;
+
+ if (!dev->get_port_pvid)
+ return -EOPNOTSUPP;
+
+ return dev->get_port_pvid(dev, val->port_vlan, &val->value.i);
}
static int
return dev->apply_config(dev);
}
+static int
+swconfig_reset_switch(struct switch_dev *dev, const struct switch_attr *attr, struct switch_val *val)
+{
+ /* don't complain if not supported by the switch driver */
+ if (!dev->reset_switch)
+ return 0;
+
+ return dev->reset_switch(dev);
+}
enum global_defaults {
GLOBAL_APPLY,
+ GLOBAL_RESET,
};
enum vlan_defaults {
};
enum port_defaults {
- PORT_LINK,
+ PORT_PVID,
};
static struct switch_attr default_global[] = {
.name = "apply",
.description = "Activate changes in the hardware",
.set = swconfig_apply_config,
+ },
+ [GLOBAL_RESET] = {
+ .type = SWITCH_TYPE_NOVAL,
+ .name = "reset",
+ .description = "Reset the switch",
+ .set = swconfig_reset_switch,
}
};
static struct switch_attr default_port[] = {
- [PORT_LINK] = {
+ [PORT_PVID] = {
.type = SWITCH_TYPE_INT,
- .name = "link",
- .description = "Current link speed",
+ .name = "pvid",
+ .description = "Primary VLAN ID",
+ .set = swconfig_set_pvid,
+ .get = swconfig_get_pvid,
}
};
if (dev->get_vlan_ports || dev->set_vlan_ports)
set_bit(VLAN_PORTS, &dev->def_vlan);
+ if (dev->get_port_pvid || dev->set_port_pvid)
+ set_bit(PORT_PVID, &dev->def_port);
+
/* always present, can be no-op */
set_bit(GLOBAL_APPLY, &dev->def_global);
+ set_bit(GLOBAL_RESET, &dev->def_global);
}
if (!info->attrs[SWITCH_ATTR_OP_VLAN])
goto done;
val->port_vlan = nla_get_u32(info->attrs[SWITCH_ATTR_OP_VLAN]);
+ if (val->port_vlan >= dev->vlans)
+ goto done;
break;
case SWITCH_CMD_SET_PORT:
case SWITCH_CMD_GET_PORT:
if (!info->attrs[SWITCH_ATTR_OP_PORT])
goto done;
val->port_vlan = nla_get_u32(info->attrs[SWITCH_ATTR_OP_PORT]);
+ if (val->port_vlan >= dev->ports)
+ goto done;
break;
default:
WARN_ON(1);
NLA_PUT_STRING(msg, SWITCH_ATTR_DEV_NAME, dev->devname);
NLA_PUT_U32(msg, SWITCH_ATTR_VLANS, dev->vlans);
NLA_PUT_U32(msg, SWITCH_ATTR_PORTS, dev->ports);
+ NLA_PUT_U32(msg, SWITCH_ATTR_CPU_PORT, dev->cpu_port);
return genlmsg_end(msg, hdr);
nla_put_failure: