You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (56 commits) route: Take the right src and dst addresses in ip_route_newports ipv4: Fix nexthop caching wrt. scoping. ipv4: Invalidate nexthop cache nh_saddr more correctly. net: fix pch_gbe section mismatch warning ipv4: fix fib metrics mlx4_en: Removing HW info from ethtool -i report. net_sched: fix THROTTLED/RUNNING race drivers/net/a2065.c: Convert release_resource to release_region/release_mem_region drivers/net/ariadne.c: Convert release_resource to release_region/release_mem_region bonding: fix rx_handler locking myri10ge: fix rmmod crash mlx4_en: updated driver version to 1.5.4.1 mlx4_en: Using blue flame support mlx4_core: reserve UARs for userspace consumers mlx4_core: maintain available field in bitmap allocator mlx4: Add blue flame support for kernel consumers mlx4_en: Enabling new steering mlx4: Add support for promiscuous mode in the new steering model. mlx4: generalization of multicast steering. mlx4_en: Reporting HW revision in ethtool -i ...
This commit is contained in:
@@ -625,7 +625,7 @@ static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
|
||||
|
||||
err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw,
|
||||
!!(mqp->flags & MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK),
|
||||
MLX4_PROTOCOL_IB);
|
||||
MLX4_PROT_IB_IPV6);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -636,7 +636,7 @@ static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
|
||||
return 0;
|
||||
|
||||
err_add:
|
||||
mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw, MLX4_PROTOCOL_IB);
|
||||
mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw, MLX4_PROT_IB_IPV6);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -666,7 +666,7 @@ static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
|
||||
struct mlx4_ib_gid_entry *ge;
|
||||
|
||||
err = mlx4_multicast_detach(mdev->dev,
|
||||
&mqp->mqp, gid->raw, MLX4_PROTOCOL_IB);
|
||||
&mqp->mqp, gid->raw, MLX4_PROT_IB_IPV6);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -721,7 +721,6 @@ static int init_node_data(struct mlx4_ib_dev *dev)
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
dev->dev->rev_id = be32_to_cpup((__be32 *) (out_mad->data + 32));
|
||||
memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8);
|
||||
|
||||
out:
|
||||
@@ -954,7 +953,7 @@ static int mlx4_ib_netdev_event(struct notifier_block *this, unsigned long event
|
||||
mlx4_foreach_ib_transport_port(port, ibdev->dev) {
|
||||
oldnd = iboe->netdevs[port - 1];
|
||||
iboe->netdevs[port - 1] =
|
||||
mlx4_get_protocol_dev(ibdev->dev, MLX4_PROTOCOL_EN, port);
|
||||
mlx4_get_protocol_dev(ibdev->dev, MLX4_PROT_ETH, port);
|
||||
if (oldnd != iboe->netdevs[port - 1]) {
|
||||
if (iboe->netdevs[port - 1])
|
||||
netdev_added(ibdev, port);
|
||||
@@ -1207,7 +1206,7 @@ static struct mlx4_interface mlx4_ib_interface = {
|
||||
.add = mlx4_ib_add,
|
||||
.remove = mlx4_ib_remove,
|
||||
.event = mlx4_ib_event,
|
||||
.protocol = MLX4_PROTOCOL_IB
|
||||
.protocol = MLX4_PROT_IB_IPV6
|
||||
};
|
||||
|
||||
static int __init mlx4_ib_init(void)
|
||||
|
||||
+5
-5
@@ -711,14 +711,14 @@ static int __devinit a2065_init_one(struct zorro_dev *z,
|
||||
return -EBUSY;
|
||||
r2 = request_mem_region(mem_start, A2065_RAM_SIZE, "RAM");
|
||||
if (!r2) {
|
||||
release_resource(r1);
|
||||
release_mem_region(base_addr, sizeof(struct lance_regs));
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
dev = alloc_etherdev(sizeof(struct lance_private));
|
||||
if (dev == NULL) {
|
||||
release_resource(r1);
|
||||
release_resource(r2);
|
||||
release_mem_region(base_addr, sizeof(struct lance_regs));
|
||||
release_mem_region(mem_start, A2065_RAM_SIZE);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -764,8 +764,8 @@ static int __devinit a2065_init_one(struct zorro_dev *z,
|
||||
|
||||
err = register_netdev(dev);
|
||||
if (err) {
|
||||
release_resource(r1);
|
||||
release_resource(r2);
|
||||
release_mem_region(base_addr, sizeof(struct lance_regs));
|
||||
release_mem_region(mem_start, A2065_RAM_SIZE);
|
||||
free_netdev(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -182,14 +182,14 @@ static int __devinit ariadne_init_one(struct zorro_dev *z,
|
||||
return -EBUSY;
|
||||
r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM");
|
||||
if (!r2) {
|
||||
release_resource(r1);
|
||||
release_mem_region(base_addr, sizeof(struct Am79C960));
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
dev = alloc_etherdev(sizeof(struct ariadne_private));
|
||||
if (dev == NULL) {
|
||||
release_resource(r1);
|
||||
release_resource(r2);
|
||||
release_mem_region(base_addr, sizeof(struct Am79C960));
|
||||
release_mem_region(mem_start, ARIADNE_RAM_SIZE);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -213,8 +213,8 @@ static int __devinit ariadne_init_one(struct zorro_dev *z,
|
||||
|
||||
err = register_netdev(dev);
|
||||
if (err) {
|
||||
release_resource(r1);
|
||||
release_resource(r2);
|
||||
release_mem_region(base_addr, sizeof(struct Am79C960));
|
||||
release_mem_region(mem_start, ARIADNE_RAM_SIZE);
|
||||
free_netdev(dev);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1482,21 +1482,16 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
|
||||
{
|
||||
struct sk_buff *skb = *pskb;
|
||||
struct slave *slave;
|
||||
struct net_device *bond_dev;
|
||||
struct bonding *bond;
|
||||
|
||||
slave = bond_slave_get_rcu(skb->dev);
|
||||
bond_dev = ACCESS_ONCE(slave->dev->master);
|
||||
if (unlikely(!bond_dev))
|
||||
return RX_HANDLER_PASS;
|
||||
|
||||
skb = skb_share_check(skb, GFP_ATOMIC);
|
||||
if (unlikely(!skb))
|
||||
return RX_HANDLER_CONSUMED;
|
||||
|
||||
*pskb = skb;
|
||||
|
||||
bond = netdev_priv(bond_dev);
|
||||
slave = bond_slave_get_rcu(skb->dev);
|
||||
bond = slave->bond;
|
||||
|
||||
if (bond->params.arp_interval)
|
||||
slave->dev->last_rx = jiffies;
|
||||
@@ -1505,10 +1500,10 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
|
||||
return RX_HANDLER_EXACT;
|
||||
}
|
||||
|
||||
skb->dev = bond_dev;
|
||||
skb->dev = bond->dev;
|
||||
|
||||
if (bond->params.mode == BOND_MODE_ALB &&
|
||||
bond_dev->priv_flags & IFF_BRIDGE_PORT &&
|
||||
bond->dev->priv_flags & IFF_BRIDGE_PORT &&
|
||||
skb->pkt_type == PACKET_HOST) {
|
||||
|
||||
if (unlikely(skb_cow_head(skb,
|
||||
@@ -1516,7 +1511,7 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
|
||||
kfree_skb(skb);
|
||||
return RX_HANDLER_CONSUMED;
|
||||
}
|
||||
memcpy(eth_hdr(skb)->h_dest, bond_dev->dev_addr, ETH_ALEN);
|
||||
memcpy(eth_hdr(skb)->h_dest, bond->dev->dev_addr, ETH_ALEN);
|
||||
}
|
||||
|
||||
return RX_HANDLER_ANOTHER;
|
||||
@@ -1698,20 +1693,15 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
||||
pr_debug("Error %d calling netdev_set_bond_master\n", res);
|
||||
goto err_restore_mac;
|
||||
}
|
||||
res = netdev_rx_handler_register(slave_dev, bond_handle_frame,
|
||||
new_slave);
|
||||
if (res) {
|
||||
pr_debug("Error %d calling netdev_rx_handler_register\n", res);
|
||||
goto err_unset_master;
|
||||
}
|
||||
|
||||
/* open the slave since the application closed it */
|
||||
res = dev_open(slave_dev);
|
||||
if (res) {
|
||||
pr_debug("Opening slave %s failed\n", slave_dev->name);
|
||||
goto err_unreg_rxhandler;
|
||||
goto err_unset_master;
|
||||
}
|
||||
|
||||
new_slave->bond = bond;
|
||||
new_slave->dev = slave_dev;
|
||||
slave_dev->priv_flags |= IFF_BONDING;
|
||||
|
||||
@@ -1907,6 +1897,13 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
||||
if (res)
|
||||
goto err_close;
|
||||
|
||||
res = netdev_rx_handler_register(slave_dev, bond_handle_frame,
|
||||
new_slave);
|
||||
if (res) {
|
||||
pr_debug("Error %d calling netdev_rx_handler_register\n", res);
|
||||
goto err_dest_symlinks;
|
||||
}
|
||||
|
||||
pr_info("%s: enslaving %s as a%s interface with a%s link.\n",
|
||||
bond_dev->name, slave_dev->name,
|
||||
bond_is_active_slave(new_slave) ? "n active" : " backup",
|
||||
@@ -1916,13 +1913,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
|
||||
return 0;
|
||||
|
||||
/* Undo stages on error */
|
||||
err_dest_symlinks:
|
||||
bond_destroy_slave_symlinks(bond_dev, slave_dev);
|
||||
|
||||
err_close:
|
||||
dev_close(slave_dev);
|
||||
|
||||
err_unreg_rxhandler:
|
||||
netdev_rx_handler_unregister(slave_dev);
|
||||
synchronize_net();
|
||||
|
||||
err_unset_master:
|
||||
netdev_set_bond_master(slave_dev, NULL);
|
||||
|
||||
@@ -1988,6 +1984,14 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* unregister rx_handler early so bond_handle_frame wouldn't be called
|
||||
* for this slave anymore.
|
||||
*/
|
||||
netdev_rx_handler_unregister(slave_dev);
|
||||
write_unlock_bh(&bond->lock);
|
||||
synchronize_net();
|
||||
write_lock_bh(&bond->lock);
|
||||
|
||||
if (!bond->params.fail_over_mac) {
|
||||
if (!compare_ether_addr(bond_dev->dev_addr, slave->perm_hwaddr) &&
|
||||
bond->slave_cnt > 1)
|
||||
@@ -2104,8 +2108,6 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
|
||||
netif_addr_unlock_bh(bond_dev);
|
||||
}
|
||||
|
||||
netdev_rx_handler_unregister(slave_dev);
|
||||
synchronize_net();
|
||||
netdev_set_bond_master(slave_dev, NULL);
|
||||
|
||||
slave_disable_netpoll(slave);
|
||||
@@ -2186,6 +2188,12 @@ static int bond_release_all(struct net_device *bond_dev)
|
||||
*/
|
||||
write_unlock_bh(&bond->lock);
|
||||
|
||||
/* unregister rx_handler early so bond_handle_frame wouldn't
|
||||
* be called for this slave anymore.
|
||||
*/
|
||||
netdev_rx_handler_unregister(slave_dev);
|
||||
synchronize_net();
|
||||
|
||||
if (bond_is_lb(bond)) {
|
||||
/* must be called only after the slave
|
||||
* has been detached from the list
|
||||
@@ -2217,8 +2225,6 @@ static int bond_release_all(struct net_device *bond_dev)
|
||||
netif_addr_unlock_bh(bond_dev);
|
||||
}
|
||||
|
||||
netdev_rx_handler_unregister(slave_dev);
|
||||
synchronize_net();
|
||||
netdev_set_bond_master(slave_dev, NULL);
|
||||
|
||||
slave_disable_netpoll(slave);
|
||||
|
||||
@@ -187,6 +187,7 @@ struct slave {
|
||||
struct net_device *dev; /* first - useful for panic debug */
|
||||
struct slave *next;
|
||||
struct slave *prev;
|
||||
struct bonding *bond; /* our master */
|
||||
int delay;
|
||||
unsigned long jiffies;
|
||||
unsigned long last_arp_rx;
|
||||
|
||||
@@ -76,6 +76,7 @@ struct cpdma_desc {
|
||||
|
||||
struct cpdma_desc_pool {
|
||||
u32 phys;
|
||||
u32 hw_addr;
|
||||
void __iomem *iomap; /* ioremap map */
|
||||
void *cpumap; /* dma_alloc map */
|
||||
int desc_size, mem_size;
|
||||
@@ -137,7 +138,8 @@ struct cpdma_chan {
|
||||
* abstract out these details
|
||||
*/
|
||||
static struct cpdma_desc_pool *
|
||||
cpdma_desc_pool_create(struct device *dev, u32 phys, int size, int align)
|
||||
cpdma_desc_pool_create(struct device *dev, u32 phys, u32 hw_addr,
|
||||
int size, int align)
|
||||
{
|
||||
int bitmap_size;
|
||||
struct cpdma_desc_pool *pool;
|
||||
@@ -161,10 +163,12 @@ cpdma_desc_pool_create(struct device *dev, u32 phys, int size, int align)
|
||||
if (phys) {
|
||||
pool->phys = phys;
|
||||
pool->iomap = ioremap(phys, size);
|
||||
pool->hw_addr = hw_addr;
|
||||
} else {
|
||||
pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys,
|
||||
GFP_KERNEL);
|
||||
pool->iomap = (void __force __iomem *)pool->cpumap;
|
||||
pool->hw_addr = pool->phys;
|
||||
}
|
||||
|
||||
if (pool->iomap)
|
||||
@@ -201,14 +205,14 @@ static inline dma_addr_t desc_phys(struct cpdma_desc_pool *pool,
|
||||
{
|
||||
if (!desc)
|
||||
return 0;
|
||||
return pool->phys + (__force dma_addr_t)desc -
|
||||
return pool->hw_addr + (__force dma_addr_t)desc -
|
||||
(__force dma_addr_t)pool->iomap;
|
||||
}
|
||||
|
||||
static inline struct cpdma_desc __iomem *
|
||||
desc_from_phys(struct cpdma_desc_pool *pool, dma_addr_t dma)
|
||||
{
|
||||
return dma ? pool->iomap + dma - pool->phys : NULL;
|
||||
return dma ? pool->iomap + dma - pool->hw_addr : NULL;
|
||||
}
|
||||
|
||||
static struct cpdma_desc __iomem *
|
||||
@@ -260,6 +264,7 @@ struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params)
|
||||
|
||||
ctlr->pool = cpdma_desc_pool_create(ctlr->dev,
|
||||
ctlr->params.desc_mem_phys,
|
||||
ctlr->params.desc_hw_addr,
|
||||
ctlr->params.desc_mem_size,
|
||||
ctlr->params.desc_align);
|
||||
if (!ctlr->pool) {
|
||||
|
||||
@@ -33,6 +33,7 @@ struct cpdma_params {
|
||||
bool has_soft_reset;
|
||||
int min_packet_size;
|
||||
u32 desc_mem_phys;
|
||||
u32 desc_hw_addr;
|
||||
int desc_mem_size;
|
||||
int desc_align;
|
||||
|
||||
|
||||
@@ -1854,10 +1854,13 @@ static int __devinit davinci_emac_probe(struct platform_device *pdev)
|
||||
dma_params.rxcp = priv->emac_base + 0x660;
|
||||
dma_params.num_chan = EMAC_MAX_TXRX_CHANNELS;
|
||||
dma_params.min_packet_size = EMAC_DEF_MIN_ETHPKTSIZE;
|
||||
dma_params.desc_mem_phys = hw_ram_addr;
|
||||
dma_params.desc_hw_addr = hw_ram_addr;
|
||||
dma_params.desc_mem_size = pdata->ctrl_ram_size;
|
||||
dma_params.desc_align = 16;
|
||||
|
||||
dma_params.desc_mem_phys = pdata->no_bd_ram ? 0 :
|
||||
(u32 __force)res->start + pdata->ctrl_ram_offset;
|
||||
|
||||
priv->dma = cpdma_ctlr_create(&dma_params);
|
||||
if (!priv->dma) {
|
||||
dev_err(emac_dev, "DaVinci EMAC: Error initializing DMA\n");
|
||||
|
||||
@@ -62,6 +62,9 @@ u32 mlx4_bitmap_alloc(struct mlx4_bitmap *bitmap)
|
||||
} else
|
||||
obj = -1;
|
||||
|
||||
if (obj != -1)
|
||||
--bitmap->avail;
|
||||
|
||||
spin_unlock(&bitmap->lock);
|
||||
|
||||
return obj;
|
||||
@@ -101,11 +104,19 @@ u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align)
|
||||
} else
|
||||
obj = -1;
|
||||
|
||||
if (obj != -1)
|
||||
bitmap->avail -= cnt;
|
||||
|
||||
spin_unlock(&bitmap->lock);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
u32 mlx4_bitmap_avail(struct mlx4_bitmap *bitmap)
|
||||
{
|
||||
return bitmap->avail;
|
||||
}
|
||||
|
||||
void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt)
|
||||
{
|
||||
obj &= bitmap->max + bitmap->reserved_top - 1;
|
||||
@@ -115,6 +126,7 @@ void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt)
|
||||
bitmap->last = min(bitmap->last, obj);
|
||||
bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
|
||||
& bitmap->mask;
|
||||
bitmap->avail += cnt;
|
||||
spin_unlock(&bitmap->lock);
|
||||
}
|
||||
|
||||
@@ -130,6 +142,7 @@ int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask,
|
||||
bitmap->max = num - reserved_top;
|
||||
bitmap->mask = mask;
|
||||
bitmap->reserved_top = reserved_top;
|
||||
bitmap->avail = num - reserved_top - reserved_bot;
|
||||
spin_lock_init(&bitmap->lock);
|
||||
bitmap->table = kzalloc(BITS_TO_LONGS(bitmap->max) *
|
||||
sizeof (long), GFP_KERNEL);
|
||||
|
||||
@@ -198,7 +198,7 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
|
||||
u64 mtt_addr;
|
||||
int err;
|
||||
|
||||
if (vector >= dev->caps.num_comp_vectors)
|
||||
if (vector > dev->caps.num_comp_vectors + dev->caps.comp_pool)
|
||||
return -EINVAL;
|
||||
|
||||
cq->vector = vector;
|
||||
|
||||
@@ -51,13 +51,10 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv,
|
||||
int err;
|
||||
|
||||
cq->size = entries;
|
||||
if (mode == RX) {
|
||||
if (mode == RX)
|
||||
cq->buf_size = cq->size * sizeof(struct mlx4_cqe);
|
||||
cq->vector = ring % mdev->dev->caps.num_comp_vectors;
|
||||
} else {
|
||||
else
|
||||
cq->buf_size = sizeof(struct mlx4_cqe);
|
||||
cq->vector = 0;
|
||||
}
|
||||
|
||||
cq->ring = ring;
|
||||
cq->is_tx = mode;
|
||||
@@ -80,7 +77,8 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv,
|
||||
int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
|
||||
{
|
||||
struct mlx4_en_dev *mdev = priv->mdev;
|
||||
int err;
|
||||
int err = 0;
|
||||
char name[25];
|
||||
|
||||
cq->dev = mdev->pndev[priv->port];
|
||||
cq->mcq.set_ci_db = cq->wqres.db.db;
|
||||
@@ -89,6 +87,29 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
|
||||
*cq->mcq.arm_db = 0;
|
||||
memset(cq->buf, 0, cq->buf_size);
|
||||
|
||||
if (cq->is_tx == RX) {
|
||||
if (mdev->dev->caps.comp_pool) {
|
||||
if (!cq->vector) {
|
||||
sprintf(name , "%s-rx-%d", priv->dev->name, cq->ring);
|
||||
if (mlx4_assign_eq(mdev->dev, name, &cq->vector)) {
|
||||
cq->vector = (cq->ring + 1 + priv->port) %
|
||||
mdev->dev->caps.num_comp_vectors;
|
||||
mlx4_warn(mdev, "Failed Assigning an EQ to "
|
||||
"%s_rx-%d ,Falling back to legacy EQ's\n",
|
||||
priv->dev->name, cq->ring);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cq->vector = (cq->ring + 1 + priv->port) %
|
||||
mdev->dev->caps.num_comp_vectors;
|
||||
}
|
||||
} else {
|
||||
if (!cq->vector || !mdev->dev->caps.comp_pool) {
|
||||
/*Fallback to legacy pool in case of error*/
|
||||
cq->vector = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cq->is_tx)
|
||||
cq->size = priv->rx_ring[cq->ring].actual_size;
|
||||
|
||||
@@ -112,12 +133,15 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
|
||||
void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
|
||||
bool reserve_vectors)
|
||||
{
|
||||
struct mlx4_en_dev *mdev = priv->mdev;
|
||||
|
||||
mlx4_en_unmap_buffer(&cq->wqres.buf);
|
||||
mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size);
|
||||
if (priv->mdev->dev->caps.comp_pool && cq->vector && !reserve_vectors)
|
||||
mlx4_release_eq(priv->mdev->dev, cq->vector);
|
||||
cq->buf_size = 0;
|
||||
cq->buf = NULL;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
|
||||
struct mlx4_en_priv *priv = netdev_priv(dev);
|
||||
struct mlx4_en_dev *mdev = priv->mdev;
|
||||
|
||||
sprintf(drvinfo->driver, DRV_NAME " (%s)", mdev->dev->board_id);
|
||||
strncpy(drvinfo->driver, DRV_NAME, 32);
|
||||
strncpy(drvinfo->version, DRV_VERSION " (" DRV_RELDATE ")", 32);
|
||||
sprintf(drvinfo->fw_version, "%d.%d.%d",
|
||||
(u16) (mdev->dev->caps.fw_ver >> 32),
|
||||
@@ -131,8 +131,65 @@ static void mlx4_en_set_msglevel(struct net_device *dev, u32 val)
|
||||
static void mlx4_en_get_wol(struct net_device *netdev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct mlx4_en_priv *priv = netdev_priv(netdev);
|
||||
int err = 0;
|
||||
u64 config = 0;
|
||||
|
||||
if (!priv->mdev->dev->caps.wol) {
|
||||
wol->supported = 0;
|
||||
wol->wolopts = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
err = mlx4_wol_read(priv->mdev->dev, &config, priv->port);
|
||||
if (err) {
|
||||
en_err(priv, "Failed to get WoL information\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (config & MLX4_EN_WOL_MAGIC)
|
||||
wol->supported = WAKE_MAGIC;
|
||||
else
|
||||
wol->supported = 0;
|
||||
|
||||
if (config & MLX4_EN_WOL_ENABLED)
|
||||
wol->wolopts = WAKE_MAGIC;
|
||||
else
|
||||
wol->wolopts = 0;
|
||||
}
|
||||
|
||||
static int mlx4_en_set_wol(struct net_device *netdev,
|
||||
struct ethtool_wolinfo *wol)
|
||||
{
|
||||
struct mlx4_en_priv *priv = netdev_priv(netdev);
|
||||
u64 config = 0;
|
||||
int err = 0;
|
||||
|
||||
if (!priv->mdev->dev->caps.wol)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (wol->supported & ~WAKE_MAGIC)
|
||||
return -EINVAL;
|
||||
|
||||
err = mlx4_wol_read(priv->mdev->dev, &config, priv->port);
|
||||
if (err) {
|
||||
en_err(priv, "Failed to get WoL info, unable to modify\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (wol->wolopts & WAKE_MAGIC) {
|
||||
config |= MLX4_EN_WOL_DO_MODIFY | MLX4_EN_WOL_ENABLED |
|
||||
MLX4_EN_WOL_MAGIC;
|
||||
} else {
|
||||
config &= ~(MLX4_EN_WOL_ENABLED | MLX4_EN_WOL_MAGIC);
|
||||
config |= MLX4_EN_WOL_DO_MODIFY;
|
||||
}
|
||||
|
||||
err = mlx4_wol_write(priv->mdev->dev, config, priv->port);
|
||||
if (err)
|
||||
en_err(priv, "Failed to set WoL information\n");
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
|
||||
@@ -388,7 +445,7 @@ static int mlx4_en_set_ringparam(struct net_device *dev,
|
||||
mlx4_en_stop_port(dev);
|
||||
}
|
||||
|
||||
mlx4_en_free_resources(priv);
|
||||
mlx4_en_free_resources(priv, true);
|
||||
|
||||
priv->prof->tx_ring_size = tx_size;
|
||||
priv->prof->rx_ring_size = rx_size;
|
||||
@@ -442,6 +499,7 @@ const struct ethtool_ops mlx4_en_ethtool_ops = {
|
||||
.get_ethtool_stats = mlx4_en_get_ethtool_stats,
|
||||
.self_test = mlx4_en_self_test,
|
||||
.get_wol = mlx4_en_get_wol,
|
||||
.set_wol = mlx4_en_set_wol,
|
||||
.get_msglevel = mlx4_en_get_msglevel,
|
||||
.set_msglevel = mlx4_en_set_msglevel,
|
||||
.get_coalesce = mlx4_en_get_coalesce,
|
||||
|
||||
+12
-10
@@ -241,16 +241,18 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
|
||||
mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH)
|
||||
mdev->port_cnt++;
|
||||
|
||||
/* If we did not receive an explicit number of Rx rings, default to
|
||||
* the number of completion vectors populated by the mlx4_core */
|
||||
mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
|
||||
mlx4_info(mdev, "Using %d tx rings for port:%d\n",
|
||||
mdev->profile.prof[i].tx_ring_num, i);
|
||||
mdev->profile.prof[i].rx_ring_num = min_t(int,
|
||||
roundup_pow_of_two(dev->caps.num_comp_vectors),
|
||||
MAX_RX_RINGS);
|
||||
mlx4_info(mdev, "Defaulting to %d rx rings for port:%d\n",
|
||||
mdev->profile.prof[i].rx_ring_num, i);
|
||||
if (!dev->caps.comp_pool) {
|
||||
mdev->profile.prof[i].rx_ring_num =
|
||||
rounddown_pow_of_two(max_t(int, MIN_RX_RINGS,
|
||||
min_t(int,
|
||||
dev->caps.num_comp_vectors,
|
||||
MAX_RX_RINGS)));
|
||||
} else {
|
||||
mdev->profile.prof[i].rx_ring_num = rounddown_pow_of_two(
|
||||
min_t(int, dev->caps.comp_pool/
|
||||
dev->caps.num_ports - 1 , MAX_MSIX_P_PORT - 1));
|
||||
}
|
||||
}
|
||||
|
||||
/* Create our own workqueue for reset/multicast tasks
|
||||
@@ -294,7 +296,7 @@ static struct mlx4_interface mlx4_en_interface = {
|
||||
.remove = mlx4_en_remove,
|
||||
.event = mlx4_en_event,
|
||||
.get_dev = mlx4_en_get_netdev,
|
||||
.protocol = MLX4_PROTOCOL_EN,
|
||||
.protocol = MLX4_PROT_ETH,
|
||||
};
|
||||
|
||||
static int __init mlx4_en_init(void)
|
||||
|
||||
+144
-39
@@ -156,9 +156,8 @@ static void mlx4_en_do_set_mac(struct work_struct *work)
|
||||
mutex_lock(&mdev->state_lock);
|
||||
if (priv->port_up) {
|
||||
/* Remove old MAC and insert the new one */
|
||||
mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
|
||||
err = mlx4_register_mac(mdev->dev, priv->port,
|
||||
priv->mac, &priv->mac_index);
|
||||
err = mlx4_replace_mac(mdev->dev, priv->port,
|
||||
priv->base_qpn, priv->mac, 0);
|
||||
if (err)
|
||||
en_err(priv, "Failed changing HW MAC address\n");
|
||||
} else
|
||||
@@ -214,6 +213,7 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
|
||||
struct mlx4_en_dev *mdev = priv->mdev;
|
||||
struct net_device *dev = priv->dev;
|
||||
u64 mcast_addr = 0;
|
||||
u8 mc_list[16] = {0};
|
||||
int err;
|
||||
|
||||
mutex_lock(&mdev->state_lock);
|
||||
@@ -239,8 +239,12 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
|
||||
priv->flags |= MLX4_EN_FLAG_PROMISC;
|
||||
|
||||
/* Enable promiscouos mode */
|
||||
if (!mdev->dev->caps.vep_uc_steering)
|
||||
err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
|
||||
priv->base_qpn, 1);
|
||||
else
|
||||
err = mlx4_unicast_promisc_add(mdev->dev, priv->base_qpn,
|
||||
priv->port);
|
||||
if (err)
|
||||
en_err(priv, "Failed enabling "
|
||||
"promiscous mode\n");
|
||||
@@ -252,11 +256,22 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
|
||||
en_err(priv, "Failed disabling "
|
||||
"multicast filter\n");
|
||||
|
||||
/* Add the default qp number as multicast promisc */
|
||||
if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
|
||||
err = mlx4_multicast_promisc_add(mdev->dev, priv->base_qpn,
|
||||
priv->port);
|
||||
if (err)
|
||||
en_err(priv, "Failed entering multicast promisc mode\n");
|
||||
priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
|
||||
}
|
||||
|
||||
if (priv->vlgrp) {
|
||||
/* Disable port VLAN filter */
|
||||
err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, NULL);
|
||||
if (err)
|
||||
en_err(priv, "Failed disabling VLAN filter\n");
|
||||
}
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -270,11 +285,24 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
|
||||
priv->flags &= ~MLX4_EN_FLAG_PROMISC;
|
||||
|
||||
/* Disable promiscouos mode */
|
||||
if (!mdev->dev->caps.vep_uc_steering)
|
||||
err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
|
||||
priv->base_qpn, 0);
|
||||
else
|
||||
err = mlx4_unicast_promisc_remove(mdev->dev, priv->base_qpn,
|
||||
priv->port);
|
||||
if (err)
|
||||
en_err(priv, "Failed disabling promiscous mode\n");
|
||||
|
||||
/* Disable Multicast promisc */
|
||||
if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
|
||||
err = mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn,
|
||||
priv->port);
|
||||
if (err)
|
||||
en_err(priv, "Failed disabling multicast promiscous mode\n");
|
||||
priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
|
||||
}
|
||||
|
||||
/* Enable port VLAN filter */
|
||||
err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
|
||||
if (err)
|
||||
@@ -287,14 +315,38 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
|
||||
0, MLX4_MCAST_DISABLE);
|
||||
if (err)
|
||||
en_err(priv, "Failed disabling multicast filter\n");
|
||||
|
||||
/* Add the default qp number as multicast promisc */
|
||||
if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
|
||||
err = mlx4_multicast_promisc_add(mdev->dev, priv->base_qpn,
|
||||
priv->port);
|
||||
if (err)
|
||||
en_err(priv, "Failed entering multicast promisc mode\n");
|
||||
priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
|
||||
}
|
||||
} else {
|
||||
int i;
|
||||
/* Disable Multicast promisc */
|
||||
if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
|
||||
err = mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn,
|
||||
priv->port);
|
||||
if (err)
|
||||
en_err(priv, "Failed disabling multicast promiscous mode\n");
|
||||
priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
|
||||
}
|
||||
|
||||
err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
|
||||
0, MLX4_MCAST_DISABLE);
|
||||
if (err)
|
||||
en_err(priv, "Failed disabling multicast filter\n");
|
||||
|
||||
/* Detach our qp from all the multicast addresses */
|
||||
for (i = 0; i < priv->mc_addrs_cnt; i++) {
|
||||
memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, ETH_ALEN);
|
||||
mc_list[5] = priv->port;
|
||||
mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp,
|
||||
mc_list, MLX4_PROT_ETH);
|
||||
}
|
||||
/* Flush mcast filter and init it with broadcast address */
|
||||
mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, ETH_BCAST,
|
||||
1, MLX4_MCAST_CONFIG);
|
||||
@@ -307,6 +359,10 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
|
||||
for (i = 0; i < priv->mc_addrs_cnt; i++) {
|
||||
mcast_addr =
|
||||
mlx4_en_mac_to_u64(priv->mc_addrs + i * ETH_ALEN);
|
||||
memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, ETH_ALEN);
|
||||
mc_list[5] = priv->port;
|
||||
mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp,
|
||||
mc_list, 0, MLX4_PROT_ETH);
|
||||
mlx4_SET_MCAST_FLTR(mdev->dev, priv->port,
|
||||
mcast_addr, 0, MLX4_MCAST_CONFIG);
|
||||
}
|
||||
@@ -314,8 +370,6 @@ static void mlx4_en_do_set_multicast(struct work_struct *work)
|
||||
0, MLX4_MCAST_ENABLE);
|
||||
if (err)
|
||||
en_err(priv, "Failed enabling multicast filter\n");
|
||||
|
||||
mlx4_en_clear_list(dev);
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&mdev->state_lock);
|
||||
@@ -417,7 +471,6 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
|
||||
unsigned long avg_pkt_size;
|
||||
unsigned long rx_packets;
|
||||
unsigned long rx_bytes;
|
||||
unsigned long rx_byte_diff;
|
||||
unsigned long tx_packets;
|
||||
unsigned long tx_pkt_diff;
|
||||
unsigned long rx_pkt_diff;
|
||||
@@ -441,25 +494,20 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
|
||||
rx_pkt_diff = ((unsigned long) (rx_packets -
|
||||
priv->last_moder_packets));
|
||||
packets = max(tx_pkt_diff, rx_pkt_diff);
|
||||
rx_byte_diff = rx_bytes - priv->last_moder_bytes;
|
||||
rx_byte_diff = rx_byte_diff ? rx_byte_diff : 1;
|
||||
rate = packets * HZ / period;
|
||||
avg_pkt_size = packets ? ((unsigned long) (rx_bytes -
|
||||
priv->last_moder_bytes)) / packets : 0;
|
||||
|
||||
/* Apply auto-moderation only when packet rate exceeds a rate that
|
||||
* it matters */
|
||||
if (rate > MLX4_EN_RX_RATE_THRESH) {
|
||||
if (rate > MLX4_EN_RX_RATE_THRESH && avg_pkt_size > MLX4_EN_AVG_PKT_SMALL) {
|
||||
/* If tx and rx packet rates are not balanced, assume that
|
||||
* traffic is mainly BW bound and apply maximum moderation.
|
||||
* Otherwise, moderate according to packet rate */
|
||||
if (2 * tx_pkt_diff > 3 * rx_pkt_diff &&
|
||||
rx_pkt_diff / rx_byte_diff <
|
||||
MLX4_EN_SMALL_PKT_SIZE)
|
||||
moder_time = priv->rx_usecs_low;
|
||||
else if (2 * rx_pkt_diff > 3 * tx_pkt_diff)
|
||||
if (2 * tx_pkt_diff > 3 * rx_pkt_diff ||
|
||||
2 * rx_pkt_diff > 3 * tx_pkt_diff) {
|
||||
moder_time = priv->rx_usecs_high;
|
||||
else {
|
||||
} else {
|
||||
if (rate < priv->pkt_rate_low)
|
||||
moder_time = priv->rx_usecs_low;
|
||||
else if (rate > priv->pkt_rate_high)
|
||||
@@ -471,9 +519,7 @@ static void mlx4_en_auto_moderation(struct mlx4_en_priv *priv)
|
||||
priv->rx_usecs_low;
|
||||
}
|
||||
} else {
|
||||
/* When packet rate is low, use default moderation rather than
|
||||
* 0 to prevent interrupt storms if traffic suddenly increases */
|
||||
moder_time = priv->rx_usecs;
|
||||
moder_time = priv->rx_usecs_low;
|
||||
}
|
||||
|
||||
en_dbg(INTR, priv, "tx rate:%lu rx_rate:%lu\n",
|
||||
@@ -565,6 +611,8 @@ int mlx4_en_start_port(struct net_device *dev)
|
||||
int err = 0;
|
||||
int i;
|
||||
int j;
|
||||
u8 mc_list[16] = {0};
|
||||
char name[32];
|
||||
|
||||
if (priv->port_up) {
|
||||
en_dbg(DRV, priv, "start port called while port already up\n");
|
||||
@@ -603,16 +651,35 @@ int mlx4_en_start_port(struct net_device *dev)
|
||||
++rx_index;
|
||||
}
|
||||
|
||||
/* Set port mac number */
|
||||
en_dbg(DRV, priv, "Setting mac for port %d\n", priv->port);
|
||||
err = mlx4_register_mac(mdev->dev, priv->port,
|
||||
priv->mac, &priv->base_qpn, 0);
|
||||
if (err) {
|
||||
en_err(priv, "Failed setting port mac\n");
|
||||
goto cq_err;
|
||||
}
|
||||
mdev->mac_removed[priv->port] = 0;
|
||||
|
||||
err = mlx4_en_config_rss_steer(priv);
|
||||
if (err) {
|
||||
en_err(priv, "Failed configuring rss steering\n");
|
||||
goto cq_err;
|
||||
goto mac_err;
|
||||
}
|
||||
|
||||
if (mdev->dev->caps.comp_pool && !priv->tx_vector) {
|
||||
sprintf(name , "%s-tx", priv->dev->name);
|
||||
if (mlx4_assign_eq(mdev->dev , name, &priv->tx_vector)) {
|
||||
mlx4_warn(mdev, "Failed Assigning an EQ to "
|
||||
"%s_tx ,Falling back to legacy "
|
||||
"EQ's\n", priv->dev->name);
|
||||
}
|
||||
}
|
||||
/* Configure tx cq's and rings */
|
||||
for (i = 0; i < priv->tx_ring_num; i++) {
|
||||
/* Configure cq */
|
||||
cq = &priv->tx_cq[i];
|
||||
cq->vector = priv->tx_vector;
|
||||
err = mlx4_en_activate_cq(priv, cq);
|
||||
if (err) {
|
||||
en_err(priv, "Failed allocating Tx CQ\n");
|
||||
@@ -659,24 +726,22 @@ int mlx4_en_start_port(struct net_device *dev)
|
||||
en_err(priv, "Failed setting default qp numbers\n");
|
||||
goto tx_err;
|
||||
}
|
||||
/* Set port mac number */
|
||||
en_dbg(DRV, priv, "Setting mac for port %d\n", priv->port);
|
||||
err = mlx4_register_mac(mdev->dev, priv->port,
|
||||
priv->mac, &priv->mac_index);
|
||||
if (err) {
|
||||
en_err(priv, "Failed setting port mac\n");
|
||||
goto tx_err;
|
||||
}
|
||||
mdev->mac_removed[priv->port] = 0;
|
||||
|
||||
/* Init port */
|
||||
en_dbg(HW, priv, "Initializing port\n");
|
||||
err = mlx4_INIT_PORT(mdev->dev, priv->port);
|
||||
if (err) {
|
||||
en_err(priv, "Failed Initializing port\n");
|
||||
goto mac_err;
|
||||
goto tx_err;
|
||||
}
|
||||
|
||||
/* Attach rx QP to bradcast address */
|
||||
memset(&mc_list[10], 0xff, ETH_ALEN);
|
||||
mc_list[5] = priv->port;
|
||||
if (mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
|
||||
0, MLX4_PROT_ETH))
|
||||
mlx4_warn(mdev, "Failed Attaching Broadcast\n");
|
||||
|
||||
/* Schedule multicast task to populate multicast list */
|
||||
queue_work(mdev->workqueue, &priv->mcast_task);
|
||||
|
||||
@@ -684,8 +749,6 @@ int mlx4_en_start_port(struct net_device *dev)
|
||||
netif_tx_start_all_queues(dev);
|
||||
return 0;
|
||||
|
||||
mac_err:
|
||||
mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
|
||||
tx_err:
|
||||
while (tx_index--) {
|
||||
mlx4_en_deactivate_tx_ring(priv, &priv->tx_ring[tx_index]);
|
||||
@@ -693,6 +756,8 @@ tx_err:
|
||||
}
|
||||
|
||||
mlx4_en_release_rss_steer(priv);
|
||||
mac_err:
|
||||
mlx4_unregister_mac(mdev->dev, priv->port, priv->base_qpn);
|
||||
cq_err:
|
||||
while (rx_index--)
|
||||
mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]);
|
||||
@@ -708,6 +773,7 @@ void mlx4_en_stop_port(struct net_device *dev)
|
||||
struct mlx4_en_priv *priv = netdev_priv(dev);
|
||||
struct mlx4_en_dev *mdev = priv->mdev;
|
||||
int i;
|
||||
u8 mc_list[16] = {0};
|
||||
|
||||
if (!priv->port_up) {
|
||||
en_dbg(DRV, priv, "stop port called while port already down\n");
|
||||
@@ -722,8 +788,23 @@ void mlx4_en_stop_port(struct net_device *dev)
|
||||
/* Set port as not active */
|
||||
priv->port_up = false;
|
||||
|
||||
/* Detach All multicasts */
|
||||
memset(&mc_list[10], 0xff, ETH_ALEN);
|
||||
mc_list[5] = priv->port;
|
||||
mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
|
||||
MLX4_PROT_ETH);
|
||||
for (i = 0; i < priv->mc_addrs_cnt; i++) {
|
||||
memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, ETH_ALEN);
|
||||
mc_list[5] = priv->port;
|
||||
mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp,
|
||||
mc_list, MLX4_PROT_ETH);
|
||||
}
|
||||
mlx4_en_clear_list(dev);
|
||||
/* Flush multicast filter */
|
||||
mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG);
|
||||
|
||||
/* Unregister Mac address for the port */
|
||||
mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
|
||||
mlx4_unregister_mac(mdev->dev, priv->port, priv->base_qpn);
|
||||
mdev->mac_removed[priv->port] = 1;
|
||||
|
||||
/* Free TX Rings */
|
||||
@@ -801,7 +882,6 @@ static int mlx4_en_open(struct net_device *dev)
|
||||
priv->rx_ring[i].packets = 0;
|
||||
}
|
||||
|
||||
mlx4_en_set_default_moderation(priv);
|
||||
err = mlx4_en_start_port(dev);
|
||||
if (err)
|
||||
en_err(priv, "Failed starting port:%d\n", priv->port);
|
||||
@@ -828,7 +908,7 @@ static int mlx4_en_close(struct net_device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mlx4_en_free_resources(struct mlx4_en_priv *priv)
|
||||
void mlx4_en_free_resources(struct mlx4_en_priv *priv, bool reserve_vectors)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -836,14 +916,14 @@ void mlx4_en_free_resources(struct mlx4_en_priv *priv)
|
||||
if (priv->tx_ring[i].tx_info)
|
||||
mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]);
|
||||
if (priv->tx_cq[i].buf)
|
||||
mlx4_en_destroy_cq(priv, &priv->tx_cq[i]);
|
||||
mlx4_en_destroy_cq(priv, &priv->tx_cq[i], reserve_vectors);
|
||||
}
|
||||
|
||||
for (i = 0; i < priv->rx_ring_num; i++) {
|
||||
if (priv->rx_ring[i].rx_info)
|
||||
mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i]);
|
||||
if (priv->rx_cq[i].buf)
|
||||
mlx4_en_destroy_cq(priv, &priv->rx_cq[i]);
|
||||
mlx4_en_destroy_cq(priv, &priv->rx_cq[i], reserve_vectors);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -851,6 +931,13 @@ int mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
|
||||
{
|
||||
struct mlx4_en_port_profile *prof = priv->prof;
|
||||
int i;
|
||||
int base_tx_qpn, err;
|
||||
|
||||
err = mlx4_qp_reserve_range(priv->mdev->dev, priv->tx_ring_num, 256, &base_tx_qpn);
|
||||
if (err) {
|
||||
en_err(priv, "failed reserving range for TX rings\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Create tx Rings */
|
||||
for (i = 0; i < priv->tx_ring_num; i++) {
|
||||
@@ -858,7 +945,7 @@ int mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
|
||||
prof->tx_ring_size, i, TX))
|
||||
goto err;
|
||||
|
||||
if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[i],
|
||||
if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[i], base_tx_qpn + i,
|
||||
prof->tx_ring_size, TXBB_SIZE))
|
||||
goto err;
|
||||
}
|
||||
@@ -878,6 +965,7 @@ int mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
|
||||
|
||||
err:
|
||||
en_err(priv, "Failed to allocate NIC resources\n");
|
||||
mlx4_qp_release_range(priv->mdev->dev, base_tx_qpn, priv->tx_ring_num);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@@ -905,7 +993,7 @@ void mlx4_en_destroy_netdev(struct net_device *dev)
|
||||
mdev->pndev[priv->port] = NULL;
|
||||
mutex_unlock(&mdev->state_lock);
|
||||
|
||||
mlx4_en_free_resources(priv);
|
||||
mlx4_en_free_resources(priv, false);
|
||||
free_netdev(dev);
|
||||
}
|
||||
|
||||
@@ -932,7 +1020,6 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
|
||||
en_dbg(DRV, priv, "Change MTU called with card down!?\n");
|
||||
} else {
|
||||
mlx4_en_stop_port(dev);
|
||||
mlx4_en_set_default_moderation(priv);
|
||||
err = mlx4_en_start_port(dev);
|
||||
if (err) {
|
||||
en_err(priv, "Failed restarting port:%d\n",
|
||||
@@ -1079,7 +1166,25 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
|
||||
en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num);
|
||||
en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
|
||||
|
||||
/* Configure port */
|
||||
err = mlx4_SET_PORT_general(mdev->dev, priv->port,
|
||||
MLX4_EN_MIN_MTU,
|
||||
0, 0, 0, 0);
|
||||
if (err) {
|
||||
en_err(priv, "Failed setting port general configurations "
|
||||
"for port %d, with error %d\n", priv->port, err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Init port */
|
||||
en_warn(priv, "Initializing port\n");
|
||||
err = mlx4_INIT_PORT(mdev->dev, priv->port);
|
||||
if (err) {
|
||||
en_err(priv, "Failed Initializing port\n");
|
||||
goto out;
|
||||
}
|
||||
priv->registered = 1;
|
||||
mlx4_en_set_default_moderation(priv);
|
||||
queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -119,6 +119,10 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
|
||||
struct mlx4_set_port_rqp_calc_context *context;
|
||||
int err;
|
||||
u32 in_mod;
|
||||
u32 m_promisc = (dev->caps.vep_mc_steering) ? MCAST_DIRECT : MCAST_DEFAULT;
|
||||
|
||||
if (dev->caps.vep_mc_steering && dev->caps.vep_uc_steering)
|
||||
return 0;
|
||||
|
||||
mailbox = mlx4_alloc_cmd_mailbox(dev);
|
||||
if (IS_ERR(mailbox))
|
||||
@@ -127,8 +131,11 @@ int mlx4_SET_PORT_qpn_calc(struct mlx4_dev *dev, u8 port, u32 base_qpn,
|
||||
memset(context, 0, sizeof *context);
|
||||
|
||||
context->base_qpn = cpu_to_be32(base_qpn);
|
||||
context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_EN_SHIFT | base_qpn);
|
||||
context->mcast = cpu_to_be32(1 << SET_PORT_PROMISC_MODE_SHIFT | base_qpn);
|
||||
context->n_mac = 0x7;
|
||||
context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT |
|
||||
base_qpn);
|
||||
context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT |
|
||||
base_qpn);
|
||||
context->intra_no_vlan = 0;
|
||||
context->no_vlan = MLX4_NO_VLAN_IDX;
|
||||
context->intra_vlan_miss = 0;
|
||||
@@ -206,7 +213,7 @@ int mlx4_en_DUMP_ETH_STATS(struct mlx4_en_dev *mdev, u8 port, u8 reset)
|
||||
}
|
||||
stats->tx_packets = 0;
|
||||
stats->tx_bytes = 0;
|
||||
for (i = 0; i <= priv->tx_ring_num; i++) {
|
||||
for (i = 0; i < priv->tx_ring_num; i++) {
|
||||
stats->tx_packets += priv->tx_ring[i].packets;
|
||||
stats->tx_bytes += priv->tx_ring[i].bytes;
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@
|
||||
|
||||
|
||||
#define SET_PORT_GEN_ALL_VALID 0x7
|
||||
#define SET_PORT_PROMISC_EN_SHIFT 31
|
||||
#define SET_PORT_PROMISC_MODE_SHIFT 30
|
||||
#define SET_PORT_PROMISC_SHIFT 31
|
||||
#define SET_PORT_MC_PROMISC_SHIFT 30
|
||||
|
||||
enum {
|
||||
MLX4_CMD_SET_VLAN_FLTR = 0x47,
|
||||
@@ -45,6 +45,12 @@ enum {
|
||||
MLX4_CMD_DUMP_ETH_STATS = 0x49,
|
||||
};
|
||||
|
||||
enum {
|
||||
MCAST_DIRECT_ONLY = 0,
|
||||
MCAST_DIRECT = 1,
|
||||
MCAST_DEFAULT = 2
|
||||
};
|
||||
|
||||
struct mlx4_set_port_general_context {
|
||||
u8 reserved[3];
|
||||
u8 flags;
|
||||
@@ -60,14 +66,17 @@ struct mlx4_set_port_general_context {
|
||||
|
||||
struct mlx4_set_port_rqp_calc_context {
|
||||
__be32 base_qpn;
|
||||
__be32 flags;
|
||||
u8 reserved[3];
|
||||
u8 rererved;
|
||||
u8 n_mac;
|
||||
u8 n_vlan;
|
||||
u8 n_prio;
|
||||
u8 reserved2[3];
|
||||
u8 mac_miss;
|
||||
u8 intra_no_vlan;
|
||||
u8 no_vlan;
|
||||
u8 intra_vlan_miss;
|
||||
u8 vlan_miss;
|
||||
u8 reserved2[3];
|
||||
u8 reserved3[3];
|
||||
u8 no_vlan_prio;
|
||||
__be32 promisc;
|
||||
__be32 mcast;
|
||||
|
||||
@@ -845,16 +845,10 @@ int mlx4_en_config_rss_steer(struct mlx4_en_priv *priv)
|
||||
}
|
||||
|
||||
/* Configure RSS indirection qp */
|
||||
err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &priv->base_qpn);
|
||||
if (err) {
|
||||
en_err(priv, "Failed to reserve range for RSS "
|
||||
"indirection qp\n");
|
||||
goto rss_err;
|
||||
}
|
||||
err = mlx4_qp_alloc(mdev->dev, priv->base_qpn, &rss_map->indir_qp);
|
||||
if (err) {
|
||||
en_err(priv, "Failed to allocate RSS indirection QP\n");
|
||||
goto reserve_err;
|
||||
goto rss_err;
|
||||
}
|
||||
rss_map->indir_qp.event = mlx4_en_sqp_event;
|
||||
mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn,
|
||||
@@ -881,8 +875,6 @@ indir_err:
|
||||
MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp);
|
||||
mlx4_qp_remove(mdev->dev, &rss_map->indir_qp);
|
||||
mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
|
||||
reserve_err:
|
||||
mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1);
|
||||
rss_err:
|
||||
for (i = 0; i < good_qps; i++) {
|
||||
mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
|
||||
@@ -904,7 +896,6 @@ void mlx4_en_release_rss_steer(struct mlx4_en_priv *priv)
|
||||
MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp);
|
||||
mlx4_qp_remove(mdev->dev, &rss_map->indir_qp);
|
||||
mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
|
||||
mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1);
|
||||
|
||||
for (i = 0; i < priv->rx_ring_num; i++) {
|
||||
mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
|
||||
|
||||
+47
-15
@@ -44,6 +44,7 @@
|
||||
|
||||
enum {
|
||||
MAX_INLINE = 104, /* 128 - 16 - 4 - 4 */
|
||||
MAX_BF = 256,
|
||||
};
|
||||
|
||||
static int inline_thold __read_mostly = MAX_INLINE;
|
||||
@@ -52,7 +53,7 @@ module_param_named(inline_thold, inline_thold, int, 0444);
|
||||
MODULE_PARM_DESC(inline_thold, "threshold for using inline data");
|
||||
|
||||
int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_tx_ring *ring, u32 size,
|
||||
struct mlx4_en_tx_ring *ring, int qpn, u32 size,
|
||||
u16 stride)
|
||||
{
|
||||
struct mlx4_en_dev *mdev = priv->mdev;
|
||||
@@ -103,23 +104,25 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
|
||||
"buf_size:%d dma:%llx\n", ring, ring->buf, ring->size,
|
||||
ring->buf_size, (unsigned long long) ring->wqres.buf.direct.map);
|
||||
|
||||
err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &ring->qpn);
|
||||
if (err) {
|
||||
en_err(priv, "Failed reserving qp for tx ring.\n");
|
||||
goto err_map;
|
||||
}
|
||||
|
||||
ring->qpn = qpn;
|
||||
err = mlx4_qp_alloc(mdev->dev, ring->qpn, &ring->qp);
|
||||
if (err) {
|
||||
en_err(priv, "Failed allocating qp %d\n", ring->qpn);
|
||||
goto err_reserve;
|
||||
goto err_map;
|
||||
}
|
||||
ring->qp.event = mlx4_en_sqp_event;
|
||||
|
||||
err = mlx4_bf_alloc(mdev->dev, &ring->bf);
|
||||
if (err) {
|
||||
en_dbg(DRV, priv, "working without blueflame (%d)", err);
|
||||
ring->bf.uar = &mdev->priv_uar;
|
||||
ring->bf.uar->map = mdev->uar_map;
|
||||
ring->bf_enabled = false;
|
||||
} else
|
||||
ring->bf_enabled = true;
|
||||
|
||||
return 0;
|
||||
|
||||
err_reserve:
|
||||
mlx4_qp_release_range(mdev->dev, ring->qpn, 1);
|
||||
err_map:
|
||||
mlx4_en_unmap_buffer(&ring->wqres.buf);
|
||||
err_hwq_res:
|
||||
@@ -139,6 +142,8 @@ void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv,
|
||||
struct mlx4_en_dev *mdev = priv->mdev;
|
||||
en_dbg(DRV, priv, "Destroying tx ring, qpn: %d\n", ring->qpn);
|
||||
|
||||
if (ring->bf_enabled)
|
||||
mlx4_bf_free(mdev->dev, &ring->bf);
|
||||
mlx4_qp_remove(mdev->dev, &ring->qp);
|
||||
mlx4_qp_free(mdev->dev, &ring->qp);
|
||||
mlx4_qp_release_range(mdev->dev, ring->qpn, 1);
|
||||
@@ -171,6 +176,8 @@ int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
|
||||
|
||||
mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn,
|
||||
ring->cqn, &ring->context);
|
||||
if (ring->bf_enabled)
|
||||
ring->context.usr_page = cpu_to_be32(ring->bf.uar->index);
|
||||
|
||||
err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context,
|
||||
&ring->qp, &ring->qp_state);
|
||||
@@ -591,6 +598,11 @@ u16 mlx4_en_select_queue(struct net_device *dev, struct sk_buff *skb)
|
||||
return skb_tx_hash(dev, skb);
|
||||
}
|
||||
|
||||
static void mlx4_bf_copy(unsigned long *dst, unsigned long *src, unsigned bytecnt)
|
||||
{
|
||||
__iowrite64_copy(dst, src, bytecnt / 8);
|
||||
}
|
||||
|
||||
netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct mlx4_en_priv *priv = netdev_priv(dev);
|
||||
@@ -609,12 +621,13 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
int desc_size;
|
||||
int real_size;
|
||||
dma_addr_t dma;
|
||||
u32 index;
|
||||
u32 index, bf_index;
|
||||
__be32 op_own;
|
||||
u16 vlan_tag = 0;
|
||||
int i;
|
||||
int lso_header_size;
|
||||
void *fragptr;
|
||||
bool bounce = false;
|
||||
|
||||
if (!priv->port_up)
|
||||
goto tx_drop;
|
||||
@@ -657,13 +670,16 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
/* Packet is good - grab an index and transmit it */
|
||||
index = ring->prod & ring->size_mask;
|
||||
bf_index = ring->prod;
|
||||
|
||||
/* See if we have enough space for whole descriptor TXBB for setting
|
||||
* SW ownership on next descriptor; if not, use a bounce buffer. */
|
||||
if (likely(index + nr_txbb <= ring->size))
|
||||
tx_desc = ring->buf + index * TXBB_SIZE;
|
||||
else
|
||||
else {
|
||||
tx_desc = (struct mlx4_en_tx_desc *) ring->bounce_buf;
|
||||
bounce = true;
|
||||
}
|
||||
|
||||
/* Save skb in tx_info ring */
|
||||
tx_info = &ring->tx_info[index];
|
||||
@@ -768,21 +784,37 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
ring->prod += nr_txbb;
|
||||
|
||||
/* If we used a bounce buffer then copy descriptor back into place */
|
||||
if (tx_desc == (struct mlx4_en_tx_desc *) ring->bounce_buf)
|
||||
if (bounce)
|
||||
tx_desc = mlx4_en_bounce_to_desc(priv, ring, index, desc_size);
|
||||
|
||||
/* Run destructor before passing skb to HW */
|
||||
if (likely(!skb_shared(skb)))
|
||||
skb_orphan(skb);
|
||||
|
||||
if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tag) {
|
||||
*(u32 *) (&tx_desc->ctrl.vlan_tag) |= ring->doorbell_qpn;
|
||||
op_own |= htonl((bf_index & 0xffff) << 8);
|
||||
/* Ensure new descirptor hits memory
|
||||
* before setting ownership of this descriptor to HW */
|
||||
wmb();
|
||||
tx_desc->ctrl.owner_opcode = op_own;
|
||||
|
||||
/* Ring doorbell! */
|
||||
wmb();
|
||||
writel(ring->doorbell_qpn, mdev->uar_map + MLX4_SEND_DOORBELL);
|
||||
|
||||
mlx4_bf_copy(ring->bf.reg + ring->bf.offset, (unsigned long *) &tx_desc->ctrl,
|
||||
desc_size);
|
||||
|
||||
wmb();
|
||||
|
||||
ring->bf.offset ^= ring->bf.buf_size;
|
||||
} else {
|
||||
/* Ensure new descirptor hits memory
|
||||
* before setting ownership of this descriptor to HW */
|
||||
wmb();
|
||||
tx_desc->ctrl.owner_opcode = op_own;
|
||||
wmb();
|
||||
writel(ring->doorbell_qpn, ring->bf.uar->map + MLX4_SEND_DOORBELL);
|
||||
}
|
||||
|
||||
/* Poll CQ here */
|
||||
mlx4_en_xmit_poll(priv, tx_ind);
|
||||
|
||||
+101
-6
@@ -42,7 +42,7 @@
|
||||
#include "fw.h"
|
||||
|
||||
enum {
|
||||
MLX4_IRQNAME_SIZE = 64
|
||||
MLX4_IRQNAME_SIZE = 32
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -317,8 +317,8 @@ static int mlx4_num_eq_uar(struct mlx4_dev *dev)
|
||||
* we need to map, take the difference of highest index and
|
||||
* the lowest index we'll use and add 1.
|
||||
*/
|
||||
return (dev->caps.num_comp_vectors + 1 + dev->caps.reserved_eqs) / 4 -
|
||||
dev->caps.reserved_eqs / 4 + 1;
|
||||
return (dev->caps.num_comp_vectors + 1 + dev->caps.reserved_eqs +
|
||||
dev->caps.comp_pool)/4 - dev->caps.reserved_eqs/4 + 1;
|
||||
}
|
||||
|
||||
static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq)
|
||||
@@ -496,16 +496,32 @@ static void mlx4_free_eq(struct mlx4_dev *dev,
|
||||
static void mlx4_free_irqs(struct mlx4_dev *dev)
|
||||
{
|
||||
struct mlx4_eq_table *eq_table = &mlx4_priv(dev)->eq_table;
|
||||
int i;
|
||||
struct mlx4_priv *priv = mlx4_priv(dev);
|
||||
int i, vec;
|
||||
|
||||
if (eq_table->have_irq)
|
||||
free_irq(dev->pdev->irq, dev);
|
||||
|
||||
for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i)
|
||||
if (eq_table->eq[i].have_irq) {
|
||||
free_irq(eq_table->eq[i].irq, eq_table->eq + i);
|
||||
eq_table->eq[i].have_irq = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->caps.comp_pool; i++) {
|
||||
/*
|
||||
* Freeing the assigned irq's
|
||||
* all bits should be 0, but we need to validate
|
||||
*/
|
||||
if (priv->msix_ctl.pool_bm & 1ULL << i) {
|
||||
/* NO need protecting*/
|
||||
vec = dev->caps.num_comp_vectors + 1 + i;
|
||||
free_irq(priv->eq_table.eq[vec].irq,
|
||||
&priv->eq_table.eq[vec]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
kfree(eq_table->irq_names);
|
||||
}
|
||||
|
||||
@@ -578,7 +594,8 @@ int mlx4_init_eq_table(struct mlx4_dev *dev)
|
||||
(priv->eq_table.inta_pin < 32 ? 4 : 0);
|
||||
|
||||
priv->eq_table.irq_names =
|
||||
kmalloc(MLX4_IRQNAME_SIZE * (dev->caps.num_comp_vectors + 1),
|
||||
kmalloc(MLX4_IRQNAME_SIZE * (dev->caps.num_comp_vectors + 1 +
|
||||
dev->caps.comp_pool),
|
||||
GFP_KERNEL);
|
||||
if (!priv->eq_table.irq_names) {
|
||||
err = -ENOMEM;
|
||||
@@ -601,6 +618,22 @@ int mlx4_init_eq_table(struct mlx4_dev *dev)
|
||||
if (err)
|
||||
goto err_out_comp;
|
||||
|
||||
/*if additional completion vectors poolsize is 0 this loop will not run*/
|
||||
for (i = dev->caps.num_comp_vectors + 1;
|
||||
i < dev->caps.num_comp_vectors + dev->caps.comp_pool + 1; ++i) {
|
||||
|
||||
err = mlx4_create_eq(dev, dev->caps.num_cqs -
|
||||
dev->caps.reserved_cqs +
|
||||
MLX4_NUM_SPARE_EQE,
|
||||
(dev->flags & MLX4_FLAG_MSI_X) ? i : 0,
|
||||
&priv->eq_table.eq[i]);
|
||||
if (err) {
|
||||
--i;
|
||||
goto err_out_unmap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (dev->flags & MLX4_FLAG_MSI_X) {
|
||||
const char *eq_name;
|
||||
|
||||
@@ -686,7 +719,7 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev)
|
||||
|
||||
mlx4_free_irqs(dev);
|
||||
|
||||
for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i)
|
||||
for (i = 0; i < dev->caps.num_comp_vectors + dev->caps.comp_pool + 1; ++i)
|
||||
mlx4_free_eq(dev, &priv->eq_table.eq[i]);
|
||||
|
||||
mlx4_unmap_clr_int(dev);
|
||||
@@ -743,3 +776,65 @@ int mlx4_test_interrupts(struct mlx4_dev *dev)
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(mlx4_test_interrupts);
|
||||
|
||||
int mlx4_assign_eq(struct mlx4_dev *dev, char* name, int * vector)
|
||||
{
|
||||
|
||||
struct mlx4_priv *priv = mlx4_priv(dev);
|
||||
int vec = 0, err = 0, i;
|
||||
|
||||
spin_lock(&priv->msix_ctl.pool_lock);
|
||||
for (i = 0; !vec && i < dev->caps.comp_pool; i++) {
|
||||
if (~priv->msix_ctl.pool_bm & 1ULL << i) {
|
||||
priv->msix_ctl.pool_bm |= 1ULL << i;
|
||||
vec = dev->caps.num_comp_vectors + 1 + i;
|
||||
snprintf(priv->eq_table.irq_names +
|
||||
vec * MLX4_IRQNAME_SIZE,
|
||||
MLX4_IRQNAME_SIZE, "%s", name);
|
||||
err = request_irq(priv->eq_table.eq[vec].irq,
|
||||
mlx4_msi_x_interrupt, 0,
|
||||
&priv->eq_table.irq_names[vec<<5],
|
||||
priv->eq_table.eq + vec);
|
||||
if (err) {
|
||||
/*zero out bit by fliping it*/
|
||||
priv->msix_ctl.pool_bm ^= 1 << i;
|
||||
vec = 0;
|
||||
continue;
|
||||
/*we dont want to break here*/
|
||||
}
|
||||
eq_set_ci(&priv->eq_table.eq[vec], 1);
|
||||
}
|
||||
}
|
||||
spin_unlock(&priv->msix_ctl.pool_lock);
|
||||
|
||||
if (vec) {
|
||||
*vector = vec;
|
||||
} else {
|
||||
*vector = 0;
|
||||
err = (i == dev->caps.comp_pool) ? -ENOSPC : err;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(mlx4_assign_eq);
|
||||
|
||||
void mlx4_release_eq(struct mlx4_dev *dev, int vec)
|
||||
{
|
||||
struct mlx4_priv *priv = mlx4_priv(dev);
|
||||
/*bm index*/
|
||||
int i = vec - dev->caps.num_comp_vectors - 1;
|
||||
|
||||
if (likely(i >= 0)) {
|
||||
/*sanity check , making sure were not trying to free irq's
|
||||
Belonging to a legacy EQ*/
|
||||
spin_lock(&priv->msix_ctl.pool_lock);
|
||||
if (priv->msix_ctl.pool_bm & 1ULL << i) {
|
||||
free_irq(priv->eq_table.eq[vec].irq,
|
||||
&priv->eq_table.eq[vec]);
|
||||
priv->msix_ctl.pool_bm &= ~(1ULL << i);
|
||||
}
|
||||
spin_unlock(&priv->msix_ctl.pool_lock);
|
||||
}
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(mlx4_release_eq);
|
||||
|
||||
|
||||
@@ -274,8 +274,11 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
|
||||
dev_cap->stat_rate_support = stat_rate;
|
||||
MLX4_GET(field, outbox, QUERY_DEV_CAP_UDP_RSS_OFFSET);
|
||||
dev_cap->udp_rss = field & 0x1;
|
||||
dev_cap->vep_uc_steering = field & 0x2;
|
||||
dev_cap->vep_mc_steering = field & 0x4;
|
||||
MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET);
|
||||
dev_cap->loopback_support = field & 0x1;
|
||||
dev_cap->wol = field & 0x40;
|
||||
MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
|
||||
MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET);
|
||||
dev_cap->reserved_uars = field >> 4;
|
||||
@@ -737,6 +740,7 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
|
||||
#define INIT_HCA_MC_BASE_OFFSET (INIT_HCA_MCAST_OFFSET + 0x00)
|
||||
#define INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x12)
|
||||
#define INIT_HCA_LOG_MC_HASH_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x16)
|
||||
#define INIT_HCA_UC_STEERING_OFFSET (INIT_HCA_MCAST_OFFSET + 0x18)
|
||||
#define INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b)
|
||||
#define INIT_HCA_TPT_OFFSET 0x0f0
|
||||
#define INIT_HCA_DMPT_BASE_OFFSET (INIT_HCA_TPT_OFFSET + 0x00)
|
||||
@@ -797,6 +801,8 @@ int mlx4_INIT_HCA(struct mlx4_dev *dev, struct mlx4_init_hca_param *param)
|
||||
MLX4_PUT(inbox, param->mc_base, INIT_HCA_MC_BASE_OFFSET);
|
||||
MLX4_PUT(inbox, param->log_mc_entry_sz, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
|
||||
MLX4_PUT(inbox, param->log_mc_hash_sz, INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
|
||||
if (dev->caps.vep_mc_steering)
|
||||
MLX4_PUT(inbox, (u8) (1 << 3), INIT_HCA_UC_STEERING_OFFSET);
|
||||
MLX4_PUT(inbox, param->log_mc_table_sz, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
|
||||
|
||||
/* TPT attributes */
|
||||
@@ -908,3 +914,22 @@ int mlx4_NOP(struct mlx4_dev *dev)
|
||||
/* Input modifier of 0x1f means "finish as soon as possible." */
|
||||
return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, 100);
|
||||
}
|
||||
|
||||
#define MLX4_WOL_SETUP_MODE (5 << 28)
|
||||
int mlx4_wol_read(struct mlx4_dev *dev, u64 *config, int port)
|
||||
{
|
||||
u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8;
|
||||
|
||||
return mlx4_cmd_imm(dev, 0, config, in_mod, 0x3,
|
||||
MLX4_CMD_MOD_STAT_CFG, MLX4_CMD_TIME_CLASS_A);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx4_wol_read);
|
||||
|
||||
int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port)
|
||||
{
|
||||
u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8;
|
||||
|
||||
return mlx4_cmd(dev, config, in_mod, 0x1, MLX4_CMD_MOD_STAT_CFG,
|
||||
MLX4_CMD_TIME_CLASS_A);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mlx4_wol_write);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user