aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYevgeny Petrilin <yevgenyp@mellanox.com>2013-07-28 11:54:21 -0400
committerDavid S. Miller <davem@davemloft.net>2013-07-29 04:12:40 -0400
commitfe6f700d6cbb7e8a61711e325f53d9c9e0a42a4c (patch)
tree1a3d5b95434519950cb10ed9e51b50c2583e53fd
parent2d4b646613d6b12175b017aca18113945af1faf3 (diff)
net/mlx4_core: Respond to operation request by firmware
This commit adds new firmware command and new firmware event. The firmware raises the MLX4_EVENT_TYPE_OP_REQUIRED event in order to signal the driver it needs to perform an administrative operation throughout the MLX4_CMD_GET_OP_REQ command. At the moment the supported operation is adding/removing multicast entries which are used by the firmware for handling NCSI traffic in B0 steering mode. Also, had to swap the order of mlx4_init_mcg_table() and mlx4_init_eq_table() to make sure that driver will get events only after resources are initialized to handle it. Signed-off-by: Yevgeny Petrilin <yevgenyp@mellanox.com> Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.com> Signed-off-by: Eugenia Emantayev <eugenia@mellanox.com> Signed-off-by: Amir Vadai <amirv@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c18
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/eq.c9
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.c104
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/fw.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c35
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mcg.c11
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/mlx4.h13
-rw-r--r--include/linux/mlx4/cmd.h1
-rw-r--r--include/linux/mlx4/device.h1
9 files changed, 166 insertions, 27 deletions
</
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index 299d0184f983..141322c31ae9 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -809,6 +809,15 @@ int MLX4_CMD_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave,
809 return -EPERM; 809 return -EPERM;
810} 810}
811 811
812int MLX4_CMD_GET_OP_REQ_wrapper(struct mlx4_dev *dev, int slave,
813 struct mlx4_vhcr *vhcr,
814 struct mlx4_cmd_mailbox *inbox,
815 struct mlx4_cmd_mailbox *outbox,
816 struct mlx4_cmd_info *cmd)
817{
818 return -EPERM;
819}
820
812int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave, 821int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave,
813 struct mlx4_vhcr *vhcr, 822 struct mlx4_vhcr *vhcr,
814 struct mlx4_cmd_mailbox *inbox, 823 struct mlx4_cmd_mailbox *inbox,
@@ -1252,6 +1261,15 @@ static struct mlx4_cmd_info cmd_info[] = {
1252 .wrapper = MLX4_CMD_UPDATE_QP_wrapper 1261 .wrapper = MLX4_CMD_UPDATE_QP_wrapper
1253 }, 1262 },
1254 { 1263 {
1264 .opcode = MLX4_CMD_GET_OP_REQ,
1265 .has_inbox = false,
1266 .has_outbox = false,
1267 .out_is_imm = false,
1268 .encode_slave_id = false,
1269 .verify = NULL,
1270 .wrapper = MLX4_CMD_GET_OP_REQ_wrapper,
1271 },
1272 {
1255 .opcode = MLX4_CMD_CONF_SPECIAL_QP, 1273 .opcode = MLX4_CMD_CONF_SPECIAL_QP,
1256 .has_inbox = false, 1274 .has_inbox = false,
1257 .has_outbox = false, 1275 .has_outbox = false,
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
index 7e042869ef0c..0416c5b3b35c 100644
--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -79,6 +79,7 @@ enum {
79 (1ull << MLX4_EVENT_TYPE_SRQ_QP_LAST_WQE) | \ 79 (1ull << MLX4_EVENT_TYPE_SRQ_QP_LAST_WQE) | \
80 (1ull << MLX4_EVENT_TYPE_SRQ_LIMIT) | \ 80 (1ull << MLX4_EVENT_TYPE_SRQ_LIMIT) | \
81 (1ull << MLX4_EVENT_TYPE_CMD) | \ 81 (1ull << MLX4_EVENT_TYPE_CMD) | \
82 (1ull << MLX4_EVENT_TYPE_OP_REQUIRED) | \
82 (1ull << MLX4_EVENT_TYPE_COMM_CHANNEL) | \ 83 (1ull << MLX4_EVENT_TYPE_COMM_CHANNEL) | \
83 (1ull << MLX4_EVENT_TYPE_FLR_EVENT) | \ 84 (1ull << MLX4_EVENT_TYPE_FLR_EVENT) | \
84 (1ull << MLX4_EVENT_TYPE_FATAL_WARNING)) 85 (1ull << MLX4_EVENT_TYPE_FATAL_WARNING))
@@ -629,6 +630,14 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
629 mlx4_warn(dev, "EQ overrun on EQN %d\n", eq->eqn); 630 mlx4_warn(dev, "EQ overrun on EQN %d\n", eq->eqn);
630 break; 631 break;
631 632
633 case MLX4_EVENT_TYPE_OP_REQUIRED:
634 atomic_inc(&priv->opreq_count);
635 /* FW commands can't be executed from interrupt context
636 * working in deferred task
637 */
638 queue_work(mlx4_wq, &priv->opreq_task);
639 break;
640
632 case MLX4_EVENT_TYPE_COMM_CHANNEL: 641 case MLX4_EVENT_TYPE_COMM_CHANNEL:
633 if (!mlx4_is_master(dev)) { 642 if (!mlx4_is_master(dev)) {
634 mlx4_warn(dev, "Received comm channel event " 643 mlx4_warn(dev, "Received comm channel event "
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c
index 8873d6802c80..aec6f5802da5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/fw.c
+++ b/drivers/net/ethernet/mellanox/mlx4/fw.c
@@ -1705,3 +1705,107 @@ int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port)
1705 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 1705 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
1706} 1706}
1707EXPORT_SYMBOL_GPL(mlx4_wol_write); 1707EXPORT_SYMBOL_GPL(mlx4_wol_write);
1708
1709enum {
1710 ADD_TO_MCG = 0x26,
1711};
1712
1713
1714void mlx4_opreq_action(struct work_struct *work)
1715{
1716 struct mlx4_priv *priv = container_of(work, struct mlx4_priv,
1717 opreq_task);
1718 struct mlx4_dev *dev = &priv->dev;
1719 int num_tasks = atomic_read(&priv->opreq_count);
1720 struct mlx4_cmd_mailbox *mailbox;
1721 struct mlx4_mgm *mgm;
1722 u32 *outbox;
1723 u32 modifier;
1724 u16 token;
1725 u16 type_m;
1726 u16 type;
1727 int err;
1728 u32 num_qps;
1729 struct mlx4_qp qp;
1730 int i;
1731 u8 rem_mcg;
1732 u8 prot;
1733
1734#define GET_OP_REQ_MODIFIER_OFFSET 0x08
1735#define GET_OP_REQ_TOKEN_OFFSET 0x14
1736#define GET_OP_REQ_TYPE_OFFSET 0x1a
1737#define GET_OP_REQ_DATA_OFFSET 0x20
1738
1739 mailbox = mlx4_alloc_cmd_mailbox(dev);
1740 if (IS_ERR(mailbox)) {
1741 mlx4_err(dev, "Failed to allocate mailbox for GET_OP_REQ\n");
1742 return;
1743 }
1744 outbox = mailbox->buf;
1745
1746 while (num_tasks) {
1747 err = mlx4_cmd_box(dev, 0, mailbox->dma, 0, 0,
1748 MLX4_CMD_GET_OP_REQ, MLX4_CMD_TIME_CLASS_A,
1749 MLX4_CMD_NATIVE);
1750 if (err) {
1751 mlx4_err(dev, "Failed to retreive required operation: %d\n",
1752 err);
1753 return;
1754 }
1755 MLX4_GET(modifier, outbox, GET_OP_REQ_MODIFIER_OFFSET);
1756 MLX4_GET(token, outbox, GET_OP_REQ_TOKEN_OFFSET);
1757 MLX4_GET(type, outbox, GET_OP_REQ_TYPE_OFFSET);
1758 type_m = type >> 12;
1759 type &= 0xfff;
1760
1761 switch (type) {
1762 case ADD_TO_MCG:
1763 if (dev->caps.steering_mode ==
1764 MLX4_STEERING_MODE_DEVICE_MANAGED) {
1765 mlx4_warn(dev, "ADD MCG operation is not supported in DEVICE_MANAGED steering mode\n");
1766 err = EPERM;
1767 break;
1768 }
1769 mgm = (struct mlx4_mgm *)((u8 *)(outbox) +
1770 GET_OP_REQ_DATA_OFFSET);
1771 num_qps = be32_to_cpu(mgm->members_count) &
1772 MGM_QPN_MASK;
1773 rem_mcg = ((u8 *)(&mgm->members_count))[0] & 1;
1774 prot = ((u8 *)(&mgm->members_count))[0] >> 6;
1775
1776 for (i = 0; i < num_qps; i++) {
1777 qp.qpn = be32_to_cpu(mgm->qp[i]);
1778 if (rem_mcg)
1779 err = mlx4_multicast_detach(dev, &qp,
1780 mgm->gid,
1781 prot, 0);
1782 else
1783 err = mlx4_multicast_attach(dev, &qp,
1784 mgm->gid,
1785 mgm->gid[5]
1786 , 0, prot,
1787 NULL);
1788 if (err)
1789 break;
1790 }
1791 break;
1792 default:
1793 mlx4_warn(dev, "Bad type for required operation\n");
1794 err = EINVAL;
1795 break;
1796 }