Skip to content

Commit

Permalink
liquidio CN23XX: VF mac address
Browse files Browse the repository at this point in the history
Adds support for configuring mtu, multicast and mac address.

Signed-off-by: Raghu Vatsavayi <raghu.vatsavayi@caviumnetworks.com>
Signed-off-by: Derek Chickles <derek.chickles@caviumnetworks.com>
Signed-off-by: Satanand Burla <satananda.burla@caviumnetworks.com>
Signed-off-by: Felix Manlunas <felix.manlunas@caviumnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Raghu Vatsavayi authored and David S. Miller committed Dec 8, 2016
1 parent 3cd25e4 commit 50f7f94
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 0 deletions.
195 changes: 195 additions & 0 deletions drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,194 @@ static int liquidio_stop(struct net_device *netdev)
return 0;
}

/**
* \brief Converts a mask based on net device flags
* @param netdev network device
*
* This routine generates a octnet_ifflags mask from the net device flags
* received from the OS.
*/
static enum octnet_ifflags get_new_flags(struct net_device *netdev)
{
enum octnet_ifflags f = OCTNET_IFFLAG_UNICAST;

if (netdev->flags & IFF_PROMISC)
f |= OCTNET_IFFLAG_PROMISC;

if (netdev->flags & IFF_ALLMULTI)
f |= OCTNET_IFFLAG_ALLMULTI;

if (netdev->flags & IFF_MULTICAST) {
f |= OCTNET_IFFLAG_MULTICAST;

/* Accept all multicast addresses if there are more than we
* can handle
*/
if (netdev_mc_count(netdev) > MAX_OCTEON_MULTICAST_ADDR)
f |= OCTNET_IFFLAG_ALLMULTI;
}

if (netdev->flags & IFF_BROADCAST)
f |= OCTNET_IFFLAG_BROADCAST;

return f;
}

static void liquidio_set_uc_list(struct net_device *netdev)
{
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
struct octnic_ctrl_pkt nctrl;
struct netdev_hw_addr *ha;
u64 *mac;

if (lio->netdev_uc_count == netdev_uc_count(netdev))
return;

if (netdev_uc_count(netdev) > MAX_NCTRL_UDD) {
dev_err(&oct->pci_dev->dev, "too many MAC addresses in netdev uc list\n");
return;
}

lio->netdev_uc_count = netdev_uc_count(netdev);

memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));
nctrl.ncmd.s.cmd = OCTNET_CMD_SET_UC_LIST;
nctrl.ncmd.s.more = lio->netdev_uc_count;
nctrl.ncmd.s.param1 = oct->vf_num;
nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
nctrl.netpndev = (u64)netdev;
nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;

/* copy all the addresses into the udd */
mac = &nctrl.udd[0];
netdev_for_each_uc_addr(ha, netdev) {
ether_addr_copy(((u8 *)mac) + 2, ha->addr);
mac++;
}

octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
}

/**
* \brief Net device set_multicast_list
* @param netdev network device
*/
static void liquidio_set_mcast_list(struct net_device *netdev)
{
int mc_count = min(netdev_mc_count(netdev), MAX_OCTEON_MULTICAST_ADDR);
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
struct octnic_ctrl_pkt nctrl;
struct netdev_hw_addr *ha;
u64 *mc;
int ret;

memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));

/* Create a ctrl pkt command to be sent to core app. */
nctrl.ncmd.u64 = 0;
nctrl.ncmd.s.cmd = OCTNET_CMD_SET_MULTI_LIST;
nctrl.ncmd.s.param1 = get_new_flags(netdev);
nctrl.ncmd.s.param2 = mc_count;
nctrl.ncmd.s.more = mc_count;
nctrl.netpndev = (u64)netdev;
nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;

/* copy all the addresses into the udd */
mc = &nctrl.udd[0];
netdev_for_each_mc_addr(ha, netdev) {
*mc = 0;
ether_addr_copy(((u8 *)mc) + 2, ha->addr);
/* no need to swap bytes */
if (++mc > &nctrl.udd[mc_count])
break;
}

nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;

