dev = alloc_etherdev(sizeof(struct mlxsw_m_port)); if (!dev) {
err = -ENOMEM; goto err_alloc_etherdev;
}
SET_NETDEV_DEV(dev, mlxsw_m->bus_info->dev);
dev_net_set(dev, mlxsw_core_net(mlxsw_m->core));
mlxsw_m_port = netdev_priv(dev);
mlxsw_core_port_netdev_link(mlxsw_m->core, local_port,
mlxsw_m_port, dev);
mlxsw_m_port->dev = dev;
mlxsw_m_port->mlxsw_m = mlxsw_m;
mlxsw_m_port->local_port = local_port;
mlxsw_m_port->module = module;
mlxsw_m_port->slot_index = slot_index; /* Add module offset for line card. Offset for main board iz zero. * For line card in slot #n offset is calculated as (#n - 1) * multiplied by maximum modules number, which could be found on a line * card.
*/
mlxsw_m_port->module_offset = mlxsw_m_port->slot_index ?
(mlxsw_m_port->slot_index - 1) *
mlxsw_m->max_modules_per_slot : 0;
err = mlxsw_m_port_dev_addr_get(mlxsw_m_port); if (err) {
dev_err(mlxsw_m->bus_info->dev, "Port %d: Unable to get port mac address\n",
mlxsw_m_port->local_port); goto err_dev_addr_get;
}
/* Fill out to local port mapping array */
err = mlxsw_m_port_module_info_get(mlxsw_m, local_port, &module,
&width, &slot_index); if (err) return err;
/* Skip if line card has been already configured */ if (mlxsw_m->line_cards[slot_index]->active) return 0; if (!width) return 0; /* Skip, if port belongs to the cluster */ if (module == *last_module) return 0;
*last_module = module;
mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, &num_of_modules,
&mlxsw_m->num_of_slots); /* If the system is modular, get the maximum number of modules per-slot. * Otherwise, get the maximum number of modules on the main board.
*/ if (mlxsw_m->num_of_slots)
mlxsw_m->max_modules_per_slot =
mlxsw_reg_mgpir_max_modules_per_slot_get(mgpir_pl); else
mlxsw_m->max_modules_per_slot = num_of_modules; /* Add slot for main board. */
mlxsw_m->num_of_slots += 1;
mlxsw_m->ports = kcalloc(max_ports, sizeof(*mlxsw_m->ports),
GFP_KERNEL); if (!mlxsw_m->ports) return -ENOMEM;
for (i = 0; i < mlxsw_m->num_of_slots; i++) {
mlxsw_m->line_cards[i] =
kzalloc(struct_size(mlxsw_m->line_cards[i],
module_to_port,
mlxsw_m->max_modules_per_slot),
GFP_KERNEL); if (!mlxsw_m->line_cards[i]) {
err = -ENOMEM; goto err_kmalloc_array;
}
/* Invalidate the entries of module to local port mapping array. */ for (j = 0; j < mlxsw_m->max_modules_per_slot; j++)
mlxsw_m->line_cards[i]->module_to_port[j] = -1;
}
return 0;
err_kmalloc_array: for (i--; i >= 0; i--)
kfree(mlxsw_m->line_cards[i]);
kfree(mlxsw_m->line_cards);
err_kcalloc:
kfree(mlxsw_m->ports); return err;
}
staticvoid mlxsw_m_linecards_fini(struct mlxsw_m *mlxsw_m)
{ int i = mlxsw_m->num_of_slots;
for (i--; i >= 0; i--)
kfree(mlxsw_m->line_cards[i]);
kfree(mlxsw_m->line_cards);
kfree(mlxsw_m->ports);
}
staticvoid
mlxsw_m_linecard_port_module_unmap(struct mlxsw_m *mlxsw_m, u8 slot_index)
{ int i;
for (i = mlxsw_m->max_modules_per_slot - 1; i >= 0; i--) { int *module_to_port;
staticint
mlxsw_m_linecard_ports_create(struct mlxsw_m *mlxsw_m, u8 slot_index)
{ int *module_to_port; int i, err;
for (i = 0; i < mlxsw_m->max_modules_per_slot; i++) {
module_to_port = mlxsw_m_port_mapping_get(mlxsw_m, slot_index, i); if (*module_to_port > 0) {
err = mlxsw_m_port_create(mlxsw_m, *module_to_port,
slot_index, i); if (err) goto err_port_create; /* Mark slot as active */ if (!mlxsw_m->line_cards[slot_index]->active)
mlxsw_m->line_cards[slot_index]->active = true;
}
} return 0;
err_port_create: for (i--; i >= 0; i--) {
module_to_port = mlxsw_m_port_mapping_get(mlxsw_m, slot_index, i); if (*module_to_port > 0 &&
mlxsw_m_port_created(mlxsw_m, *module_to_port)) {
mlxsw_m_port_remove(mlxsw_m, *module_to_port); /* Mark slot as inactive */ if (mlxsw_m->line_cards[slot_index]->active)
mlxsw_m->line_cards[slot_index]->active = false;
}
} return err;
}
staticvoid
mlxsw_m_linecard_ports_remove(struct mlxsw_m *mlxsw_m, u8 slot_index)
{ int i;
for (i = 0; i < mlxsw_m->max_modules_per_slot; i++) { int *module_to_port = mlxsw_m_port_mapping_get(mlxsw_m,
slot_index, i);
/* Validate driver and FW are compatible. * Do not check major version, since it defines chip type, while * driver is supposed to support any type.
*/ if (mlxsw_core_fw_rev_minor_subminor_validate(rev, &mlxsw_m_fw_rev)) return 0;
dev_err(mlxsw_m->bus_info->dev, "The firmware version %d.%d.%d is incompatible with the driver (required >= %d.%d.%d)\n",
rev->major, rev->minor, rev->subminor, rev->major,
mlxsw_m_fw_rev.minor, mlxsw_m_fw_rev.subminor);
linecard = mlxsw_m->line_cards[slot_index]; /* Skip if line card has been already configured during init */ if (linecard->active) return;
/* Fill out module to local port mapping array */
err = mlxsw_m_ports_module_map(mlxsw_m); if (err) goto err_ports_module_map;
/* Create port objects for each valid entry */
err = mlxsw_m_linecard_ports_create(mlxsw_m, slot_index); if (err) {
dev_err(mlxsw_m->bus_info->dev, "Failed to create port for line card at slot %d\n",
slot_index); goto err_linecard_ports_create;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.