Skip to content

Commit

Permalink
net/smc: add smcd support to the pnet table
Browse files Browse the repository at this point in the history
Currently, users can only set pnetids for netdevs and ib devices in the
pnet table. This patch adds support for smcd devices to the pnet table.

Signed-off-by: Hans Wippel <hwippel@linux.ibm.com>
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Hans Wippel authored and David S. Miller committed Feb 21, 2019
1 parent 890a2cb commit f3d74b2
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 7 deletions.
1 change: 1 addition & 0 deletions include/net/smc.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ struct smcd_dev {
struct list_head vlan;
struct workqueue_struct *event_wq;
u8 pnetid[SMC_MAX_PNETID_LEN];
bool pnetid_by_user;
};

struct smcd_dev *smcd_alloc_dev(struct device *parent, const char *name,
Expand Down
87 changes: 80 additions & 7 deletions net/smc/smc_pnet.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,15 @@ static struct smc_pnettable {
* @ndev: pointer to network device.
* @smcibdev: Pointer to IB device.
* @ib_port: Port of IB device.
* @smcd_dev: Pointer to smcd device.
*/
struct smc_user_pnetentry {
struct list_head list;
char pnet_name[SMC_MAX_PNETID_LEN + 1];
struct net_device *ndev;
struct smc_ib_device *smcibdev;
u8 ib_port;
struct smcd_dev *smcd_dev;
};

/* pnet entry stored in pnet table */
Expand Down Expand Up @@ -103,6 +105,7 @@ static int smc_pnet_remove_by_pnetid(char *pnet_name)
{
struct smc_pnetentry *pnetelem, *tmp_pe;
struct smc_ib_device *ibdev;
struct smcd_dev *smcd_dev;
int rc = -ENOENT;
int ibport;

Expand Down Expand Up @@ -135,6 +138,18 @@ static int smc_pnet_remove_by_pnetid(char *pnet_name)
}
}
spin_unlock(&smc_ib_devices.lock);
/* remove smcd devices */
spin_lock(&smcd_dev_list.lock);
list_for_each_entry(smcd_dev, &smcd_dev_list.list, list) {
if (smcd_dev->pnetid_by_user &&
(!pnet_name ||
smc_pnet_match(pnet_name, smcd_dev->pnetid))) {
memset(smcd_dev->pnetid, 0, SMC_MAX_PNETID_LEN);
smcd_dev->pnetid_by_user = false;
rc = 0;
}
}
spin_unlock(&smcd_dev_list.lock);
return rc;
}

Expand Down Expand Up @@ -168,6 +183,7 @@ static int smc_pnet_enter(struct smc_user_pnetentry *new_pnetelem)
u8 ndev_pnetid[SMC_MAX_PNETID_LEN];
struct smc_pnetentry *tmp_pnetelem;
struct smc_pnetentry *pnetelem;
bool new_smcddev = false;
struct net_device *ndev;
bool new_netdev = true;
bool new_ibdev = false;
Expand All @@ -185,17 +201,29 @@ static int smc_pnet_enter(struct smc_user_pnetentry *new_pnetelem)
}
spin_unlock(&smc_ib_devices.lock);
}
if (new_pnetelem->smcd_dev) {
struct smcd_dev *smcd_dev = new_pnetelem->smcd_dev;

spin_lock(&smcd_dev_list.lock);
if (smc_pnet_match(smcd_dev->pnetid, pnet_null)) {
memcpy(smcd_dev->pnetid, new_pnetelem->pnet_name,
SMC_MAX_PNETID_LEN);
smcd_dev->pnetid_by_user = true;
new_smcddev = true;
}
spin_unlock(&smcd_dev_list.lock);
}

if (!new_pnetelem->ndev)
return new_ibdev ? 0 : -EEXIST;
return (new_ibdev || new_smcddev) ? 0 : -EEXIST;

/* check if (base) netdev already has a pnetid. If there is one, we do
* not want to add a pnet table entry
*/
ndev = pnet_find_base_ndev(new_pnetelem->ndev);
if (!smc_pnetid_by_dev_port(ndev->dev.parent, ndev->dev_port,
ndev_pnetid))
return new_ibdev ? 0 : -EEXIST;
return (new_ibdev || new_smcddev) ? 0 : -EEXIST;

/* add a new netdev entry to the pnet table if there isn't one */
tmp_pnetelem = kzalloc(sizeof(*pnetelem), GFP_KERNEL);
Expand All @@ -219,7 +247,7 @@ static int smc_pnet_enter(struct smc_user_pnetentry *new_pnetelem)
kfree(tmp_pnetelem);
}

return (new_netdev || new_ibdev) ? 0 : -EEXIST;
return (new_netdev || new_ibdev || new_smcddev) ? 0 : -EEXIST;
}

