diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx4/cmd.c | 88 |
1 files changed, 56 insertions, 32 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index c4fef839168c..978f593094c0 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c | |||
@@ -152,6 +152,26 @@ static int mlx4_status_to_errno(u8 status) | |||
152 | return trans_table[status]; | 152 | return trans_table[status]; |
153 | } | 153 | } |
154 | 154 | ||
155 | static u8 mlx4_errno_to_status(int errno) | ||
156 | { | ||
157 | switch (errno) { | ||
158 | case -EPERM: | ||
159 | return CMD_STAT_BAD_OP; | ||
160 | case -EINVAL: | ||
161 | return CMD_STAT_BAD_PARAM; | ||
162 | case -ENXIO: | ||
163 | return CMD_STAT_BAD_SYS_STATE; | ||
164 | case -EBUSY: | ||
165 | return CMD_STAT_RESOURCE_BUSY; | ||
166 | case -ENOMEM: | ||
167 | return CMD_STAT_EXCEED_LIM; | ||
168 | case -ENFILE: | ||
169 | return CMD_STAT_ICM_ERROR; | ||
170 | default: | ||
171 | return CMD_STAT_INTERNAL_ERR; | ||
172 | } | ||
173 | } | ||
174 | |||
155 | static int comm_pending(struct mlx4_dev *dev) | 175 | static int comm_pending(struct mlx4_dev *dev) |
156 | { | 176 | { |
157 | struct mlx4_priv *priv = mlx4_priv(dev); | 177 | struct mlx4_priv *priv = mlx4_priv(dev); |
@@ -361,10 +381,10 @@ static int mlx4_slave_cmd(struct mlx4_dev *dev, u64 in_param, u64 *out_param, | |||
361 | mlx4_err(dev, "response expected while" | 381 | mlx4_err(dev, "response expected while" |
362 | "output mailbox is NULL for " | 382 | "output mailbox is NULL for " |
363 | "command 0x%x\n", op); | 383 | "command 0x%x\n", op); |
364 | vhcr->status = -EINVAL; | 384 | vhcr->status = CMD_STAT_BAD_PARAM; |
365 | } | 385 | } |
366 | } | 386 | } |
367 | ret = vhcr->status; | 387 | ret = mlx4_status_to_errno(vhcr->status); |
368 | } | 388 | } |
369 | } else { | 389 | } else { |
370 | ret = mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR_POST, 0, | 390 | ret = mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR_POST, 0, |
@@ -378,10 +398,10 @@ static int mlx4_slave_cmd(struct mlx4_dev *dev, u64 in_param, u64 *out_param, | |||
378 | mlx4_err(dev, "response expected while" | 398 | mlx4_err(dev, "response expected while" |
379 | "output mailbox is NULL for " | 399 | "output mailbox is NULL for " |
380 | "command 0x%x\n", op); | 400 | "command 0x%x\n", op); |
381 | vhcr->status = -EINVAL; | 401 | vhcr->status = CMD_STAT_BAD_PARAM; |
382 | } | 402 | } |
383 | } | 403 | } |
384 | ret = vhcr->status; | 404 | ret = mlx4_status_to_errno(vhcr->status); |
385 | } else | 405 | } else |
386 | mlx4_err(dev, "failed execution of VHCR_POST command" | 406 | mlx4_err(dev, "failed execution of VHCR_POST command" |
387 | "opcode 0x%x\n", op); | 407 | "opcode 0x%x\n", op); |
@@ -1066,6 +1086,7 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave, | |||
1066 | u64 out_param; | 1086 | u64 out_param; |
1067 | int ret = 0; | 1087 | int ret = 0; |
1068 | int i; | 1088 | int i; |
1089 | int err = 0; | ||
1069 | 1090 | ||
1070 | /* Create sw representation of Virtual HCR */ | 1091 | /* Create sw representation of Virtual HCR */ |
1071 | vhcr = kzalloc(sizeof(struct mlx4_vhcr), GFP_KERNEL); | 1092 | vhcr = kzalloc(sizeof(struct mlx4_vhcr), GFP_KERNEL); |
@@ -1105,7 +1126,7 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave, | |||
1105 | if (!cmd) { | 1126 | if (!cmd) { |
1106 | mlx4_err(dev, "Unknown command:0x%x accepted from slave:%d\n", | 1127 | mlx4_err(dev, "Unknown command:0x%x accepted from slave:%d\n", |
1107 | vhcr->op, slave); | 1128 | vhcr->op, slave); |
1108 | vhcr_cmd->status = -EINVAL; | 1129 | vhcr_cmd->status = CMD_STAT_BAD_PARAM; |
1109 | goto out_status; | 1130 | goto out_status; |
1110 | } | 1131 | } |
1111 | 1132 | ||
@@ -1114,18 +1135,18 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave, | |||
1114 | vhcr->in_param &= INBOX_MASK; | 1135 | vhcr->in_param &= INBOX_MASK; |
1115 | inbox = mlx4_alloc_cmd_mailbox(dev); | 1136 | inbox = mlx4_alloc_cmd_mailbox(dev); |
1116 | if (IS_ERR(inbox)) { | 1137 | if (IS_ERR(inbox)) { |
1117 | ret = PTR_ERR(inbox); | 1138 | vhcr_cmd->status = CMD_STAT_BAD_SIZE; |
1118 | inbox = NULL; | 1139 | inbox = NULL; |
1119 | goto out; | 1140 | goto out_status; |
1120 | } | 1141 | } |
1121 | 1142 | ||
1122 | ret = mlx4_ACCESS_MEM(dev, inbox->dma, slave, | 1143 | if (mlx4_ACCESS_MEM(dev, inbox->dma, slave, |
1123 | vhcr->in_param, | 1144 | vhcr->in_param, |
1124 | MLX4_MAILBOX_SIZE, 1); | 1145 | MLX4_MAILBOX_SIZE, 1)) { |
1125 | if (ret) { | ||
1126 | mlx4_err(dev, "%s: Failed reading inbox (cmd:0x%x)\n", | 1146 | mlx4_err(dev, "%s: Failed reading inbox (cmd:0x%x)\n", |
1127 | __func__, cmd->opcode); | 1147 | __func__, cmd->opcode); |
1128 | goto out; | 1148 | vhcr_cmd->status = CMD_STAT_INTERNAL_ERR; |
1149 | goto out_status; | ||
1129 | } | 1150 | } |
1130 | } | 1151 | } |
1131 | 1152 | ||
@@ -1134,7 +1155,7 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave, | |||
1134 | mlx4_warn(dev, "Command:0x%x from slave: %d failed protection " | 1155 | mlx4_warn(dev, "Command:0x%x from slave: %d failed protection " |
1135 | "checks for resource_id:%d\n", vhcr->op, slave, | 1156 | "checks for resource_id:%d\n", vhcr->op, slave, |
1136 | vhcr->in_modifier); | 1157 | vhcr->in_modifier); |
1137 | vhcr_cmd->status = -EPERM; | 1158 | vhcr_cmd->status = CMD_STAT_BAD_OP; |
1138 | goto out_status; | 1159 | goto out_status; |
1139 | } | 1160 | } |
1140 | 1161 | ||
@@ -1142,16 +1163,16 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave, | |||
1142 | if (cmd->has_outbox) { | 1163 | if (cmd->has_outbox) { |
1143 | outbox = mlx4_alloc_cmd_mailbox(dev); | 1164 | outbox = mlx4_alloc_cmd_mailbox(dev); |
1144 | if (IS_ERR(outbox)) { | 1165 | if (IS_ERR(outbox)) { |
1145 | ret = PTR_ERR(outbox); | 1166 | vhcr_cmd->status = CMD_STAT_BAD_SIZE; |
1146 | outbox = NULL; | 1167 | outbox = NULL; |
1147 | goto out; | 1168 | goto out_status; |
1148 | } | 1169 | } |
1149 | } | 1170 | } |
1150 | 1171 | ||
1151 | /* Execute the command! */ | 1172 | /* Execute the command! */ |
1152 | if (cmd->wrapper) { | 1173 | if (cmd->wrapper) { |
1153 | vhcr_cmd->status = cmd->wrapper(dev, slave, vhcr, inbox, outbox, | 1174 | err = cmd->wrapper(dev, slave, vhcr, inbox, outbox, |
1154 | cmd); | 1175 | cmd); |
1155 | if (cmd->out_is_imm) | 1176 | if (cmd->out_is_imm) |
1156 | vhcr_cmd->out_param = cpu_to_be64(vhcr->out_param); | 1177 | vhcr_cmd->out_param = cpu_to_be64(vhcr->out_param); |
1157 | } else { | 1178 | } else { |
@@ -1159,20 +1180,11 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave, | |||
1159 | vhcr->in_param; | 1180 | vhcr->in_param; |
1160 | out_param = cmd->has_outbox ? (u64) outbox->dma : | 1181 | out_param = cmd->has_outbox ? (u64) outbox->dma : |
1161 | vhcr->out_param; | 1182 | vhcr->out_param; |
1162 | vhcr_cmd->status = __mlx4_cmd(dev, in_param, &out_param, | 1183 | err = __mlx4_cmd(dev, in_param, &out_param, |
1163 | cmd->out_is_imm, vhcr->in_modifier, | 1184 | cmd->out_is_imm, vhcr->in_modifier, |
1164 | vhcr->op_modifier, vhcr->op, | 1185 | vhcr->op_modifier, vhcr->op, |
1165 | MLX4_CMD_TIME_CLASS_A, | 1186 | MLX4_CMD_TIME_CLASS_A, |
1166 | MLX4_CMD_NATIVE); | 1187 | MLX4_CMD_NATIVE); |
1167 | |||
1168 | if (vhcr_cmd->status) { | ||
1169 | mlx4_warn(dev, "vhcr command:0x%x slave:%d failed with" | ||
1170 | " error:%d, status %d\n", | ||
1171 | vhcr->op, slave, vhcr->errno, | ||
1172 | vhcr_cmd->status); | ||
1173 | ret = vhcr_cmd->status; | ||
1174 | goto out; | ||
1175 | } | ||
1176 | 1188 | ||
1177 | if (cmd->out_is_imm) { | 1189 | if (cmd->out_is_imm) { |
1178 | vhcr->out_param = out_param; | 1190 | vhcr->out_param = out_param; |
@@ -1180,12 +1192,24 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave, | |||
1180 | } | 1192 | } |
1181 | } | 1193 | } |
1182 | 1194 | ||
1195 | if (err) { | ||
1196 | mlx4_warn(dev, "vhcr command:0x%x slave:%d failed with" | ||
1197 | " error:%d, status %d\n", | ||
1198 | vhcr->op, slave, vhcr->errno, err); | ||
1199 | vhcr_cmd->status = mlx4_errno_to_status(err); | ||
1200 | goto out_status; | ||
1201 | } | ||
1202 | |||
1203 | |||
1183 | /* Write outbox if command completed successfully */ | 1204 | /* Write outbox if command completed successfully */ |
1184 | if (cmd->has_outbox && !vhcr->errno) { | 1205 | if (cmd->has_outbox && !vhcr_cmd->status) { |
1185 | ret = mlx4_ACCESS_MEM(dev, outbox->dma, slave, | 1206 | ret = mlx4_ACCESS_MEM(dev, outbox->dma, slave, |
1186 | vhcr->out_param, | 1207 | vhcr->out_param, |
1187 | MLX4_MAILBOX_SIZE, MLX4_CMD_WRAPPED); | 1208 | MLX4_MAILBOX_SIZE, MLX4_CMD_WRAPPED); |
1188 | if (ret) { | 1209 | if (ret) { |
1210 | /* If we failed to write back the outbox after the | ||
1211 | *command was successfully executed, we must fail this | ||
1212 | * slave, as it is now in undefined state */ | ||
1189 | mlx4_err(dev, "%s:Failed writing outbox\n", __func__); | 1213 | mlx4_err(dev, "%s:Failed writing outbox\n", __func__); |
1190 | goto out; | 1214 | goto out; |
1191 | } | 1215 | } |