Release 4.11 drivers/scsi/scsi_transport_sas.c
/*
* Copyright (C) 2005-2006 Dell Inc.
* Released under GPL v2.
*
* Serial Attached SCSI (SAS) transport class.
*
* The SAS transport class contains common code to deal with SAS HBAs,
* an aproximated representation of SAS topologies in the driver model,
* and various sysfs attributes to expose these topologies and management
* interfaces to userspace.
*
* In addition to the basic SCSI core objects this transport class
* introduces two additional intermediate objects: The SAS PHY
* as represented by struct sas_phy defines an "outgoing" PHY on
* a SAS HBA or Expander, and the SAS remote PHY represented by
* struct sas_rphy defines an "incoming" PHY on a SAS Expander or
* end device. Note that this is purely a software concept, the
* underlying hardware for a PHY and a remote PHY is the exactly
* the same.
*
* There is no concept of a SAS port in this code, users can see
* what PHYs form a wide port based on the port_identifier attribute,
* which is the same for all PHYs in a port.
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/blkdev.h>
#include <linux/bsg.h>
#include <scsi/scsi.h>
#include <scsi/scsi_request.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_sas.h>
#include "scsi_sas_internal.h"
struct sas_host_attrs {
struct list_head rphy_list;
struct mutex lock;
struct request_queue *q;
u32 next_target_id;
u32 next_expander_id;
int next_port_id;
};
#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data)
/*
* Hack to allow attributes of the same name in different objects.
*/
#define SAS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
struct device_attribute dev_attr_##_prefix##_##_name = \
__ATTR(_name,_mode,_show,_store)
/*
* Pretty printing helpers
*/
#define sas_bitfield_name_match(title, table) \
static ssize_t \
get_sas_##title##_names(u32 table_key, char *buf) \
{ \
char *prefix = ""; \
ssize_t len = 0; \
int i; \
\
for (i = 0; i < ARRAY_SIZE(table); i++) { \
if (table[i].value & table_key) { \
len += sprintf(buf + len, "%s%s", \
prefix, table[i].name); \
prefix = ", "; \
} \
} \
len += sprintf(buf + len, "\n"); \
return len; \
}
#define sas_bitfield_name_set(title, table) \
static ssize_t \
set_sas_##title##_names(u32 *table_key, const char *buf) \
{ \
ssize_t len = 0; \
int i; \
\
for (i = 0; i < ARRAY_SIZE(table); i++) { \
len = strlen(table[i].name); \
if (strncmp(buf, table[i].name, len) == 0 && \
(buf[len] == '\n' || buf[len] == '\0')) { \
*table_key = table[i].value; \
return 0; \
} \
} \
return -EINVAL; \
}
#define sas_bitfield_name_search(title, table) \
static ssize_t \
get_sas_##title##_names(u32 table_key, char *buf) \
{ \
ssize_t len = 0; \
int i; \
\
for (i = 0; i < ARRAY_SIZE(table); i++) { \
if (table[i].value == table_key) { \
len += sprintf(buf + len, "%s", \
table[i].name); \
break; \
} \
} \
len += sprintf(buf + len, "\n"); \
return len; \
}
static struct {
u32 value;
char *name;
}
sas_device_type_names[] = {
{ SAS_PHY_UNUSED, "unused" },
{ SAS_END_DEVICE, "end device" },
{ SAS_EDGE_EXPANDER_DEVICE, "edge expander" },
{ SAS_FANOUT_EXPANDER_DEVICE, "fanout expander" },
};
sas_bitfield_name_search(device_type, sas_device_type_names)
static struct {
u32 value;
char *name;
}
sas_protocol_names[] = {
{ SAS_PROTOCOL_SATA, "sata" },
{ SAS_PROTOCOL_SMP, "smp" },
{ SAS_PROTOCOL_STP, "stp" },
{ SAS_PROTOCOL_SSP, "ssp" },
};
sas_bitfield_name_match(protocol, sas_protocol_names)
static struct {
u32 value;
char *name;
}
sas_linkspeed_names[] = {
{ SAS_LINK_RATE_UNKNOWN, "Unknown" },
{ SAS_PHY_DISABLED, "Phy disabled" },
{ SAS_LINK_RATE_FAILED, "Link Rate failed" },
{ SAS_SATA_SPINUP_HOLD, "Spin-up hold" },
{ SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" },
{ SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" },
{ SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" },
{ SAS_LINK_RATE_12_0_GBPS, "12.0 Gbit" },
};
sas_bitfield_name_search(linkspeed, sas_linkspeed_names)
sas_bitfield_name_set(linkspeed, sas_linkspeed_names)
static struct sas_end_device *sas_sdev_to_rdev(struct scsi_device *sdev)
{
struct sas_rphy *rphy = target_to_rphy(sdev->sdev_target);
struct sas_end_device *rdev;
BUG_ON(rphy->identify.device_type != SAS_END_DEVICE);
rdev = rphy_to_end_device(rphy);
return rdev;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
James Bottomley | 51 | 100.00% | 1 | 100.00% |
Total | 51 | 100.00% | 1 | 100.00% |
static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost,
struct sas_rphy *rphy)
{
struct request *req;
int ret;
int (*handler)(struct Scsi_Host *, struct sas_rphy *, struct request *);
while ((req = blk_fetch_request(q)) != NULL) {
spin_unlock_irq(q->queue_lock);
scsi_req(req)->resid_len = blk_rq_bytes(req);
if (req->next_rq)
scsi_req(req->next_rq)->resid_len =
blk_rq_bytes(req->next_rq);
handler = to_sas_internal(shost->transportt)->f->smp_handler;
ret = handler(shost, rphy, req);
req->errors = ret;
blk_end_request_all(req, ret);
spin_lock_irq(q->queue_lock);
}
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
FUJITA Tomonori | 102 | 68.92% | 2 | 33.33% |
Christoph Hellwig | 34 | 22.97% | 1 | 16.67% |
James Bottomley | 6 | 4.05% | 1 | 16.67% |
Jens Axboe | 5 | 3.38% | 1 | 16.67% |
Tejun Heo | 1 | 0.68% | 1 | 16.67% |
Total | 148 | 100.00% | 6 | 100.00% |
static void sas_host_smp_request(struct request_queue *q)
{
sas_smp_request(q, (struct Scsi_Host *)q->queuedata, NULL);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
FUJITA Tomonori | 27 | 100.00% | 1 | 100.00% |
Total | 27 | 100.00% | 1 | 100.00% |
static void sas_non_host_smp_request(struct request_queue *q)
{
struct sas_rphy *rphy = q->queuedata;
sas_smp_request(q, rphy_to_shost(rphy), rphy);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
FUJITA Tomonori | 32 | 100.00% | 1 | 100.00% |
Total | 32 | 100.00% | 1 | 100.00% |
static void sas_host_release(struct device *dev)
{
struct Scsi_Host *shost = dev_to_shost(dev);
struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
struct request_queue *q = sas_host->q;
if (q)
blk_cleanup_queue(q);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
FUJITA Tomonori | 49 | 100.00% | 1 | 100.00% |
Total | 49 | 100.00% | 1 | 100.00% |
static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
{
struct request_queue *q;
int error;
struct device *dev;
char namebuf[20];
const char *name;
void (*release)(struct device *);
if (!to_sas_internal(shost->transportt)->f->smp_handler) {
printk("%s can't handle SMP requests\n", shost->hostt->name);
return 0;
}
q = blk_alloc_queue(GFP_KERNEL);
if (!q)
return -ENOMEM;
q->cmd_size = sizeof(struct scsi_request);
if (rphy) {
q->request_fn = sas_non_host_smp_request;
dev = &rphy->dev;
name = dev_name(dev);
release = NULL;
} else {
q->request_fn = sas_host_smp_request;
dev = &shost->shost_gendev;
snprintf(namebuf, sizeof(namebuf),
"sas_host%d", shost->host_no);
name = namebuf;
release = sas_host_release;
}
error = blk_init_allocated_queue(q);
if (error)
goto out_cleanup_queue;
error = bsg_register_queue(q, dev, name, release);
if (error)
goto out_cleanup_queue;
if (rphy)
rphy->q = q;
else
to_sas_host_attrs(shost)->q = q;
if (rphy)
q->queuedata = rphy;
else
q->queuedata = shost;
queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q);
return 0;
out_cleanup_queue:
blk_cleanup_queue(q);
return error;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
FUJITA Tomonori | 130 | 48.51% | 3 | 37.50% |
James Bottomley | 79 | 29.48% | 2 | 25.00% |
Omar Sandoval | 54 | 20.15% | 1 | 12.50% |
Kay Sievers | 4 | 1.49% | 1 | 12.50% |
Nicholas Piggin | 1 | 0.37% | 1 | 12.50% |
Total | 268 | 100.00% | 8 | 100.00% |
static void sas_bsg_remove(struct Scsi_Host *shost, struct sas_rphy *rphy)
{
struct request_queue *q;
if (rphy)
q = rphy->q;
else
q = to_sas_host_attrs(shost)->q;
if (!q)
return;
bsg_unregister_queue(q);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
James Bottomley | 52 | 100.00% | 1 | 100.00% |
Total | 52 | 100.00% | 1 | 100.00% |
/*
* SAS host attributes
*/
static int sas_host_setup(struct transport_container *tc, struct device *dev,
struct device *cdev)
{
struct Scsi_Host *shost = dev_to_shost(dev);
struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
INIT_LIST_HEAD(&sas_host->rphy_list);
mutex_init(&sas_host->lock);
sas_host->next_target_id = 0;
sas_host->next_expander_id = 0;
sas_host->next_port_id = 0;
if (sas_bsg_initialize(shost, NULL))
dev_printk(KERN_ERR, dev, "fail to a bsg device %d\n",
shost->host_no);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christoph Hellwig | 56 | 56.00% | 2 | 28.57% |
FUJITA Tomonori | 22 | 22.00% | 1 | 14.29% |
James Bottomley | 21 | 21.00% | 3 | 42.86% |
Tony Jones | 1 | 1.00% | 1 | 14.29% |
Total | 100 | 100.00% | 7 | 100.00% |
static int sas_host_remove(struct transport_container *tc, struct device *dev,
struct device *cdev)
{
struct Scsi_Host *shost = dev_to_shost(dev);
sas_bsg_remove(shost, NULL);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
James Bottomley | 40 | 97.56% | 1 | 50.00% |
Tony Jones | 1 | 2.44% | 1 | 50.00% |
Total | 41 | 100.00% | 2 | 100.00% |
static DECLARE_TRANSPORT_CLASS(sas_host_class,
"sas_host", sas_host_setup, sas_host_remove, NULL);
static int sas_host_match(struct attribute_container *cont,
struct device *dev)
{
struct Scsi_Host *shost;
struct sas_internal *i;
if (!scsi_is_host_device(dev))
return 0;
shost = dev_to_shost(dev);
if (!shost->transportt)
return 0;
if (shost->transportt->host_attrs.ac.class !=
&sas_host_class.class)
return 0;
i = to_sas_internal(shost->transportt);
return &i->t.host_attrs.ac == cont;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christoph Hellwig | 95 | 100.00% | 1 | 100.00% |
Total | 95 | 100.00% | 1 | 100.00% |
static int do_sas_phy_delete(struct device *dev, void *data)
{
int pass = (int)(unsigned long)data;
if (pass == 0 && scsi_is_sas_port(dev))
sas_port_delete(dev_to_sas_port(dev));
else if (pass == 1 && scsi_is_sas_phy(dev))
sas_phy_delete(dev_to_phy(dev));
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
James Bottomley | 36 | 52.17% | 1 | 50.00% |
Christoph Hellwig | 33 | 47.83% | 1 | 50.00% |
Total | 69 | 100.00% | 2 | 100.00% |
/**
* sas_remove_children - tear down a devices SAS data structures
* @dev: device belonging to the sas object
*
* Removes all SAS PHYs and remote PHYs for a given object
*/
void sas_remove_children(struct device *dev)
{
device_for_each_child(dev, (void *)0, do_sas_phy_delete);
device_for_each_child(dev, (void *)1, do_sas_phy_delete);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
James Bottomley | 36 | 100.00% | 1 | 100.00% |
Total | 36 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL(sas_remove_children);
/**
* sas_remove_host - tear down a Scsi_Host's SAS data structures
* @shost: Scsi Host that is torn down
*
* Removes all SAS PHYs and remote PHYs for a given Scsi_Host.
* Must be called just before scsi_remove_host for SAS HBAs.
*/
void sas_remove_host(struct Scsi_Host *shost)
{
sas_remove_children(&shost->shost_gendev);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christoph Hellwig | 17 | 94.44% | 1 | 50.00% |
James Bottomley | 1 | 5.56% | 1 | 50.00% |
Total | 18 | 100.00% | 2 | 100.00% |
EXPORT_SYMBOL(sas_remove_host);
/**
* sas_get_address - return the SAS address of the device
* @sdev: scsi device
*
* Returns the SAS address of the scsi device
*/
u64 sas_get_address(struct scsi_device *sdev)
{
struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
return rdev->rphy.identify.sas_address;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
James Bottomley | 29 | 100.00% | 1 | 100.00% |
Total | 29 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL(sas_get_address);
/**
* sas_tlr_supported - checking TLR bit in vpd 0x90
* @sdev: scsi device struct
*
* Check Transport Layer Retries are supported or not.
* If vpd page 0x90 is present, TRL is supported.
*
*/
unsigned int
sas_tlr_supported(struct scsi_device *sdev)
{
const int vpd_len = 32;
struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
char *buffer = kzalloc(vpd_len, GFP_KERNEL);
int ret = 0;
if (scsi_get_vpd_page(sdev, 0x90, buffer, vpd_len))
goto out;
/*
* Magic numbers: the VPD Protocol page (0x90)
* has a 4 byte header and then one entry per device port
* the TLR bit is at offset 8 on each port entry
* if we take the first port, that's at total offset 12
*/
ret = buffer[12] & 0x01;
out:
kfree(buffer);
rdev->tlr_supported = ret;
return ret;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
James Bottomley | 85 | 100.00% | 1 | 100.00% |
Total | 85 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL_GPL(sas_tlr_supported);
/**
* sas_disable_tlr - setting TLR flags
* @sdev: scsi device struct
*
* Seting tlr_enabled flag to 0.
*
*/
void
sas_disable_tlr(struct scsi_device *sdev)
{
struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
rdev->tlr_enabled = 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
James Bottomley | 26 | 100.00% | 1 | 100.00% |
Total | 26 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL_GPL(sas_disable_tlr);
/**
* sas_enable_tlr - setting TLR flags
* @sdev: scsi device struct
*
* Seting tlr_enabled flag 1.
*
*/
void sas_enable_tlr(struct scsi_device *sdev)
{
unsigned int tlr_supported = 0;
tlr_supported = sas_tlr_supported(sdev);
if (tlr_supported) {
struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
rdev->tlr_enabled = 1;
}
return;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
James Bottomley | 46 | 100.00% | 1 | 100.00% |
Total | 46 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL_GPL(sas_enable_tlr);
unsigned int sas_is_tlr_enabled(struct scsi_device *sdev)
{
struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);
return rdev->tlr_enabled;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
James Bottomley | 26 | 100.00% | 1 | 100.00% |
Total | 26 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL_GPL(sas_is_tlr_enabled);
/*
* SAS Phy attributes
*/
#define sas_phy_show_simple(field, name, format_string, cast) \
static ssize_t \
show_sas_phy_##name(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct sas_phy *phy = transport_class_to_phy(dev); \
\
return snprintf(buf, 20, format_string, cast phy->field); \
}
#define sas_phy_simple_attr(field, name, format_string, type) \
sas_phy_show_simple(field, name, format_string, (type)) \
static DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
#define sas_phy_show_protocol(field, name) \
static ssize_t \
show_sas_phy_##name(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct sas_phy *phy = transport_class_to_phy(dev); \
\
if (!phy->field) \
return snprintf(buf, 20, "none\n"); \
return get_sas_protocol_names(phy->field, buf); \
}
#define sas_phy_protocol_attr(field, name) \
sas_phy_show_protocol(field, name) \
static DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
#define sas_phy_show_linkspeed(field) \
static ssize_t \
show_sas_phy_##field(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct sas_phy *phy = transport_class_to_phy(dev); \
\
return get_sas_linkspeed_names(phy->field, buf); \
}
/* Fudge to tell if we're minimum or maximum */
#define sas_phy_store_linkspeed(field) \
static ssize_t \
store_sas_phy_##field(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count) \
{ \
struct sas_phy *phy = transport_class_to_phy(dev); \
struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); \
struct sas_internal *i = to_sas_internal(shost->transportt); \
u32 value; \
struct sas_phy_linkrates rates = {0}; \
int error; \
\
error = set_sas_linkspeed_names(&value, buf); \
if (error) \
return error; \
rates.field = value; \
error = i->f->set_phy_speed(phy, &rates); \
\
return error ? error : count; \
}
#define sas_phy_linkspeed_rw_attr(field) \
sas_phy_show_linkspeed(field) \
sas_phy_store_linkspeed(field) \
static DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, \
store_sas_phy_##field)
#define sas_phy_linkspeed_attr(field) \
sas_phy_show_linkspeed(field) \
static DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
#define sas_phy_show_linkerror(field) \
static ssize_t \
show_sas_phy_##field(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct sas_phy *phy = transport_class_to_phy(dev); \
struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); \
struct sas_internal *i = to_sas_internal(shost->transportt); \
int error; \
\
error = i->f->get_linkerrors ? i->f->get_linkerrors(phy) : 0; \
if (error) \
return error; \
return snprintf(buf, 20, "%u\n", phy->field); \
}
#define sas_phy_linkerror_attr(field) \
sas_phy_show_linkerror(field) \
static DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
static ssize_t
show_sas_device_type(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct sas_phy *phy = transport_class_to_phy(dev);
if (!phy->identify.device_type)
return snprintf(buf, 20, "none\n");
return get_sas_device_type_names(phy->identify.device_type, buf);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christoph Hellwig | 53 | 86.89% | 1 | 50.00% |
Tony Jones | 8 | 13.11% | 1 | 50.00% |
Total | 61 | 100.00% | 2 | 100.00% |
static DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL);
static ssize_t do_sas_phy_enable(struct device *dev,
size_t count, int enable)
{
struct sas_phy *phy = transport_class_to_phy(dev);
struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
struct sas_internal *i = to_sas_internal(shost->transportt);
int error;
error = i->f->phy_enable(phy, enable);
if (error)
return error;
phy->enabled = enable;
return count;
}Contributors
Person | Tokens | Prop | Commits | CommitProp |
Darrick J. Wong | 82 | 96.47% | 1 | 50.00% |
Tony Jones | 3 | 3.53% | 1 | 50.00% |
Total | 85 | 100.00% | 2 | 100.00% |
;
static ssize_t
store_sas_phy_enable(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
if (count < 1)
return -EINVAL;
switch (buf[0]) {
case '0':
do_sas_phy_enable(dev, count, 0);
break;
case '1':
do_sas_phy_enable(dev, count, 1);
break;
default:
return -EINVAL;
}
return count;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Darrick J. Wong | 68 | 88.31% | 1 | 50.00% |
Tony Jones | 9 | 11.69% | 1 | 50.00% |
Total | 77 | 100.00% | 2 | 100.00% |
static ssize_t
show_sas_phy_enable(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct sas_phy *phy = transport_class_to_phy(dev);
return snprintf(buf, 20, "%d", phy->enabled);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Darrick J. Wong | 36 | 81.82% | 1 | 50.00% |
Tony Jones | 8 | 18.18% | 1 | 50.00% |
Total | 44 | 100.00% | 2 | 100.00% |
static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable,
store_sas_phy_enable);
static ssize_t
do_sas_phy_reset(struct device *dev, size_t count, int hard_reset)
{
struct sas_phy *phy = transport_class_to_phy(dev);
struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
struct sas_internal *i = to_sas_internal(shost->transportt);
int error;
error = i->f->phy_reset(phy, hard_reset);
if (error)
return error;
phy->enabled = 1;
return count;
}Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christoph Hellwig | 76 | 89.41% | 1 | 33.33% |
Dan J Williams | 6 | 7.06% | 1 | 33.33% |
Tony Jones | 3 | 3.53% | 1 | 33.33% |
Total | 85 | 100.00% | 3 | 100.00% |
;
static ssize_t
store_sas_link_reset(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
return do_sas_phy_reset(dev, count, 0);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christoph Hellwig | 26 | 76.47% | 1 | 50.00% |
Tony Jones | 8 | 23.53% | 1 | 50.00% |
Total | 34 | 100.00% | 2 | 100.00% |
static DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset);
static ssize_t
store_sas_hard_reset(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
return do_sas_phy_reset(dev, count, 1);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christoph Hellwig | 26 | 76.47% | 1 | 50.00% |
Tony Jones | 8 | 23.53% | 1 | 50.00% |
Total | 34 | 100.00% | 2 | 100.00% |
static DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset);
sas_phy_protocol_attr(identify.initiator_port_protocols,
initiator_port_protocols);
sas_phy_protocol_attr(identify.target_port_protocols,
target_port_protocols);
sas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",
unsigned long long);
sas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", int);
sas_phy_linkspeed_attr(negotiated_linkrate);
sas_phy_linkspeed_attr(minimum_linkrate_hw);
sas_phy_linkspeed_rw_attr(minimum_linkrate);
sas_phy_linkspeed_attr(maximum_linkrate_hw);
sas_phy_linkspeed_rw_attr(maximum_linkrate);
sas_phy_linkerror_attr(invalid_dword_count);
sas_phy_linkerror_attr(running_disparity_error_count);
sas_phy_linkerror_attr(loss_of_dword_sync_count);
sas_phy_linkerror_attr(phy_reset_problem_count);
static int sas_phy_setup(struct transport_container *tc, struct device *dev,
struct device *cdev)
{
struct sas_phy *phy = dev_to_phy(dev);
struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
struct sas_internal *i = to_sas_internal(shost->transportt);
if (i->f->phy_setup)
i->f->phy_setup(phy);
return 0;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dan J Williams | 77 | 100.00% | 1 | 100.00% |
Total | 77 | 100.00% | 1 | 100.00% |
static DECLARE_TRANSPORT_CLASS(sas_phy_class,
"sas_phy", sas_phy_setup, NULL, NULL);
static int sas_phy_match(struct attribute_container *cont, struct device *dev)
{
struct Scsi_Host *shost;
struct sas_internal *i;
if (!scsi_is_sas_phy(dev))
return 0;
shost = dev_to_shost(dev->parent);
if (!shost->transportt)
return 0;
if (shost->transportt->host_attrs.ac.class !=
&sas_host_class.class)
return 0;
i = to_sas_internal(shost->transportt);
return &i->phy_attr_cont.ac == cont;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christoph Hellwig | 95 | 100.00% | 1 | 100.00% |
Total | 95 | 100.00% | 1 | 100.00% |
static void sas_phy_release(struct device *dev)
{
struct sas_phy *phy = dev_to_phy(dev);
struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
struct sas_internal *i = to_sas_internal(shost->transportt);
if (i->f->phy_release)
i->f->phy_release(phy);
put_device(dev->parent);
kfree(phy);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Dan J Williams | 43 | 56.58% | 1 | 50.00% |
Christoph Hellwig | 33 | 43.42% | 1 | 50.00% |
Total | 76 | 100.00% | 2 | 100.00% |
/**
* sas_phy_alloc - allocates and initialize a SAS PHY structure
* @parent: Parent device
* @number: Phy index
*
* Allocates an SAS PHY structure. It will be added in the device tree
* below the device specified by @parent, which has to be either a Scsi_Host
* or sas_rphy.
*
* Returns:
* SAS PHY allocated or %NULL if the allocation failed.
*/
struct sas_phy *sas_phy_alloc(struct device *parent, int number)
{
struct Scsi_Host *shost = dev_to_shost(parent);
struct sas_phy *phy;
phy = kzalloc(sizeof(*phy), GFP_KERNEL);
if (!phy)
return NULL;
phy->number = number;
phy->enabled = 1;
device_initialize(&phy->dev);
phy->dev.parent = get_device(parent);
phy->dev.release = sas_phy_release;
INIT_LIST_HEAD(&phy->port_siblings);
if (scsi_is_sas_expander_device(parent)) {
struct sas_rphy *rphy = dev_to_rphy(parent);
dev_set_name(&phy->dev, "phy-%d:%d:%d", shost->host_no,
rphy->scsi_target_id, number);
} else
dev_set_name(&phy->dev, "phy-%d:%d", shost->host_no, number);
transport_setup_device(&phy->dev);
return phy;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christoph Hellwig | 108 | 65.45% | 1 | 16.67% |
James Bottomley | 46 | 27.88% | 2 | 33.33% |
Darrick J. Wong | 6 | 3.64% | 1 | 16.67% |
Kay Sievers | 4 | 2.42% | 1 | 16.67% |
Jes Sorensen | 1 | 0.61% | 1 | 16.67% |
Total | 165 | 100.00% | 6 | 100.00% |
EXPORT_SYMBOL(sas_phy_alloc);
/**
* sas_phy_add - add a SAS PHY to the device hierarchy
* @phy: The PHY to be added
*
* Publishes a SAS PHY to the rest of the system.
*/
int sas_phy_add(struct sas_phy *phy)
{
int error;
error = device_add(&phy->dev);
if (!error) {
transport_add_device(&phy->dev);
transport_configure_device(&phy->dev);
}
return error;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christoph Hellwig | 49 | 100.00% | 1 | 100.00% |
Total | 49 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL(sas_phy_add);
/**
* sas_phy_free - free a SAS PHY
* @phy: SAS PHY to free
*
* Frees the specified SAS PHY.
*
* Note:
* This function must only be called on a PHY that has not
* successfully been added using sas_phy_add().
*/
void sas_phy_free(struct sas_phy *phy)
{
transport_destroy_device(&phy->dev);
put_device(&phy->dev);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
Christoph Hellwig | 25 | 96.15% | 1 | 50.00% |
Mike Anderson | 1 | 3.85% | 1 | 50.00% |
Total | 26 | 100.00% | 2 | 100.00% |
EXPORT_SYMBOL(sas_phy_free);
/**
* sas_phy_delete - remove SAS PHY
* @phy: SAS PHY to remove
*
* Removes the specified SAS PHY. If the SAS PHY has an
* associated remote PHY it is removed before.
*/
void
sas_phy_delete(struct sas_phy *phy)
{
struct device *dev = &phy->dev;
/* this happens if the phy is still part of a port when deleted */
BUG_ON(!list_empty(&phy->port_siblings));
transport_remove_device(dev);
device_del(dev);
transport_destroy_device(dev);
put_device(dev);
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
James Bottomley | 27 | 50.94% | 1 | 50.00% |
Christoph Hellwig | 26 | 49.06% | 1 | 50.00% |
Total | 53 | 100.00% | 2 | 100.00% |
EXPORT_SYMBOL(sas_phy_delete);
/**
* scsi_is_sas_phy - check if a struct device represents a SAS PHY
* @dev: device to check
*
* Returns:
* %1 if the device represents a SAS PHY, %0 else
*/
int scsi_is_sas_phy(const struct device *dev)
{
return dev->release == sas_phy_release;
}
Contributors
Person | Tokens | Prop | Commits | CommitProp |
James Bottomley | 18 | 100.00% | 1 | 100.00% |
Total | 18 | 100.00% | 1 | 100.00% |
EXPORT_SYMBOL(scsi_is_sas_phy);
/*
* SAS Port attributes
*/
#define sas_port_show_simple(field, name, format_string, cast) \
static ssize_t \
show_sas_port_##name(struct device *dev, \
struct device_attribute *attr, char *buf) \
{ \
struct sas_port *port = transport_class_to_sas_port(dev); \
\
return snprintf(buf, 20, format_string, cast port->field); \
}
#define sas_port_simple_attr(field, name, format_string, type) \
sas_port_show_simple(field, name, format_string, (type)) \
static DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL)
sas_port_simple_attr(num_phys, num_phys, "%d\n", int);
static DECLARE_TRANSPORT_CLASS(sas_port_class,
"sas_port", NULL, NULL, NULL);
static int sas_port_match(struct attribute_container *cont, struct device *dev)
{
struct Scsi_Host *shost;
struct sas_internal *i;
if (!scsi_is_sas_port(dev))
return 0;
s