15a2cc190SJeff Kirsher /* 25a2cc190SJeff Kirsher * Copyright (c) 2007 Mellanox Technologies. All rights reserved. 35a2cc190SJeff Kirsher * 45a2cc190SJeff Kirsher * This software is available to you under a choice of one of two 55a2cc190SJeff Kirsher * licenses. You may choose to be licensed under the terms of the GNU 65a2cc190SJeff Kirsher * General Public License (GPL) Version 2, available from the file 75a2cc190SJeff Kirsher * COPYING in the main directory of this source tree, or the 85a2cc190SJeff Kirsher * OpenIB.org BSD license below: 95a2cc190SJeff Kirsher * 105a2cc190SJeff Kirsher * Redistribution and use in source and binary forms, with or 115a2cc190SJeff Kirsher * without modification, are permitted provided that the following 125a2cc190SJeff Kirsher * conditions are met: 135a2cc190SJeff Kirsher * 145a2cc190SJeff Kirsher * - Redistributions of source code must retain the above 155a2cc190SJeff Kirsher * copyright notice, this list of conditions and the following 165a2cc190SJeff Kirsher * disclaimer. 175a2cc190SJeff Kirsher * 185a2cc190SJeff Kirsher * - Redistributions in binary form must reproduce the above 195a2cc190SJeff Kirsher * copyright notice, this list of conditions and the following 205a2cc190SJeff Kirsher * disclaimer in the documentation and/or other materials 215a2cc190SJeff Kirsher * provided with the distribution. 225a2cc190SJeff Kirsher * 235a2cc190SJeff Kirsher * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 245a2cc190SJeff Kirsher * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 255a2cc190SJeff Kirsher * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 265a2cc190SJeff Kirsher * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 275a2cc190SJeff Kirsher * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 285a2cc190SJeff Kirsher * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 295a2cc190SJeff Kirsher * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 305a2cc190SJeff Kirsher * SOFTWARE. 315a2cc190SJeff Kirsher * 325a2cc190SJeff Kirsher */ 335a2cc190SJeff Kirsher 345a2cc190SJeff Kirsher #include <linux/errno.h> 355a2cc190SJeff Kirsher #include <linux/if_ether.h> 365a2cc190SJeff Kirsher 375a2cc190SJeff Kirsher #include <linux/mlx4/cmd.h> 385a2cc190SJeff Kirsher 395a2cc190SJeff Kirsher #include "mlx4.h" 405a2cc190SJeff Kirsher 415a2cc190SJeff Kirsher int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port, 425a2cc190SJeff Kirsher enum mlx4_port_type *type) 435a2cc190SJeff Kirsher { 445a2cc190SJeff Kirsher u64 out_param; 455a2cc190SJeff Kirsher int err = 0; 465a2cc190SJeff Kirsher 475a2cc190SJeff Kirsher err = mlx4_cmd_imm(dev, 0, &out_param, port, 0, 48*f9baff50SJack Morgenstein MLX4_CMD_SENSE_PORT, MLX4_CMD_TIME_CLASS_B, 49*f9baff50SJack Morgenstein MLX4_CMD_WRAPPED); 505a2cc190SJeff Kirsher if (err) { 515a2cc190SJeff Kirsher mlx4_err(dev, "Sense command failed for port: %d\n", port); 525a2cc190SJeff Kirsher return err; 535a2cc190SJeff Kirsher } 545a2cc190SJeff Kirsher 555a2cc190SJeff Kirsher if (out_param > 2) { 565a2cc190SJeff Kirsher mlx4_err(dev, "Sense returned illegal value: 0x%llx\n", out_param); 575a2cc190SJeff Kirsher return -EINVAL; 585a2cc190SJeff Kirsher } 595a2cc190SJeff Kirsher 605a2cc190SJeff Kirsher *type = out_param; 615a2cc190SJeff Kirsher return 0; 625a2cc190SJeff Kirsher } 635a2cc190SJeff Kirsher 645a2cc190SJeff Kirsher void mlx4_do_sense_ports(struct mlx4_dev *dev, 655a2cc190SJeff Kirsher enum mlx4_port_type *stype, 665a2cc190SJeff Kirsher enum mlx4_port_type *defaults) 675a2cc190SJeff Kirsher { 685a2cc190SJeff Kirsher struct mlx4_sense *sense = &mlx4_priv(dev)->sense; 695a2cc190SJeff Kirsher int err; 705a2cc190SJeff Kirsher int i; 715a2cc190SJeff Kirsher 725a2cc190SJeff Kirsher for (i = 1; i <= dev->caps.num_ports; i++) { 735a2cc190SJeff Kirsher stype[i - 1] = 0; 745a2cc190SJeff Kirsher if (sense->do_sense_port[i] && sense->sense_allowed[i] && 755a2cc190SJeff Kirsher dev->caps.possible_type[i] == MLX4_PORT_TYPE_AUTO) { 765a2cc190SJeff Kirsher err = mlx4_SENSE_PORT(dev, i, &stype[i - 1]); 775a2cc190SJeff Kirsher if (err) 785a2cc190SJeff Kirsher stype[i - 1] = defaults[i - 1]; 795a2cc190SJeff Kirsher } else 805a2cc190SJeff Kirsher stype[i - 1] = defaults[i - 1]; 815a2cc190SJeff Kirsher } 825a2cc190SJeff Kirsher 835a2cc190SJeff Kirsher /* 845a2cc190SJeff Kirsher * Adjust port configuration: 855a2cc190SJeff Kirsher * If port 1 sensed nothing and port 2 is IB, set both as IB 865a2cc190SJeff Kirsher * If port 2 sensed nothing and port 1 is Eth, set both as Eth 875a2cc190SJeff Kirsher */ 885a2cc190SJeff Kirsher if (stype[0] == MLX4_PORT_TYPE_ETH) { 895a2cc190SJeff Kirsher for (i = 1; i < dev->caps.num_ports; i++) 905a2cc190SJeff Kirsher stype[i] = stype[i] ? stype[i] : MLX4_PORT_TYPE_ETH; 915a2cc190SJeff Kirsher } 925a2cc190SJeff Kirsher if (stype[dev->caps.num_ports - 1] == MLX4_PORT_TYPE_IB) { 935a2cc190SJeff Kirsher for (i = 0; i < dev->caps.num_ports - 1; i++) 945a2cc190SJeff Kirsher stype[i] = stype[i] ? stype[i] : MLX4_PORT_TYPE_IB; 955a2cc190SJeff Kirsher } 965a2cc190SJeff Kirsher 975a2cc190SJeff Kirsher /* 985a2cc190SJeff Kirsher * If sensed nothing, remain in current configuration. 995a2cc190SJeff Kirsher */ 1005a2cc190SJeff Kirsher for (i = 0; i < dev->caps.num_ports; i++) 1015a2cc190SJeff Kirsher stype[i] = stype[i] ? stype[i] : defaults[i]; 1025a2cc190SJeff Kirsher 1035a2cc190SJeff Kirsher } 1045a2cc190SJeff Kirsher 1055a2cc190SJeff Kirsher static void mlx4_sense_port(struct work_struct *work) 1065a2cc190SJeff Kirsher { 1075a2cc190SJeff Kirsher struct delayed_work *delay = to_delayed_work(work); 1085a2cc190SJeff Kirsher struct mlx4_sense *sense = container_of(delay, struct mlx4_sense, 1095a2cc190SJeff Kirsher sense_poll); 1105a2cc190SJeff Kirsher struct mlx4_dev *dev = sense->dev; 1115a2cc190SJeff Kirsher struct mlx4_priv *priv = mlx4_priv(dev); 1125a2cc190SJeff Kirsher enum mlx4_port_type stype[MLX4_MAX_PORTS]; 1135a2cc190SJeff Kirsher 1145a2cc190SJeff Kirsher mutex_lock(&priv->port_mutex); 1155a2cc190SJeff Kirsher mlx4_do_sense_ports(dev, stype, &dev->caps.port_type[1]); 1165a2cc190SJeff Kirsher 1175a2cc190SJeff Kirsher if (mlx4_check_port_params(dev, stype)) 1185a2cc190SJeff Kirsher goto sense_again; 1195a2cc190SJeff Kirsher 1205a2cc190SJeff Kirsher if (mlx4_change_port_types(dev, stype)) 1215a2cc190SJeff Kirsher mlx4_err(dev, "Failed to change port_types\n"); 1225a2cc190SJeff Kirsher 1235a2cc190SJeff Kirsher sense_again: 1245a2cc190SJeff Kirsher mutex_unlock(&priv->port_mutex); 1255a2cc190SJeff Kirsher queue_delayed_work(mlx4_wq , &sense->sense_poll, 1265a2cc190SJeff Kirsher round_jiffies_relative(MLX4_SENSE_RANGE)); 1275a2cc190SJeff Kirsher } 1285a2cc190SJeff Kirsher 1295a2cc190SJeff Kirsher void mlx4_start_sense(struct mlx4_dev *dev) 1305a2cc190SJeff Kirsher { 1315a2cc190SJeff Kirsher struct mlx4_priv *priv = mlx4_priv(dev); 1325a2cc190SJeff Kirsher struct mlx4_sense *sense = &priv->sense; 1335a2cc190SJeff Kirsher 1345a2cc190SJeff Kirsher if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP)) 1355a2cc190SJeff Kirsher return; 1365a2cc190SJeff Kirsher 1375a2cc190SJeff Kirsher queue_delayed_work(mlx4_wq , &sense->sense_poll, 1385a2cc190SJeff Kirsher round_jiffies_relative(MLX4_SENSE_RANGE)); 1395a2cc190SJeff Kirsher } 1405a2cc190SJeff Kirsher 1415a2cc190SJeff Kirsher void mlx4_stop_sense(struct mlx4_dev *dev) 1425a2cc190SJeff Kirsher { 1435a2cc190SJeff Kirsher cancel_delayed_work_sync(&mlx4_priv(dev)->sense.sense_poll); 1445a2cc190SJeff Kirsher } 1455a2cc190SJeff Kirsher 1465a2cc190SJeff Kirsher void mlx4_sense_init(struct mlx4_dev *dev) 1475a2cc190SJeff Kirsher { 1485a2cc190SJeff Kirsher struct mlx4_priv *priv = mlx4_priv(dev); 1495a2cc190SJeff Kirsher struct mlx4_sense *sense = &priv->sense; 1505a2cc190SJeff Kirsher int port; 1515a2cc190SJeff Kirsher 1525a2cc190SJeff Kirsher sense->dev = dev; 1535a2cc190SJeff Kirsher for (port = 1; port <= dev->caps.num_ports; port++) 1545a2cc190SJeff Kirsher sense->do_sense_port[port] = 1; 1555a2cc190SJeff Kirsher 1565a2cc190SJeff Kirsher INIT_DELAYED_WORK_DEFERRABLE(&sense->sense_poll, mlx4_sense_port); 1575a2cc190SJeff Kirsher } 158