Commit eb8b7077 authored by David S. Miller's avatar David S. Miller

Merge branch 'mv88e6xxx-Allow-config-of-ATU-hash-algorithm'

Andrew Lunn says:

====================
mv88e6xxx: Allow config of ATU hash algorithm

v2:

Pass a pointer for where the hash should be stored, return a plain
errno, or 0.

Document the parameter.

v3:

Document type of parameter, and valid range
Add break statements to default clause of switch
Directly use ctx->val.vu8

v4:

Consistently use devlink, not a mix of devlink and dl.
Fix allocation of devlink priv
Remove upper case from parameter name
Make mask 16 bit wide.

v5:
Back to using the parameter name ATU_hash

v6:
Rebase net-next/master
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ebdcebcb 23e8b470
ATU_hash [DEVICE, DRIVER-SPECIFIC]
Select one of four possible hashing algorithms for
MAC addresses in the Address Translation Unit.
A value of 3 seems to work better than the default of
1 when many MAC addresses have the same OUI.
Configuration mode: runtime
Type: u8. 0-3 valid.
......@@ -9744,6 +9744,7 @@ S: Maintained
F: drivers/net/dsa/mv88e6xxx/
F: include/linux/platform_data/mv88e6xxx.h
F: Documentation/devicetree/bindings/net/dsa/marvell.txt
F: Documentation/networking/devlink-params-mv88e6xxx.txt
MARVELL ARMADA DRM SUPPORT
M: Russell King <linux@armlinux.org.uk>
......
This diff is collapsed.
......@@ -497,6 +497,10 @@ struct mv88e6xxx_ops {
int (*serdes_get_stats)(struct mv88e6xxx_chip *chip, int port,
uint64_t *data);
/* Address Translation Unit operations */
int (*atu_get_hash)(struct mv88e6xxx_chip *chip, u8 *hash);
int (*atu_set_hash)(struct mv88e6xxx_chip *chip, u8 hash);
/* VLAN Translation Unit operations */
int (*vtu_getnext)(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry);
......
......@@ -109,6 +109,7 @@
/* Offset 0x0A: ATU Control Register */
#define MV88E6XXX_G1_ATU_CTL 0x0a
#define MV88E6XXX_G1_ATU_CTL_LEARN2ALL 0x0008
#define MV88E6161_G1_ATU_CTL_HASH_MASK 0x0003
/* Offset 0x0B: ATU Operation Register */
#define MV88E6XXX_G1_ATU_OP 0x0b
......@@ -318,6 +319,8 @@ int mv88e6xxx_g1_atu_remove(struct mv88e6xxx_chip *chip, u16 fid, int port,
bool all);
int mv88e6xxx_g1_atu_prob_irq_setup(struct mv88e6xxx_chip *chip);
void mv88e6xxx_g1_atu_prob_irq_free(struct mv88e6xxx_chip *chip);
int mv88e6165_g1_atu_get_hash(struct mv88e6xxx_chip *chip, u8 *hash);
int mv88e6165_g1_atu_set_hash(struct mv88e6xxx_chip *chip, u8 hash);
int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_vtu_entry *entry);
......
......@@ -73,6 +73,38 @@ int mv88e6xxx_g1_atu_set_age_time(struct mv88e6xxx_chip *chip,
return 0;
}
int mv88e6165_g1_atu_get_hash(struct mv88e6xxx_chip *chip, u8 *hash)
{
int err;
u16 val;
err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_CTL, &val);
if (err)
return err;
*hash = val & MV88E6161_G1_ATU_CTL_HASH_MASK;
return 0;
}
int mv88e6165_g1_atu_set_hash(struct mv88e6xxx_chip *chip, u8 hash)
{
int err;
u16 val;
if (hash & ~MV88E6161_G1_ATU_CTL_HASH_MASK)
return -EINVAL;
err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_ATU_CTL, &val);
if (err)
return err;
val &= ~MV88E6161_G1_ATU_CTL_HASH_MASK;
val |= hash;
return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_ATU_CTL, val);
}
/* Offset 0x0B: ATU Operation Register */
static int mv88e6xxx_g1_atu_op_wait(struct mv88e6xxx_chip *chip)
......
......@@ -550,6 +550,29 @@ struct dsa_switch_ops {
*/
netdev_tx_t (*port_deferred_xmit)(struct dsa_switch *ds, int port,
struct sk_buff *skb);
/* Devlink parameters */
int (*devlink_param_get)(struct dsa_switch *ds, u32 id,
struct devlink_param_gset_ctx *ctx);
int (*devlink_param_set)(struct dsa_switch *ds, u32 id,
struct devlink_param_gset_ctx *ctx);
};
#define DSA_DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes) \
DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes, \
dsa_devlink_param_get, dsa_devlink_param_set, NULL)
int dsa_devlink_param_get(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx);
int dsa_devlink_param_set(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx);
int dsa_devlink_params_register(struct dsa_switch *ds,
const struct devlink_param *params,
size_t params_count);
void dsa_devlink_params_unregister(struct dsa_switch *ds,
const struct devlink_param *params,
size_t params_count);
struct dsa_devlink_priv {
struct dsa_switch *ds;
};
struct dsa_switch_driver {
......
......@@ -331,6 +331,54 @@ int call_dsa_notifiers(unsigned long val, struct net_device *dev,
}
EXPORT_SYMBOL_GPL(call_dsa_notifiers);
int dsa_devlink_param_get(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx)
{
struct dsa_devlink_priv *dl_priv;
struct dsa_switch *ds;
dl_priv = devlink_priv(dl);
ds = dl_priv->ds;
if (!ds->ops->devlink_param_get)
return -EOPNOTSUPP;
return ds->ops->devlink_param_get(ds, id, ctx);
}
EXPORT_SYMBOL_GPL(dsa_devlink_param_get);
int dsa_devlink_param_set(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx)
{
struct dsa_devlink_priv *dl_priv;
struct dsa_switch *ds;
dl_priv = devlink_priv(dl);
ds = dl_priv->ds;
if (!ds->ops->devlink_param_set)
return -EOPNOTSUPP;
return ds->ops->devlink_param_set(ds, id, ctx);
}
EXPORT_SYMBOL_GPL(dsa_devlink_param_set);
int dsa_devlink_params_register(struct dsa_switch *ds,
const struct devlink_param *params,
size_t params_count)
{
return devlink_params_register(ds->devlink, params, params_count);
}
EXPORT_SYMBOL_GPL(dsa_devlink_params_register);
void dsa_devlink_params_unregister(struct dsa_switch *ds,
const struct devlink_param *params,
size_t params_count)
{
devlink_params_unregister(ds->devlink, params, params_count);
}
EXPORT_SYMBOL_GPL(dsa_devlink_params_unregister);
static int __init dsa_init_module(void)
{
int rc;
......
......@@ -349,6 +349,7 @@ static void dsa_port_teardown(struct dsa_port *dp)
static int dsa_switch_setup(struct dsa_switch *ds)
{
struct dsa_devlink_priv *dl_priv;
int err;
if (ds->setup)
......@@ -364,9 +365,11 @@ static int dsa_switch_setup(struct dsa_switch *ds)
/* Add the switch to devlink before calling setup, so that setup can
* add dpipe tables
*/
ds->devlink = devlink_alloc(&dsa_devlink_ops, 0);
ds->devlink = devlink_alloc(&dsa_devlink_ops, sizeof(*dl_priv));
if (!ds->devlink)
return -ENOMEM;
dl_priv = devlink_priv(ds->devlink);
dl_priv->ds = ds;
err = devlink_register(ds->devlink, ds->dev);
if (err)
......@@ -380,6 +383,8 @@ static int dsa_switch_setup(struct dsa_switch *ds)
if (err < 0)
goto unregister_notifier;
devlink_params_publish(ds->devlink);
if (!ds->slave_mii_bus && ds->ops->phy_read) {
ds->slave_mii_bus = devm_mdiobus_alloc(ds->dev);
if (!ds->slave_mii_bus) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment