sense.c revision 272407
1219820Sjeff/* 2272407Shselasky * Copyright (c) 2007, 2014 Mellanox Technologies. All rights reserved. 3219820Sjeff * 4219820Sjeff * This software is available to you under a choice of one of two 5219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 6219820Sjeff * General Public License (GPL) Version 2, available from the file 7219820Sjeff * COPYING in the main directory of this source tree, or the 8219820Sjeff * OpenIB.org BSD license below: 9219820Sjeff * 10219820Sjeff * Redistribution and use in source and binary forms, with or 11219820Sjeff * without modification, are permitted provided that the following 12219820Sjeff * conditions are met: 13219820Sjeff * 14219820Sjeff * - Redistributions of source code must retain the above 15219820Sjeff * copyright notice, this list of conditions and the following 16219820Sjeff * disclaimer. 17219820Sjeff * 18219820Sjeff * - Redistributions in binary form must reproduce the above 19219820Sjeff * copyright notice, this list of conditions and the following 20219820Sjeff * disclaimer in the documentation and/or other materials 21219820Sjeff * provided with the distribution. 22219820Sjeff * 23219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30219820Sjeff * SOFTWARE. 31219820Sjeff * 32219820Sjeff */ 33219820Sjeff 34219820Sjeff#include <linux/errno.h> 35219820Sjeff#include <linux/if_ether.h> 36219820Sjeff 37219820Sjeff#include <linux/mlx4/cmd.h> 38219820Sjeff 39219820Sjeff#include "mlx4.h" 40219820Sjeff 41255932Salfredint mlx4_SENSE_PORT(struct mlx4_dev *dev, int port, 42255932Salfred enum mlx4_port_type *type) 43219820Sjeff{ 44219820Sjeff u64 out_param; 45219820Sjeff int err = 0; 46219820Sjeff 47219820Sjeff err = mlx4_cmd_imm(dev, 0, &out_param, port, 0, 48255932Salfred MLX4_CMD_SENSE_PORT, MLX4_CMD_TIME_CLASS_B, 49255932Salfred MLX4_CMD_WRAPPED); 50219820Sjeff if (err) { 51219820Sjeff mlx4_err(dev, "Sense command failed for port: %d\n", port); 52219820Sjeff return err; 53219820Sjeff } 54219820Sjeff 55219820Sjeff if (out_param > 2) { 56272407Shselasky mlx4_err(dev, "Sense returned illegal value: 0x%llx\n", (unsigned long long)out_param); 57255932Salfred return -EINVAL; 58219820Sjeff } 59219820Sjeff 60219820Sjeff *type = out_param; 61219820Sjeff return 0; 62219820Sjeff} 63219820Sjeff 64219820Sjeffvoid mlx4_do_sense_ports(struct mlx4_dev *dev, 65219820Sjeff enum mlx4_port_type *stype, 66219820Sjeff enum mlx4_port_type *defaults) 67219820Sjeff{ 68219820Sjeff struct mlx4_sense *sense = &mlx4_priv(dev)->sense; 69219820Sjeff int err; 70219820Sjeff int i; 71219820Sjeff 72219820Sjeff for (i = 1; i <= dev->caps.num_ports; i++) { 73219820Sjeff stype[i - 1] = 0; 74219820Sjeff if (sense->do_sense_port[i] && sense->sense_allowed[i] && 75219820Sjeff dev->caps.possible_type[i] == MLX4_PORT_TYPE_AUTO) { 76219820Sjeff err = mlx4_SENSE_PORT(dev, i, &stype[i - 1]); 77219820Sjeff if (err) 78219820Sjeff stype[i - 1] = defaults[i - 1]; 79219820Sjeff } else 80219820Sjeff stype[i - 1] = defaults[i - 1]; 81219820Sjeff } 82219820Sjeff 83219820Sjeff /* 84219820Sjeff * If sensed nothing, remain in current configuration. 85219820Sjeff */ 86219820Sjeff for (i = 0; i < dev->caps.num_ports; i++) 87219820Sjeff stype[i] = stype[i] ? stype[i] : defaults[i]; 88219820Sjeff 89219820Sjeff} 90219820Sjeff 91219820Sjeffstatic void mlx4_sense_port(struct work_struct *work) 92219820Sjeff{ 93219820Sjeff struct delayed_work *delay = to_delayed_work(work); 94219820Sjeff struct mlx4_sense *sense = container_of(delay, struct mlx4_sense, 95219820Sjeff sense_poll); 96219820Sjeff struct mlx4_dev *dev = sense->dev; 97219820Sjeff struct mlx4_priv *priv = mlx4_priv(dev); 98219820Sjeff enum mlx4_port_type stype[MLX4_MAX_PORTS]; 99219820Sjeff 100219820Sjeff mutex_lock(&priv->port_mutex); 101219820Sjeff mlx4_do_sense_ports(dev, stype, &dev->caps.port_type[1]); 102219820Sjeff 103219820Sjeff if (mlx4_check_port_params(dev, stype)) 104219820Sjeff goto sense_again; 105219820Sjeff 106219820Sjeff if (mlx4_change_port_types(dev, stype)) 107219820Sjeff mlx4_err(dev, "Failed to change port_types\n"); 108219820Sjeff 109219820Sjeffsense_again: 110219820Sjeff mutex_unlock(&priv->port_mutex); 111272407Shselasky queue_delayed_work(mlx4_wq , &sense->sense_poll, 112272407Shselasky round_jiffies_relative(MLX4_SENSE_RANGE)); 113219820Sjeff} 114219820Sjeff 115219820Sjeffvoid mlx4_start_sense(struct mlx4_dev *dev) 116219820Sjeff{ 117219820Sjeff struct mlx4_priv *priv = mlx4_priv(dev); 118219820Sjeff struct mlx4_sense *sense = &priv->sense; 119219820Sjeff 120219820Sjeff if (!(dev->caps.flags & MLX4_DEV_CAP_FLAG_DPDP)) 121219820Sjeff return; 122219820Sjeff 123272407Shselasky queue_delayed_work(mlx4_wq , &sense->sense_poll, 124272407Shselasky round_jiffies_relative(MLX4_SENSE_RANGE)); 125219820Sjeff} 126219820Sjeff 127219820Sjeffvoid mlx4_stop_sense(struct mlx4_dev *dev) 128219820Sjeff{ 129272407Shselasky cancel_delayed_work_sync(&mlx4_priv(dev)->sense.sense_poll); 130219820Sjeff} 131219820Sjeff 132272407Shselaskyvoid mlx4_sense_init(struct mlx4_dev *dev) 133219820Sjeff{ 134219820Sjeff struct mlx4_priv *priv = mlx4_priv(dev); 135219820Sjeff struct mlx4_sense *sense = &priv->sense; 136219820Sjeff int port; 137219820Sjeff 138219820Sjeff sense->dev = dev; 139219820Sjeff for (port = 1; port <= dev->caps.num_ports; port++) 140219820Sjeff sense->do_sense_port[port] = 1; 141219820Sjeff 142255932Salfred INIT_DEFERRABLE_WORK(&sense->sense_poll, mlx4_sense_port); 143219820Sjeff} 144