/* Apparently, any activity in this call from the kernel has to
* be atomic. So we won't wait for response.
*/
nctrl.wait_time = 0;

ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
if (ret < 0) {
dev_err(&oct->pci_dev->dev, "DEVFLAGS change failed in core (ret: 0x%x)\n",
ret);
}

liquidio_set_uc_list(netdev);
}

/**
* \brief Net device set_mac_address
* @param netdev network device
*/
static int liquidio_set_mac(struct net_device *netdev, void *p)
{
struct sockaddr *addr = (struct sockaddr *)p;
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;
struct octnic_ctrl_pkt nctrl;
int ret = 0;

if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;

if (ether_addr_equal(addr->sa_data, netdev->dev_addr))
return 0;

if (lio->linfo.macaddr_is_admin_asgnd)
return -EPERM;

memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt));

nctrl.ncmd.u64 = 0;
nctrl.ncmd.s.cmd = OCTNET_CMD_CHANGE_MACADDR;
nctrl.ncmd.s.param1 = 0;
nctrl.ncmd.s.more = 1;
nctrl.iq_no = lio->linfo.txpciq[0].s.q_no;
nctrl.netpndev = (u64)netdev;
nctrl.cb_fn = liquidio_link_ctrl_cmd_completion;
nctrl.wait_time = 100;

nctrl.udd[0] = 0;
/* The MAC Address is presented in network byte order. */
ether_addr_copy((u8 *)&nctrl.udd[0] + 2, addr->sa_data);

ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl);
if (ret < 0) {
dev_err(&oct->pci_dev->dev, "MAC Address change failed\n");
return -ENOMEM;
}
memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
ether_addr_copy(((u8 *)&lio->linfo.hw_addr) + 2, addr->sa_data);

return 0;
}

/**
* \brief Net device change_mtu
* @param netdev network device
*/
static int liquidio_change_mtu(struct net_device *netdev, int new_mtu)
{
struct lio *lio = GET_LIO(netdev);
struct octeon_device *oct = lio->oct_dev;

lio->mtu = new_mtu;

netif_info(lio, probe, lio->netdev, "MTU Changed from %d to %d\n",
netdev->mtu, new_mtu);
dev_info(&oct->pci_dev->dev, "%s MTU Changed from %d to %d\n",
netdev->name, netdev->mtu, new_mtu);

netdev->mtu = new_mtu;

return 0;
}

/** Sending command to enable/disable RX checksum offload
* @param netdev pointer to network device
* @param command OCTNET_CMD_TNL_RX_CSUM_CTL
Expand Down Expand Up @@ -966,6 +1154,9 @@ static int liquidio_set_features(struct net_device *netdev,
static const struct net_device_ops lionetdevops = {
.ndo_open = liquidio_open,
.ndo_stop = liquidio_stop,
.ndo_set_mac_address = liquidio_set_mac,
.ndo_set_rx_mode = liquidio_set_mcast_list,
.ndo_change_mtu = liquidio_change_mtu,
.ndo_fix_features = liquidio_fix_features,
.ndo_set_features = liquidio_set_features,
.ndo_select_queue = select_q,
Expand Down Expand Up @@ -1165,6 +1356,10 @@ static int setup_nic_devices(struct octeon_device *octeon_dev)

netdev->hw_features = lio->dev_capability;

/* MTU range: 68 - 16000 */
netdev->min_mtu = LIO_MIN_MTU_SIZE;
netdev->max_mtu = LIO_MAX_MTU_SIZE;

/* Point to the properties for octeon device to which this
* interface belongs.
*/
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/cavium/liquidio/liquidio_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ static inline void add_sg_size(struct octeon_sg_entry *sg_entry,

#define OCTNET_CMD_ID_ACTIVE 0x1a

#define OCTNET_CMD_SET_UC_LIST 0x1b
#define OCTNET_CMD_SET_VF_LINKSTATE 0x1c
#define OCTNET_CMD_VXLAN_PORT_ADD 0x0
#define OCTNET_CMD_VXLAN_PORT_DEL 0x1
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/cavium/liquidio/octeon_network.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ struct lio {
/* work queue for link status */
struct cavium_wq link_status_wq;

int netdev_uc_count;
};

#define LIO_SIZE (sizeof(struct lio))
Expand Down

0 comments on commit 50f7f94

Please sign in to comment.