/* The limit for pnetid is 16 characters.
Expand Down Expand Up @@ -267,6 +295,23 @@ static struct smc_ib_device *smc_pnet_find_ib(char *ib_name)
return ibdev;
}

/* Find an smcd device by a given name. The device might not exist. */
static struct smcd_dev *smc_pnet_find_smcd(char *smcd_name)
{
struct smcd_dev *smcd_dev;

spin_lock(&smcd_dev_list.lock);
list_for_each_entry(smcd_dev, &smcd_dev_list.list, list) {
if (!strncmp(dev_name(&smcd_dev->dev), smcd_name,
IB_DEVICE_NAME_MAX - 1))
goto out;
}
smcd_dev = NULL;
out:
spin_unlock(&smcd_dev_list.lock);
return smcd_dev;
}

/* Parse the supplied netlink attributes and fill a pnetentry structure.
* For ethernet and infiniband device names verify that the devices exist.
*/
Expand Down Expand Up @@ -300,7 +345,8 @@ static int smc_pnet_fill_entry(struct net *net,
ibname = (char *)nla_data(tb[SMC_PNETID_IBNAME]);
ibname = strim(ibname);
pnetelem->smcibdev = smc_pnet_find_ib(ibname);
if (!pnetelem->smcibdev)
pnetelem->smcd_dev = smc_pnet_find_smcd(ibname);
if (!pnetelem->smcibdev && !pnetelem->smcd_dev)
goto error;
if (pnetelem->smcibdev) {
if (!tb[SMC_PNETID_IBPORT])
Expand Down Expand Up @@ -339,6 +385,11 @@ static int smc_pnet_set_nla(struct sk_buff *msg,
pnetelem->smcibdev->ibdev->name) ||
nla_put_u8(msg, SMC_PNETID_IBPORT, pnetelem->ib_port))
return -1;
} else if (pnetelem->smcd_dev) {
if (nla_put_string(msg, SMC_PNETID_IBNAME,
dev_name(&pnetelem->smcd_dev->dev)) ||
nla_put_u8(msg, SMC_PNETID_IBPORT, 1))
return -1;
} else {
if (nla_put_string(msg, SMC_PNETID_IBNAME, "n/a") ||
nla_put_u8(msg, SMC_PNETID_IBPORT, 0xff))
Expand Down Expand Up @@ -400,6 +451,7 @@ static int _smc_pnet_dump(struct sk_buff *skb, u32 portid, u32 seq, u8 *pnetid,
struct smc_user_pnetentry tmp_entry;
struct smc_pnetentry *pnetelem;
struct smc_ib_device *ibdev;
struct smcd_dev *smcd_dev;
int idx = 0;
int ibport;

Expand Down Expand Up @@ -450,6 +502,27 @@ static int _smc_pnet_dump(struct sk_buff *skb, u32 portid, u32 seq, u8 *pnetid,
}
spin_unlock(&smc_ib_devices.lock);

/* dump smcd devices */
spin_lock(&smcd_dev_list.lock);
list_for_each_entry(smcd_dev, &smcd_dev_list.list, list) {
if (smcd_dev->pnetid_by_user) {
if (pnetid && !smc_pnet_match(smcd_dev->pnetid, pnetid))
continue;
if (idx++ < start_idx)
continue;
memset(&tmp_entry, 0, sizeof(tmp_entry));
memcpy(&tmp_entry.pnet_name, smcd_dev->pnetid,
SMC_MAX_PNETID_LEN);
tmp_entry.smcd_dev = smcd_dev;
if (smc_pnet_dumpinfo(skb, portid, seq, NLM_F_MULTI,
&tmp_entry)) {
--idx;
break;
}
}
}
spin_unlock(&smcd_dev_list.lock);

return idx;
}

Expand Down Expand Up @@ -666,12 +739,13 @@ static void smc_pnet_find_ism_by_pnetid(struct net_device *ndev,

ndev = pnet_find_base_ndev(ndev);
if (smc_pnetid_by_dev_port(ndev->dev.parent, ndev->dev_port,
ndev_pnetid))
ndev_pnetid) &&
smc_pnet_find_ndev_pnetid_by_table(ndev, ndev_pnetid))
return; /* pnetid could not be determined */

spin_lock(&smcd_dev_list.lock);
list_for_each_entry(ismdev, &smcd_dev_list.list, list) {
if (!memcmp(ismdev->pnetid, ndev_pnetid, SMC_MAX_PNETID_LEN)) {
if (smc_pnet_match(ismdev->pnetid, ndev_pnetid)) {
*smcismdev = ismdev;
break;
}
Expand Down Expand Up @@ -715,7 +789,6 @@ void smc_pnet_find_ism_resource(struct sock *sk, struct smcd_dev **smcismdev)
if (!dst->dev)
goto out_rel;

/* if possible, lookup via hardware-defined pnetid */
smc_pnet_find_ism_by_pnetid(dst->dev, smcismdev);

out_rel:
Expand Down

0 comments on commit f3d74b2

Please sign in to comment.