Signed-off-by: Luben Tuikov <luben_tuikov@xxxxxxxxxxx> diff -X linux-2.6.13/Documentation/dontdiff -Naur linux-2.6.13-orig/drivers/scsi/sas-class/sas_phy.c linux-2.6.13/drivers/scsi/sas-class/sas_phy.c --- linux-2.6.13-orig/drivers/scsi/sas-class/sas_phy.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.6.13/drivers/scsi/sas-class/sas_phy.c 2005-09-09 11:14:29.000000000 -0400 @@ -0,0 +1,307 @@ +/* + * Serial Attached SCSI (SAS) Phy class + * + * Copyright (C) 2005 Adaptec, Inc. All rights reserved. + * Copyright (C) 2005 Luben Tuikov <luben_tuikov@xxxxxxxxxxx> + * + * This file is licensed under GPLv2. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * $Id: //depot/sas-class/sas_phy.c#37 $ + */ + +#include "sas_internal.h" + +/* ---------- Phy events ---------- */ + +void sas_phye_loss_of_signal(struct sas_phy *phy) +{ + phy->error = 0; + sas_deform_port(phy); +} + +void sas_phye_oob_done(struct sas_phy *phy) +{ + phy->error = 0; +} + +void sas_phye_oob_error(struct sas_phy *phy) +{ + struct sas_ha_struct *sas_ha = phy->ha; + struct sas_port *port = phy->port; + + sas_deform_port(phy); + + if (!port && phy->enabled && sas_ha->lldd_control_phy) { + phy->error++; + switch (phy->error) { + case 1: + case 2: + sas_ha->lldd_control_phy(phy, PHY_FUNC_HARD_RESET); + break; + case 3: + default: + phy->error = 0; + phy->enabled = 0; + sas_ha->lldd_control_phy(phy, PHY_FUNC_DISABLE); + break; + } + } +} + +void sas_phye_spinup_hold(struct sas_phy *phy) +{ + struct sas_ha_struct *sas_ha = phy->ha; + + phy->error = 0; + sas_ha->lldd_control_phy(phy, PHY_FUNC_RELEASE_SPINUP_HOLD); +} + +/* ---------- Phy attributes ---------- */ + +static ssize_t sas_phy_id_show(struct sas_phy *phy, char *buf) +{ + return sprintf(buf, "%d\n", phy->id); +} + +static ssize_t sas_phy_enabled_show(struct sas_phy *phy, char *buf) +{ + return sprintf(buf, "%d\n", phy->enabled); +} + +static ssize_t sas_phy_enabled_store(struct sas_phy *phy, const char *buf, + size_t size) +{ + if (size > 0) { + if (buf[0] == '1') + phy->ha->lldd_control_phy(phy, PHY_FUNC_LINK_RESET); + } + return size; +} + +static ssize_t sas_phy_class_show(struct sas_phy *phy, char *buf) +{ + if (!phy->enabled) + return 0; + return sas_show_class(phy->class, buf); +} + +static ssize_t sas_phy_iproto_show(struct sas_phy *phy, char *page) +{ + if (!phy->enabled) + return 0; + return sas_show_proto(phy->iproto, page); +} + +static ssize_t sas_phy_tproto_show(struct sas_phy *phy, char *page) +{ + if (!phy->enabled) + return 0; + return sas_show_proto(phy->tproto, page); +} + +static ssize_t sas_phy_type_show(struct sas_phy *phy, char *buf) +{ + static const char *phy_type_str[] = { + [PHY_TYPE_PHYSICAL] = "physical", + [PHY_TYPE_VIRTUAL] = "virtual", + }; + if (!phy->enabled) + return 0; + return sprintf(buf, "%s\n", phy_type_str[phy->type]); +} + +static ssize_t sas_phy_role_show(struct sas_phy *phy, char *page) +{ + static const char *phy_role_str[] = { + [PHY_ROLE_NONE] = "none", + [PHY_ROLE_TARGET] = "target", + [PHY_ROLE_INITIATOR] = "initiator", + }; + int v; + char *buf = page; + + if (!phy->enabled) + return 0; + + if (phy->role == PHY_ROLE_NONE) + return sprintf(buf, "%s\n", phy_role_str[PHY_ROLE_NONE]); + + for (v = 1; v <= PHY_ROLE_INITIATOR; v <<= 1) { + if (v & phy->role) { + buf += sprintf(buf, "%s", phy_role_str[v]); + if (phy->role & ~((v<<1)-1)) + buf += sprintf(buf, "|"); + else + buf += sprintf(buf, "\n"); + } + } + return buf-page; +} + +static ssize_t sas_phy_linkrate_show(struct sas_phy *phy, char *buf) +{ + if (!phy->enabled) + return 0; + return sas_show_linkrate(phy->linkrate, buf); +} + +static ssize_t sas_phy_addr_show(struct sas_phy *phy, char *buf) +{ + if (!phy->enabled) + return 0; + return sprintf(buf, "%llx\n", SAS_ADDR(phy->sas_addr)); +} + +static ssize_t sas_phy_oob_mode_show(struct sas_phy *phy, char *buf) +{ + if (!phy->enabled) + return 0; + return sas_show_oob_mode(phy->oob_mode, buf); +} + +struct phy_attribute { + struct attribute attr; + ssize_t (*show)(struct sas_phy *phy, char *); + ssize_t (*store)(struct sas_phy *phy, const char *, size_t); +}; + +static struct phy_attribute phy_attrs[] = { + /* port is a symlink */ + __ATTR(id, 0444, sas_phy_id_show, NULL), + __ATTR(enabled, 0644, sas_phy_enabled_show, sas_phy_enabled_store), + __ATTR(class, 0444, sas_phy_class_show, NULL), + __ATTR(iproto, 0444, sas_phy_iproto_show, NULL), + __ATTR(tproto, 0444, sas_phy_tproto_show, NULL), + __ATTR(type, 0444, sas_phy_type_show, NULL), + __ATTR(role, 0444, sas_phy_role_show, NULL), + __ATTR(linkrate, 0444, sas_phy_linkrate_show, NULL), + __ATTR(sas_addr, 0444, sas_phy_addr_show, NULL), + __ATTR(oob_mode, 0444, sas_phy_oob_mode_show, NULL), + __ATTR_NULL, +}; + +static struct attribute *def_attrs[ARRAY_SIZE(phy_attrs)]; + +#define to_sas_phy(_obj) container_of(_obj, struct sas_phy, phy_kobj) +#define to_phy_attr(_attr) container_of(_attr, struct phy_attribute, attr) + +static ssize_t phy_show_attr(struct kobject *kobj, + struct attribute *attr, + char *page) +{ + ssize_t ret = 0; + struct sas_phy *phy = to_sas_phy(kobj); + struct phy_attribute *phy_attr = to_phy_attr(attr); + + if (phy_attr->show) + ret = phy_attr->show(phy, page); + return ret; +} + +static ssize_t phy_store_attr(struct kobject *kobj, + struct attribute *attr, + const char *page, size_t size) +{ + ssize_t ret = 0; + struct sas_phy *phy = to_sas_phy(kobj); + struct phy_attribute *phy_attr = to_phy_attr(attr); + + if (phy_attr->store) + ret = phy_attr->store(phy, page, size); + return ret; +} + +static struct sysfs_ops phy_sysfs_ops = { + .show = phy_show_attr, + .store = phy_store_attr, +}; + +static struct kobj_type phy_ktype = { + .sysfs_ops = &phy_sysfs_ops, + .default_attrs = def_attrs, +}; + +/* ---------- Phy class registration ---------- */ + +int sas_register_phys(struct sas_ha_struct *sas_ha) +{ + int i, error; + + for (i = 0; i < ARRAY_SIZE(def_attrs)-1; i++) + def_attrs[i] = &phy_attrs[i].attr; + def_attrs[i] = NULL; + + /* make sas/ha/phys/ appear */ + kobject_set_name(&sas_ha->phy_kset.kobj, "%s", "phys"); + sas_ha->phy_kset.kobj.kset = &sas_ha->ha_kset; /* parent */ + /* we do not inherit the type of the parent */ + sas_ha->phy_kset.kobj.ktype = NULL; + sas_ha->phy_kset.ktype = &phy_ktype; + error = kset_register(&sas_ha->phy_kset); + if (error) + return error; + + /* Now register the phys. */ + for (i = 0; i < sas_ha->num_phys; i++) { + int k; + struct sas_phy *phy = sas_ha->sas_phy[i]; + + phy->error = 0; + INIT_LIST_HEAD(&phy->port_phy_el); + INIT_LIST_HEAD(&phy->port_event_list); + INIT_LIST_HEAD(&phy->phy_event_list); + for (k = 0; k < PORT_NUM_EVENTS; k++) { + struct sas_event *ev = &phy->port_events[k]; + ev->event = k; + INIT_LIST_HEAD(&ev->el); + } + for (k = 0; k < PHY_NUM_EVENTS; k++) { + struct sas_event *ev = &phy->phy_events[k]; + ev->event = k; + INIT_LIST_HEAD(&ev->el); + } + phy->port = NULL; + phy->ha = sas_ha; + spin_lock_init(&phy->frame_rcvd_lock); + spin_lock_init(&phy->sas_prim_lock); + phy->frame_rcvd_size = 0; + + kobject_set_name(&phy->phy_kobj, "%d", i); + phy->phy_kobj.kset = &sas_ha->phy_kset; /* parent */ + phy->phy_kobj.ktype = sas_ha->phy_kset.ktype; + error = kobject_register(&phy->phy_kobj); + if (error) + goto unroll; + } + + return 0; +unroll: + for (i--; i >= 0; i--) + kobject_unregister(&sas_ha->sas_phy[i]->phy_kobj); + + return error; +} + +void sas_unregister_phys(struct sas_ha_struct *sas_ha) +{ + int i; + + for (i = 0; i < sas_ha->num_phys; i++) + kobject_unregister(&sas_ha->sas_phy[i]->phy_kobj); + + kset_unregister(&sas_ha->phy_kset); +} - : send the line "unsubscribe linux-scsi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html