diff options
author | Jack Morgenstein <jackm@dev.mellanox.co.il> | 2012-08-03 04:40:45 -0400 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2012-09-30 23:33:34 -0400 |
commit | 0a9a01884d447c216eff75f8f274a0a3e82c7cee (patch) | |
tree | c25b38c66c4d26c71b82c65a558316eeb4419231 /drivers/net/ethernet | |
parent | 37bfc7c1e83f1589bcdc5918c7216422662644ee (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.c | 162 |
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 | ||
631 | static 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 | |||
657 | static 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 | |||
675 | static 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 | |||
681 | static 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 | |||
630 | int mlx4_DMA_wrapper(struct mlx4_dev *dev, int slave, | 774 | int 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, |