aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorJack Morgenstein <jackm@dev.mellanox.co.il>2012-08-03 04:40:45 -0400
committerRoland Dreier <roland@purestorage.com>2012-09-30 23:33:34 -0400
commit0a9a01884d447c216eff75f8f274a0a3e82c7cee (patch)
treec25b38c66c4d26c71b82c65a558316eeb4419231 /drivers/net/ethernet
parent37bfc7c1e83f1589bcdc5918c7216422662644ee (diff)
mlx4: MAD_IFC paravirtualization
The MAD_IFC firmware command fulfills two functions. First, it is used in the QP0/QP1 MAD-handling flow to obtain information from the FW (for answering queries), and for setting variables in the HCA (MAD SET packets). For this, MAD_IFC should provide the FW (physical) view of the data. This is the view that OpenSM needs. We call this the "network view". In the second case, MAD_IFC is used by various verbs to obtain data regarding the local HCA (e.g., ib_query_device()). We call this the "host view". This data needs to be paravirtualized. MAD_IFC therefore needs a wrapper function, and also needs another flag indicating whether it should provide the network view (when it is called by ib_process_mad in special-qp packet handling), or the host view (when it is called while implementing a verb). There are currently 2 flag parameters in mlx4_MAD_IFC already: ignore_bkey and ignore_mkey. These two parameters are replaced by a single "mad_ifc_flags" parameter, with different bits set for each flag. A third flag is added: "network-view/host-view". Signed-off-by: Jack Morgenstein <jackm@dev.mellanox.co.il> Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/cmd.c162
1 files changed, 162 insertions, 0 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index 662a3c5da73..a13d8a69b3b 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -40,6 +40,7 @@
40 40
41#include <linux/mlx4/cmd.h> 41#include <linux/mlx4/cmd.h>
42#include <linux/semaphore.h> 42#include <linux/semaphore.h>
43#include <rdma/ib_smi.h>
43 44
44#include <asm/io.h> 45#include <asm/io.h>
45 46
@@ -627,6 +628,149 @@ static int mlx4_ACCESS_MEM(struct mlx4_dev *dev, u64 master_addr,
627 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); 628 MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
628} 629}
629 630
631static int query_pkey_block(struct mlx4_dev *dev, u8 port, u16 index, u16 *pkey,
632 struct mlx4_cmd_mailbox *inbox,
633 struct mlx4_cmd_mailbox *outbox)
634{
635 struct ib_smp *in_mad = (struct ib_smp *)(inbox->buf);
636 struct ib_smp *out_mad = (struct ib_smp *)(outbox->buf);
637 int err;
638 int i;
639
640 if (index & 0x1f)
641 return -EINVAL;
642
643 in_mad->attr_mod = cpu_to_be32(index / 32);
644
645 err = mlx4_cmd_box(dev, inbox->dma, outbox->dma, port, 3,
646 MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C,
647 MLX4_CMD_NATIVE);
648 if (err)
649 return err;
650
651 for (i = 0; i < 32; ++i)
652 pkey[i] = be16_to_cpu(((__be16 *) out_mad->data)[i]);
653
654 return err;
655}
656
657static int get_full_pkey_table(struct mlx4_dev *dev, u8 port, u16 *table,
658 struct mlx4_cmd_mailbox *inbox,
659 struct mlx4_cmd_mailbox *outbox)
660{
661 int i;
662 int err;
663
664 for (i = 0; i < dev->caps.pkey_table_len[port]; i += 32) {
665 err = query_pkey_block(dev, port, i, table + i, inbox, outbox);
666 if (err)
667 return err;
668 }
669
670 return 0;
671}
672#define PORT_CAPABILITY_LOCATION_IN_SMP 20
673#define PORT_STATE_OFFSET 32
674
675static enum ib_port_state vf_port_state(struct mlx4_dev *dev, int port, int vf)
676{
677 /* will be modified when add alias_guid feature */
678 return IB_PORT_DOWN;
679}
680
681static int mlx4_MAD_IFC_wrapper(struct mlx4_dev *dev, int slave,
682 struct mlx4_vhcr *vhcr,
683 struct mlx4_cmd_mailbox *inbox,
684 struct mlx4_cmd_mailbox *outbox,
685 struct mlx4_cmd_info *cmd)
686{
687 struct ib_smp *smp = inbox->buf;
688 u32 index;
689 u8 port;
690 u16 *table;
691 int err;
692 int vidx, pidx;
693 struct mlx4_priv *priv = mlx4_priv(dev);
694 struct ib_smp *outsmp = outbox->buf;
695 __be16 *outtab = (__be16 *)(outsmp->data);
696 __be32 slave_cap_mask;
697 port = vhcr->in_modifier;
698
699 if (smp->base_version == 1 &&
700 smp->mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED &&
701 smp->class_version == 1) {
702 if (smp->method == IB_MGMT_METHOD_GET) {
703 if (smp->attr_id == IB_SMP_ATTR_PKEY_TABLE) {
704 index = be32_to_cpu(smp->attr_mod);
705 if (port < 1 || port > dev->caps.num_ports)
706 return -EINVAL;
707 table = kcalloc(dev->caps.pkey_table_len[port], sizeof *table, GFP_KERNEL);
708 if (!table)
709 return -ENOMEM;
710 /* need to get the full pkey table because the paravirtualized
711 * pkeys may be scattered among several pkey blocks.
712 */
713 err = get_full_pkey_table(dev, port, table, inbox, outbox);
714 if (!err) {
715 for (vidx = index * 32; vidx < (index + 1) * 32; ++vidx) {
716 pidx = priv->virt2phys_pkey[slave][port - 1][vidx];
717 outtab[vidx % 32] = cpu_to_be16(table[pidx]);
718 }
719 }
720 kfree(table);
721 return err;
722 }
723 if (smp->attr_id == IB_SMP_ATTR_PORT_INFO) {
724 /*get the slave specific caps:*/
725 /*do the command */
726 err = mlx4_cmd_box(dev, inbox->dma, outbox->dma,
727 vhcr->in_modifier, vhcr->op_modifier,
728 vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
729 /* modify the response for slaves */
730 if (!err && slave != mlx4_master_func_num(dev)) {
731 u8 *state = outsmp->data + PORT_STATE_OFFSET;
732
733 *state = (*state & 0xf0) | vf_port_state(dev, port, slave);
734 slave_cap_mask = priv->mfunc.master.slave_state[slave].ib_cap_mask[port];
735 memcpy(outsmp->data + PORT_CAPABILITY_LOCATION_IN_SMP, &slave_cap_mask, 4);
736 }
737 return err;
738 }
739 if (smp->attr_id == IB_SMP_ATTR_GUID_INFO) {
740 /* compute slave's gid block */
741 smp->attr_mod = cpu_to_be32(slave / 8);
742 /* execute cmd */
743 err = mlx4_cmd_box(dev, inbox->dma, outbox->dma,
744 vhcr->in_modifier, vhcr->op_modifier,
745 vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
746 if (!err) {
747 /* if needed, move slave gid to index 0 */
748 if (slave % 8)
749 memcpy(outsmp->data,
750 outsmp->data + (slave % 8) * 8, 8);
751 /* delete all other gids */
752 memset(outsmp->data + 8, 0, 56);
753 }
754 return err;
755 }
756 }
757 }
758 if (slave != mlx4_master_func_num(dev) &&
759 ((smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE) ||
760 (smp->mgmt_class == IB_MGMT_CLASS_SUBN_LID_ROUTED &&
761 smp->method == IB_MGMT_METHOD_SET))) {
762 mlx4_err(dev, "slave %d is trying to execute a Subnet MGMT MAD, "
763 "class 0x%x, method 0x%x for attr 0x%x. Rejecting\n",
764 slave, smp->method, smp->mgmt_class,
765 be16_to_cpu(smp->attr_id));
766 return -EPERM;
767 }
768 /*default:*/
769 return mlx4_cmd_box(dev, inbox->dma, outbox->dma,
770 vhcr->in_modifier, vhcr->op_modifier,
771 vhcr->op, MLX4_CMD_TIME_CLASS_C, MLX4_CMD_NATIVE);
772}
773
630int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave, 774int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave,
631 struct mlx4_vhcr *vhcr, 775 struct mlx4_vhcr *vhcr,
632 struct mlx4_cmd_mailbox *inbox, 776 struct mlx4_cmd_mailbox *inbox,
@@ -1061,6 +1205,24 @@ static struct mlx4_cmd_info cmd_info[] = {
1061 .wrapper = mlx4_GEN_QP_wrapper 1205 .wrapper = mlx4_GEN_QP_wrapper
1062 }, 1206 },
1063 { 1207 {
1208 .opcode = MLX4_CMD_CONF_SPECIAL_QP,
1209 .has_inbox = false,
1210 .has_outbox = false,
1211 .out_is_imm = false,
1212 .encode_slave_id = false,
1213 .verify = NULL, /* XXX verify: only demux can do this */
1214 .wrapper = NULL
1215 },
1216 {
1217 .opcode = MLX4_CMD_MAD_IFC,
1218 .has_inbox = true,
1219 .has_outbox = true,
1220 .out_is_imm = false,
1221 .encode_slave_id = false,
1222 .verify = NULL,
1223 .wrapper = mlx4_MAD_IFC_wrapper
1224 },
1225 {
1064 .opcode = MLX4_CMD_QUERY_IF_STAT, 1226 .opcode = MLX4_CMD_QUERY_IF_STAT,
1065 .has_inbox = false, 1227 .has_inbox = false,
1066 .has_outbox = true, 1228 .has_outbox = true,