Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/mlx4/mlx4_en/mlx4_en_netdev.c
Show First 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | |||||
static void mlx4_en_sysctl_conf(struct mlx4_en_priv *priv); | static void mlx4_en_sysctl_conf(struct mlx4_en_priv *priv); | ||||
#ifdef CONFIG_NET_RX_BUSY_POLL | #ifdef CONFIG_NET_RX_BUSY_POLL | ||||
/* must be called with local_bh_disable()d */ | /* must be called with local_bh_disable()d */ | ||||
static int mlx4_en_low_latency_recv(struct napi_struct *napi) | static int mlx4_en_low_latency_recv(struct napi_struct *napi) | ||||
{ | { | ||||
struct mlx4_en_cq *cq = container_of(napi, struct mlx4_en_cq, napi); | struct mlx4_en_cq *cq = container_of(napi, struct mlx4_en_cq, napi); | ||||
struct ifnet *dev = cq->dev; | struct ifnet *dev = cq->dev; | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
struct mlx4_en_rx_ring *rx_ring = priv->rx_ring[cq->ring]; | struct mlx4_en_rx_ring *rx_ring = priv->rx_ring[cq->ring]; | ||||
int done; | int done; | ||||
if (!priv->port_up) | if (!priv->port_up) | ||||
return LL_FLUSH_FAILED; | return LL_FLUSH_FAILED; | ||||
if (!mlx4_en_cq_lock_poll(cq)) | if (!mlx4_en_cq_lock_poll(cq)) | ||||
return LL_FLUSH_BUSY; | return LL_FLUSH_BUSY; | ||||
▲ Show 20 Lines • Show All 209 Lines • ▼ Show 20 Lines | mlx4_en_filter_find(struct mlx4_en_priv *priv, __be32 src_ip, __be32 dst_ip, | ||||
return ret; | return ret; | ||||
} | } | ||||
static int | static int | ||||
mlx4_en_filter_rfs(struct ifnet *net_dev, const struct sk_buff *skb, | mlx4_en_filter_rfs(struct ifnet *net_dev, const struct sk_buff *skb, | ||||
u16 rxq_index, u32 flow_id) | u16 rxq_index, u32 flow_id) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(net_dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(net_dev); | ||||
struct mlx4_en_filter *filter; | struct mlx4_en_filter *filter; | ||||
const struct iphdr *ip; | const struct iphdr *ip; | ||||
const __be16 *ports; | const __be16 *ports; | ||||
u8 ip_proto; | u8 ip_proto; | ||||
__be32 src_ip; | __be32 src_ip; | ||||
__be32 dst_ip; | __be32 dst_ip; | ||||
__be16 src_port; | __be16 src_port; | ||||
__be16 dst_port; | __be16 dst_port; | ||||
▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | static void mlx4_en_filter_rfs_expire(struct mlx4_en_priv *priv) | ||||
list_for_each_entry_safe(filter, tmp, &del_list, next) | list_for_each_entry_safe(filter, tmp, &del_list, next) | ||||
mlx4_en_filter_free(filter); | mlx4_en_filter_free(filter); | ||||
} | } | ||||
#endif | #endif | ||||
static void mlx4_en_vlan_rx_add_vid(void *arg, struct ifnet *dev, u16 vid) | static void mlx4_en_vlan_rx_add_vid(void *arg, struct ifnet *dev, u16 vid) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
struct mlx4_en_dev *mdev = priv->mdev; | struct mlx4_en_dev *mdev = priv->mdev; | ||||
int err; | int err; | ||||
int idx; | int idx; | ||||
if (arg != priv) | if (arg != priv) | ||||
return; | return; | ||||
en_dbg(HW, priv, "adding VLAN:%d\n", vid); | en_dbg(HW, priv, "adding VLAN:%d\n", vid); | ||||
Show All 10 Lines | static void mlx4_en_vlan_rx_add_vid(void *arg, struct ifnet *dev, u16 vid) | ||||
if (mlx4_register_vlan(mdev->dev, priv->port, vid, &idx)) | if (mlx4_register_vlan(mdev->dev, priv->port, vid, &idx)) | ||||
en_dbg(HW, priv, "failed adding vlan %d\n", vid); | en_dbg(HW, priv, "failed adding vlan %d\n", vid); | ||||
mutex_unlock(&mdev->state_lock); | mutex_unlock(&mdev->state_lock); | ||||
} | } | ||||
static void mlx4_en_vlan_rx_kill_vid(void *arg, struct ifnet *dev, u16 vid) | static void mlx4_en_vlan_rx_kill_vid(void *arg, struct ifnet *dev, u16 vid) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
struct mlx4_en_dev *mdev = priv->mdev; | struct mlx4_en_dev *mdev = priv->mdev; | ||||
int err; | int err; | ||||
if (arg != priv) | if (arg != priv) | ||||
return; | return; | ||||
en_dbg(HW, priv, "Killing VID:%d\n", vid); | en_dbg(HW, priv, "Killing VID:%d\n", vid); | ||||
▲ Show 20 Lines • Show All 162 Lines • ▼ Show 20 Lines | en_dbg(DRV, priv, "Releasing qp: port %d, qpn %d\n", | ||||
priv->port, qpn); | priv->port, qpn); | ||||
mlx4_qp_release_range(dev, qpn, 1); | mlx4_qp_release_range(dev, qpn, 1); | ||||
priv->flags &= ~MLX4_EN_FLAG_FORCE_PROMISC; | priv->flags &= ~MLX4_EN_FLAG_FORCE_PROMISC; | ||||
} | } | ||||
} | } | ||||
static void mlx4_en_clear_uclist(struct ifnet *dev) | static void mlx4_en_clear_uclist(struct ifnet *dev) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
struct mlx4_en_addr_list *tmp, *uc_to_del; | struct mlx4_en_addr_list *tmp, *uc_to_del; | ||||
list_for_each_entry_safe(uc_to_del, tmp, &priv->uc_list, list) { | list_for_each_entry_safe(uc_to_del, tmp, &priv->uc_list, list) { | ||||
list_del(&uc_to_del->list); | list_del(&uc_to_del->list); | ||||
kfree(uc_to_del); | kfree(uc_to_del); | ||||
} | } | ||||
} | } | ||||
Show All 12 Lines | static u_int mlx4_copy_addr(void *arg, struct sockaddr_dl *sdl, u_int cnt) | ||||
memcpy(tmp->addr, LLADDR(sdl), ETH_ALEN); | memcpy(tmp->addr, LLADDR(sdl), ETH_ALEN); | ||||
list_add_tail(&tmp->list, &priv->uc_list); | list_add_tail(&tmp->list, &priv->uc_list); | ||||
return (1); | return (1); | ||||
} | } | ||||
static void mlx4_en_cache_uclist(struct ifnet *dev) | static void mlx4_en_cache_uclist(struct ifnet *dev) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
mlx4_en_clear_uclist(dev); | mlx4_en_clear_uclist(dev); | ||||
if_foreach_lladdr(dev, mlx4_copy_addr, priv); | if_foreach_lladdr(dev, mlx4_copy_addr, priv); | ||||
} | } | ||||
static void mlx4_en_clear_mclist(struct ifnet *dev) | static void mlx4_en_clear_mclist(struct ifnet *dev) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
struct mlx4_en_addr_list *tmp, *mc_to_del; | struct mlx4_en_addr_list *tmp, *mc_to_del; | ||||
list_for_each_entry_safe(mc_to_del, tmp, &priv->mc_list, list) { | list_for_each_entry_safe(mc_to_del, tmp, &priv->mc_list, list) { | ||||
list_del(&mc_to_del->list); | list_del(&mc_to_del->list); | ||||
kfree(mc_to_del); | kfree(mc_to_del); | ||||
} | } | ||||
} | } | ||||
Show All 11 Lines | static u_int mlx4_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int count) | ||||
} | } | ||||
memcpy(tmp->addr, LLADDR(sdl), ETH_ALEN); | memcpy(tmp->addr, LLADDR(sdl), ETH_ALEN); | ||||
list_add_tail(&tmp->list, &priv->mc_list); | list_add_tail(&tmp->list, &priv->mc_list); | ||||
return (1); | return (1); | ||||
} | } | ||||
static void mlx4_en_cache_mclist(struct ifnet *dev) | static void mlx4_en_cache_mclist(struct ifnet *dev) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
mlx4_en_clear_mclist(dev); | mlx4_en_clear_mclist(dev); | ||||
if_foreach_llmaddr(dev, mlx4_copy_maddr, priv); | if_foreach_llmaddr(dev, mlx4_copy_maddr, priv); | ||||
} | } | ||||
static void update_addr_list_flags(struct mlx4_en_priv *priv, | static void update_addr_list_flags(struct mlx4_en_priv *priv, | ||||
struct list_head *dst, | struct list_head *dst, | ||||
struct list_head *src) | struct list_head *src) | ||||
Show All 40 Lines | if (!found) { | ||||
new_mc->action = MLX4_ADDR_LIST_ADD; | new_mc->action = MLX4_ADDR_LIST_ADD; | ||||
list_add_tail(&new_mc->list, dst); | list_add_tail(&new_mc->list, dst); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
static void mlx4_en_set_rx_mode(struct ifnet *dev) | static void mlx4_en_set_rx_mode(struct ifnet *dev) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
if (!priv->port_up) | if (!priv->port_up) | ||||
return; | return; | ||||
queue_work(priv->mdev->workqueue, &priv->rx_mode_task); | queue_work(priv->mdev->workqueue, &priv->rx_mode_task); | ||||
} | } | ||||
static void mlx4_en_set_promisc_mode(struct mlx4_en_priv *priv, | static void mlx4_en_set_promisc_mode(struct mlx4_en_priv *priv, | ||||
▲ Show 20 Lines • Show All 513 Lines • ▼ Show 20 Lines | static void mlx4_en_linkstate(struct work_struct *work) | ||||
} | } | ||||
priv->last_link_state = linkstate; | priv->last_link_state = linkstate; | ||||
mutex_unlock(&mdev->state_lock); | mutex_unlock(&mdev->state_lock); | ||||
} | } | ||||
int mlx4_en_start_port(struct ifnet *dev) | int mlx4_en_start_port(struct ifnet *dev) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
struct mlx4_en_dev *mdev = priv->mdev; | struct mlx4_en_dev *mdev = priv->mdev; | ||||
struct mlx4_en_cq *cq; | struct mlx4_en_cq *cq; | ||||
struct mlx4_en_tx_ring *tx_ring; | struct mlx4_en_tx_ring *tx_ring; | ||||
int rx_index = 0; | int rx_index = 0; | ||||
int tx_index = 0; | int tx_index = 0; | ||||
int err = 0; | int err = 0; | ||||
int i; | int i; | ||||
int j; | int j; | ||||
▲ Show 20 Lines • Show All 176 Lines • ▼ Show 20 Lines | for (i = 0; i < priv->rx_ring_num; i++) | ||||
mlx4_en_deactivate_rx_ring(priv, priv->rx_ring[i]); | mlx4_en_deactivate_rx_ring(priv, priv->rx_ring[i]); | ||||
return err; /* need to close devices */ | return err; /* need to close devices */ | ||||
} | } | ||||
void mlx4_en_stop_port(struct ifnet *dev) | void mlx4_en_stop_port(struct ifnet *dev) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
struct mlx4_en_dev *mdev = priv->mdev; | struct mlx4_en_dev *mdev = priv->mdev; | ||||
struct mlx4_en_addr_list *addr_list, *tmp; | struct mlx4_en_addr_list *addr_list, *tmp; | ||||
int i; | int i; | ||||
u8 mc_list[16] = {0}; | u8 mc_list[16] = {0}; | ||||
if (!priv->port_up) { | if (!priv->port_up) { | ||||
en_dbg(DRV, priv, "stop port called while port already down\n"); | en_dbg(DRV, priv, "stop port called while port already down\n"); | ||||
return; | return; | ||||
▲ Show 20 Lines • Show All 133 Lines • ▼ Show 20 Lines | if (priv->port_up) { | ||||
if (mlx4_en_start_port(dev)) | if (mlx4_en_start_port(dev)) | ||||
en_err(priv, "Failed restarting port %d\n", priv->port); | en_err(priv, "Failed restarting port %d\n", priv->port); | ||||
} | } | ||||
mutex_unlock(&mdev->state_lock); | mutex_unlock(&mdev->state_lock); | ||||
} | } | ||||
static void mlx4_en_clear_stats(struct ifnet *dev) | static void mlx4_en_clear_stats(struct ifnet *dev) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
struct mlx4_en_dev *mdev = priv->mdev; | struct mlx4_en_dev *mdev = priv->mdev; | ||||
int i; | int i; | ||||
if (!mlx4_is_slave(mdev->dev)) | if (!mlx4_is_slave(mdev->dev)) | ||||
if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1)) | if (mlx4_en_DUMP_ETH_STATS(mdev, priv->port, 1)) | ||||
en_dbg(HW, priv, "Failed dumping statistics\n"); | en_dbg(HW, priv, "Failed dumping statistics\n"); | ||||
memset(&priv->pstats, 0, sizeof(priv->pstats)); | memset(&priv->pstats, 0, sizeof(priv->pstats)); | ||||
▲ Show 20 Lines • Show All 142 Lines • ▼ Show 20 Lines | |||||
#define PORT_ATTR_RO(_name) \ | #define PORT_ATTR_RO(_name) \ | ||||
struct en_port_attribute en_port_attr_##_name = __ATTR_RO(_name) | struct en_port_attribute en_port_attr_##_name = __ATTR_RO(_name) | ||||
#define EN_PORT_ATTR(_name, _mode, _show, _store) \ | #define EN_PORT_ATTR(_name, _mode, _show, _store) \ | ||||
struct en_port_attribute en_port_attr_##_name = __ATTR(_name, _mode, _show, _store) | struct en_port_attribute en_port_attr_##_name = __ATTR(_name, _mode, _show, _store) | ||||
void mlx4_en_destroy_netdev(struct ifnet *dev) | void mlx4_en_destroy_netdev(struct ifnet *dev) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
struct mlx4_en_dev *mdev = priv->mdev; | struct mlx4_en_dev *mdev = priv->mdev; | ||||
en_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port); | en_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port); | ||||
/* don't allow more IOCTLs */ | /* don't allow more IOCTLs */ | ||||
priv->gone = 1; | priv->gone = 1; | ||||
/* XXX wait a bit to allow IOCTL handlers to complete */ | /* XXX wait a bit to allow IOCTL handlers to complete */ | ||||
Show All 38 Lines | kfree(priv->tx_cq); | ||||
kfree(priv); | kfree(priv); | ||||
if_free(dev); | if_free(dev); | ||||
} | } | ||||
static int mlx4_en_change_mtu(struct ifnet *dev, int new_mtu) | static int mlx4_en_change_mtu(struct ifnet *dev, int new_mtu) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
struct mlx4_en_dev *mdev = priv->mdev; | struct mlx4_en_dev *mdev = priv->mdev; | ||||
int err = 0; | int err = 0; | ||||
en_dbg(DRV, priv, "Change MTU called - current:%u new:%u\n", | en_dbg(DRV, priv, "Change MTU called - current:%u new:%u\n", | ||||
(unsigned)dev->if_mtu, (unsigned)new_mtu); | (unsigned)dev->if_mtu, (unsigned)new_mtu); | ||||
if ((new_mtu < MLX4_EN_MIN_MTU) || (new_mtu > priv->max_mtu)) { | if ((new_mtu < MLX4_EN_MIN_MTU) || (new_mtu > priv->max_mtu)) { | ||||
en_err(priv, "Bad MTU size:%d, max %u.\n", new_mtu, | en_err(priv, "Bad MTU size:%d, max %u.\n", new_mtu, | ||||
▲ Show 20 Lines • Show All 519 Lines • ▼ Show 20 Lines | |||||
out: | out: | ||||
mlx4_en_destroy_netdev(dev); | mlx4_en_destroy_netdev(dev); | ||||
return err; | return err; | ||||
} | } | ||||
static int mlx4_en_set_ring_size(struct ifnet *dev, | static int mlx4_en_set_ring_size(struct ifnet *dev, | ||||
int rx_size, int tx_size) | int rx_size, int tx_size) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
struct mlx4_en_dev *mdev = priv->mdev; | struct mlx4_en_dev *mdev = priv->mdev; | ||||
int port_up = 0; | int port_up = 0; | ||||
int err = 0; | int err = 0; | ||||
rx_size = roundup_pow_of_two(rx_size); | rx_size = roundup_pow_of_two(rx_size); | ||||
rx_size = max_t(u32, rx_size, MLX4_EN_MIN_RX_SIZE); | rx_size = max_t(u32, rx_size, MLX4_EN_MIN_RX_SIZE); | ||||
rx_size = min_t(u32, rx_size, MLX4_EN_MAX_RX_SIZE); | rx_size = min_t(u32, rx_size, MLX4_EN_MAX_RX_SIZE); | ||||
tx_size = roundup_pow_of_two(tx_size); | tx_size = roundup_pow_of_two(tx_size); | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | static int mlx4_en_set_tx_ring_size(SYSCTL_HANDLER_ARGS) | ||||
size); | size); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int mlx4_en_get_module_info(struct ifnet *dev, | static int mlx4_en_get_module_info(struct ifnet *dev, | ||||
struct ethtool_modinfo *modinfo) | struct ethtool_modinfo *modinfo) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
struct mlx4_en_dev *mdev = priv->mdev; | struct mlx4_en_dev *mdev = priv->mdev; | ||||
int ret; | int ret; | ||||
u8 data[4]; | u8 data[4]; | ||||
/* Read first 2 bytes to get Module & REV ID */ | /* Read first 2 bytes to get Module & REV ID */ | ||||
ret = mlx4_get_module_info(mdev->dev, priv->port, | ret = mlx4_get_module_info(mdev->dev, priv->port, | ||||
0/*offset*/, 2/*size*/, data); | 0/*offset*/, 2/*size*/, data); | ||||
Show All 31 Lines | static int mlx4_en_get_module_info(struct ifnet *dev, | ||||
return 0; | return 0; | ||||
} | } | ||||
static int mlx4_en_get_module_eeprom(struct ifnet *dev, | static int mlx4_en_get_module_eeprom(struct ifnet *dev, | ||||
struct ethtool_eeprom *ee, | struct ethtool_eeprom *ee, | ||||
u8 *data) | u8 *data) | ||||
{ | { | ||||
struct mlx4_en_priv *priv = netdev_priv(dev); | struct mlx4_en_priv *priv = mlx4_netdev_priv(dev); | ||||
struct mlx4_en_dev *mdev = priv->mdev; | struct mlx4_en_dev *mdev = priv->mdev; | ||||
int offset = ee->offset; | int offset = ee->offset; | ||||
int i = 0, ret; | int i = 0, ret; | ||||
if (ee->len == 0) | if (ee->len == 0) | ||||
return -EINVAL; | return -EINVAL; | ||||
memset(data, 0, ee->len); | memset(data, 0, ee->len); | ||||
▲ Show 20 Lines • Show All 460 Lines • Show Last 20 Lines |