Commit f8bd9091 authored by Scott Feldman's avatar Scott Feldman Committed by David S. Miller

net: Add ndo_{set|get}_vf_port support for enic dynamic vnics

Add enic ndo_{set|get}_vf_port ops to support setting/getting
port-profile for enic dynamic devices.  Enic dynamic devices are just like
normal enic eth devices except dynamic enics require an extra configuration
step to assign a port-profile identifier to the interface before the
interface is useable.  Once a port-profile is assigned, link comes up on the
interface and is ready for I/O.  The port-profile is used to configure the
network port assigned to the interface.  The network port configuration
includes VLAN membership, QoS policies, and port security settings typical
of a data center network.

A dynamic enic initially has a zero-mac address.  Before a port-profile is
assigned, a valid non-zero unicast mac address should be assign to the
dynamic enic interface.
Signed-off-by: default avatarScott Feldman <scofeldm@cisco.com>
Signed-off-by: default avatarRoopa Prabhu <roprabhu@cisco.com>
parent 57b61080
obj-$(CONFIG_ENIC) := enic.o
enic-y := enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \
enic_res.o vnic_dev.o vnic_rq.o
enic_res.o vnic_dev.o vnic_rq.o vnic_vic.o
......@@ -34,7 +34,7 @@
#define DRV_NAME "enic"
#define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver"
#define DRV_VERSION "1.3.1.1"
#define DRV_VERSION "1.3.1.1-pp"
#define DRV_COPYRIGHT "Copyright 2008-2009 Cisco Systems, Inc"
#define PFX DRV_NAME ": "
......@@ -74,6 +74,13 @@ struct enic_msix_entry {
void *devid;
};
struct enic_port_profile {
u8 request;
char name[PORT_PROFILE_MAX];
u8 instance_uuid[PORT_UUID_MAX];
u8 host_uuid[PORT_UUID_MAX];
};
/* Per-instance private data structure */
struct enic {
struct net_device *netdev;
......@@ -95,6 +102,7 @@ struct enic {
u32 port_mtu;
u32 rx_coalesce_usecs;
u32 tx_coalesce_usecs;
struct enic_port_profile pp;
/* work queue cache line section */
____cacheline_aligned struct vnic_wq wq[ENIC_WQ_MAX];
......
This diff is collapsed.
......@@ -103,11 +103,6 @@ int enic_get_vnic_config(struct enic *enic)
return 0;
}
void enic_add_station_addr(struct enic *enic)
{
vnic_dev_add_addr(enic->vdev, enic->mac_addr);
}
void enic_add_multicast_addr(struct enic *enic, u8 *addr)
{
vnic_dev_add_addr(enic->vdev, addr);
......
......@@ -131,7 +131,6 @@ static inline void enic_queue_rq_desc(struct vnic_rq *rq,
struct enic;
int enic_get_vnic_config(struct enic *);
void enic_add_station_addr(struct enic *enic);
void enic_add_multicast_addr(struct enic *enic, u8 *addr);
void enic_del_multicast_addr(struct enic *enic, u8 *addr);
void enic_add_vlan(struct enic *enic, u16 vlanid);
......
......@@ -530,7 +530,7 @@ void vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
printk(KERN_ERR "Can't set packet filter\n");
}
void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr)
int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr)
{
u64 a0 = 0, a1 = 0;
int wait = 1000;
......@@ -543,9 +543,11 @@ void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr)
err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
if (err)
printk(KERN_ERR "Can't add addr [%pM], %d\n", addr, err);
return err;
}
void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr)
int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr)
{
u64 a0 = 0, a1 = 0;
int wait = 1000;
......@@ -558,6 +560,8 @@ void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr)
err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait);
if (err)
printk(KERN_ERR "Can't del addr [%pM], %d\n", addr, err);
return err;
}
int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr)
......@@ -682,6 +686,56 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg)
return r;
}
int vnic_dev_init_done(struct vnic_dev *vdev, int *done, int *err)
{
u64 a0 = 0, a1 = 0;
int wait = 1000;
int ret;
*done = 0;
ret = vnic_dev_cmd(vdev, CMD_INIT_STATUS, &a0, &a1, wait);
if (ret)
return ret;
*done = (a0 == 0);
*err = (a0 == 0) ? a1 : 0;
return 0;
}
int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len)
{
u64 a0, a1 = len;
int wait = 1000;
u64 prov_pa;
void *prov_buf;
int ret;
prov_buf = pci_alloc_consistent(vdev->pdev, len, &prov_pa);
if (!prov_buf)
return -ENOMEM;
memcpy(prov_buf, buf, len);
a0 = prov_pa;
ret = vnic_dev_cmd(vdev, CMD_INIT_PROV_INFO, &a0, &a1, wait);
pci_free_consistent(vdev->pdev, len, prov_buf, prov_pa);
return ret;
}
int vnic_dev_deinit(struct vnic_dev *vdev)
{
u64 a0 = 0, a1 = 0;
int wait = 1000;
return vnic_dev_cmd(vdev, CMD_DEINIT, &a0, &a1, wait);
}
int vnic_dev_link_status(struct vnic_dev *vdev)
{
if (vdev->linkstatus)
......
......@@ -103,8 +103,8 @@ int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats);
int vnic_dev_hang_notify(struct vnic_dev *vdev);
void vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
int broadcast, int promisc, int allmulti);
void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr);
void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr);
int vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr);
int vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr);
int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr);
int vnic_dev_raise_intr(struct vnic_dev *vdev, u16 intr);
int vnic_dev_notify_setcmd(struct vnic_dev *vdev,
......@@ -124,6 +124,9 @@ int vnic_dev_disable(struct vnic_dev *vdev);
int vnic_dev_open(struct vnic_dev *vdev, int arg);
int vnic_dev_open_done(struct vnic_dev *vdev, int *done);
int vnic_dev_init(struct vnic_dev *vdev, int arg);
int vnic_dev_init_done(struct vnic_dev *vdev, int *done, int *err);
int vnic_dev_init_prov(struct vnic_dev *vdev, u8 *buf, u32 len);
int vnic_dev_deinit(struct vnic_dev *vdev);
int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg);
int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done);
void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
......
/*
* Copyright 2010 Cisco Systems, Inc. All rights reserved.
*
* This program is free software; you may redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/slab.h>
#include "vnic_vic.h"
struct vic_provinfo *vic_provinfo_alloc(gfp_t flags, u8 *oui, u8 type)
{
struct vic_provinfo *vp = kzalloc(VIC_PROVINFO_MAX_DATA, flags);
if (!vp || !oui)
return NULL;
memcpy(vp->oui, oui, sizeof(vp->oui));
vp->type = type;
vp->length = htonl(sizeof(vp->num_tlvs));
return vp;
}
void vic_provinfo_free(struct vic_provinfo *vp)
{
kfree(vp);
}
int vic_provinfo_add_tlv(struct vic_provinfo *vp, u16 type, u16 length,
void *value)
{
struct vic_provinfo_tlv *tlv;
if (!vp || !value)
return -EINVAL;
if (ntohl(vp->length) + sizeof(*tlv) + length >
VIC_PROVINFO_MAX_TLV_DATA)
return -ENOMEM;
tlv = (struct vic_provinfo_tlv *)((u8 *)vp->tlv +
ntohl(vp->length) - sizeof(vp->num_tlvs));
tlv->type = htons(type);
tlv->length = htons(length);
memcpy(tlv->value, value, length);
vp->num_tlvs = htonl(ntohl(vp->num_tlvs) + 1);
vp->length = htonl(ntohl(vp->length) + sizeof(*tlv) + length);
return 0;
}
size_t vic_provinfo_size(struct vic_provinfo *vp)
{
return vp ? ntohl(vp->length) + sizeof(*vp) - sizeof(vp->num_tlvs) : 0;
}
/*
* Copyright 2010 Cisco Systems, Inc. All rights reserved.
*
* This program is free software; you may redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
#ifndef _VNIC_VIC_H_
#define _VNIC_VIC_H_
/* Note: All integer fields in NETWORK byte order */
/* Note: String field lengths include null char */
#define VIC_PROVINFO_CISCO_OUI { 0x00, 0x00, 0x0c }
#define VIC_PROVINFO_LINUX_TYPE 0x2
enum vic_linux_prov_tlv_type {
VIC_LINUX_PROV_TLV_PORT_PROFILE_NAME_STR = 0,
VIC_LINUX_PROV_TLV_CLIENT_MAC_ADDR = 1, /* u8[6] */
VIC_LINUX_PROV_TLV_CLIENT_NAME_STR = 2,
VIC_LINUX_PROV_TLV_HOST_UUID_STR = 8,
VIC_LINUX_PROV_TLV_CLIENT_UUID_STR = 9,
};
struct vic_provinfo {
u8 oui[3]; /* OUI of data provider */
u8 type; /* provider-specific type */
u32 length; /* length of data below */
u32 num_tlvs; /* number of tlvs */
struct vic_provinfo_tlv {
u16 type;
u16 length;
u8 value[0];
} tlv[0];
} __attribute__ ((packed));
#define VIC_PROVINFO_MAX_DATA 1385
#define VIC_PROVINFO_MAX_TLV_DATA (VIC_PROVINFO_MAX_DATA - \
sizeof(struct vic_provinfo))
struct vic_provinfo *vic_provinfo_alloc(gfp_t flags, u8 *oui, u8 type);
void vic_provinfo_free(struct vic_provinfo *vp);
int vic_provinfo_add_tlv(struct vic_provinfo *vp, u16 type, u16 length,
void *value);
size_t vic_provinfo_size(struct vic_provinfo *vp);
#endif /* _VNIC_VIC_H_ */
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