1c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 2a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig * Copyright (C) 2005-2006 Dell Inc. 3c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Released under GPL v2. 4c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 5c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Serial Attached SCSI (SAS) transport class. 6c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 7c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * The SAS transport class contains common code to deal with SAS HBAs, 8c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * an aproximated representation of SAS topologies in the driver model, 9b1c118121ae37285ddc0a7a908999196bb35fb0bJoe Perches * and various sysfs attributes to expose these topologies and management 10c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * interfaces to userspace. 11c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 12c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * In addition to the basic SCSI core objects this transport class 13c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * introduces two additional intermediate objects: The SAS PHY 14c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * as represented by struct sas_phy defines an "outgoing" PHY on 15c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * a SAS HBA or Expander, and the SAS remote PHY represented by 16c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * struct sas_rphy defines an "incoming" PHY on a SAS Expander or 17c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * end device. Note that this is purely a software concept, the 18c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * underlying hardware for a PHY and a remote PHY is the exactly 19c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * the same. 20c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 21c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * There is no concept of a SAS port in this code, users can see 22c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * what PHYs form a wide port based on the port_identifier attribute, 23c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * which is the same for all PHYs in a port. 24c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 25c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 26c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <linux/init.h> 27c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <linux/module.h> 28f6a570333e554b48ad589e7137c77c57809eee81Al Viro#include <linux/jiffies.h> 29c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <linux/err.h> 308c65b4a60450590e79a28e9717ceffa9e4debb3fTim Schmielau#include <linux/slab.h> 318c65b4a60450590e79a28e9717ceffa9e4debb3fTim Schmielau#include <linux/string.h> 327aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori#include <linux/blkdev.h> 337aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori#include <linux/bsg.h> 34c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 35e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig#include <scsi/scsi.h> 36c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_device.h> 37c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_host.h> 38c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_transport.h> 39c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#include <scsi/scsi_transport_sas.h> 40c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 41d6159c17c2c76963a8067d1e1ac3c4c36c05e674James Bottomley#include "scsi_sas_internal.h" 42c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct sas_host_attrs { 43c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct list_head rphy_list; 44e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig struct mutex lock; 45b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley struct request_queue *q; 46c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 next_target_id; 4779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley u32 next_expander_id; 48c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley int next_port_id; 49c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 50c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data) 51c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 52c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 53c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 54c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Hack to allow attributes of the same name in different objects. 55c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 56ee959b00c335d7780136c5abda37809191fe52c3Tony Jones#define SAS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \ 57ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute dev_attr_##_prefix##_##_name = \ 58c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig __ATTR(_name,_mode,_show,_store) 59c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 60c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 61c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 62c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Pretty printing helpers 63c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 64c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 65c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_bitfield_name_match(title, table) \ 66c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 67c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigget_sas_##title##_names(u32 table_key, char *buf) \ 68c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 69c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *prefix = ""; \ 70c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig ssize_t len = 0; \ 71c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int i; \ 72c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 736391a11375de5e2bb1eb8481e54619761dc65d9fTobias Klauser for (i = 0; i < ARRAY_SIZE(table); i++) { \ 74c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (table[i].value & table_key) { \ 75c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "%s%s", \ 76c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig prefix, table[i].name); \ 77c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig prefix = ", "; \ 78c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 79c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 80c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "\n"); \ 81c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return len; \ 82c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 83c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 84d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define sas_bitfield_name_set(title, table) \ 85d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleystatic ssize_t \ 86d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleyset_sas_##title##_names(u32 *table_key, const char *buf) \ 87d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley{ \ 88d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley ssize_t len = 0; \ 89d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley int i; \ 90d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley \ 91d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley for (i = 0; i < ARRAY_SIZE(table); i++) { \ 92d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley len = strlen(table[i].name); \ 93d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley if (strncmp(buf, table[i].name, len) == 0 && \ 94d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley (buf[len] == '\n' || buf[len] == '\0')) { \ 95d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley *table_key = table[i].value; \ 96d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley return 0; \ 97d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley } \ 98d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley } \ 99d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley return -EINVAL; \ 100d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley} 101d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley 102c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_bitfield_name_search(title, table) \ 103c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 104c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigget_sas_##title##_names(u32 table_key, char *buf) \ 105c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 106c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig ssize_t len = 0; \ 107c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int i; \ 108c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 1096391a11375de5e2bb1eb8481e54619761dc65d9fTobias Klauser for (i = 0; i < ARRAY_SIZE(table); i++) { \ 110c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (table[i].value == table_key) { \ 111c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "%s", \ 112c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig table[i].name); \ 113c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig break; \ 114c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 115c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } \ 116c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig len += sprintf(buf + len, "\n"); \ 117c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return len; \ 118c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 119c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 120c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct { 121c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 value; 122c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *name; 123c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} sas_device_type_names[] = { 124c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PHY_UNUSED, "unused" }, 125c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_END_DEVICE, "end device" }, 126c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_EDGE_EXPANDER_DEVICE, "edge expander" }, 127c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_FANOUT_EXPANDER_DEVICE, "fanout expander" }, 128c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 129c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_bitfield_name_search(device_type, sas_device_type_names) 130c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 131c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 132c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct { 133c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 value; 134c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *name; 135c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} sas_protocol_names[] = { 136c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_SATA, "sata" }, 137c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_SMP, "smp" }, 138c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_STP, "stp" }, 139c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PROTOCOL_SSP, "ssp" }, 140c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 141c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_bitfield_name_match(protocol, sas_protocol_names) 142c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 143c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic struct { 144c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig u32 value; 145c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig char *name; 146c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} sas_linkspeed_names[] = { 147c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_UNKNOWN, "Unknown" }, 148c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_PHY_DISABLED, "Phy disabled" }, 149c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_FAILED, "Link Rate failed" }, 150c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_SATA_SPINUP_HOLD, "Spin-up hold" }, 151c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" }, 152c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" }, 1537e6dff62dad539cbd608bb3b8b833193d13f00acJames Bottomley { SAS_LINK_RATE_6_0_GBPS, "6.0 Gbit" }, 154c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig}; 155c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_bitfield_name_search(linkspeed, sas_linkspeed_names) 156d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleysas_bitfield_name_set(linkspeed, sas_linkspeed_names) 157c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1580f88009d5cfae890bd3466126d1622ad4f16b798James Bottomleystatic struct sas_end_device *sas_sdev_to_rdev(struct scsi_device *sdev) 1590f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley{ 1600f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley struct sas_rphy *rphy = target_to_rphy(sdev->sdev_target); 1610f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley struct sas_end_device *rdev; 1620f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley 1630f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley BUG_ON(rphy->identify.device_type != SAS_END_DEVICE); 1640f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley 1650f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley rdev = rphy_to_end_device(rphy); 1660f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley return rdev; 1670f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley} 1680f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley 1697aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonoristatic void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost, 1707aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori struct sas_rphy *rphy) 1717aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori{ 1727aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori struct request *req; 1737aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori int ret; 1747aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori int (*handler)(struct Scsi_Host *, struct sas_rphy *, struct request *); 1757aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori 1767eaceaccab5f40bbfda044629a6298616aeaed50Jens Axboe while ((req = blk_fetch_request(q)) != NULL) { 1777aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori spin_unlock_irq(q->queue_lock); 1787aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori 1797aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori handler = to_sas_internal(shost->transportt)->f->smp_handler; 1807aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori ret = handler(shost, rphy, req); 1812d507a01dac338831266b44ccbb01c69e84606edJames Bottomley req->errors = ret; 1827aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori 18393bdcba5a7e55307e27671594c3cd8b4669b9e7aFUJITA Tomonori blk_end_request_all(req, ret); 1847aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori 18593bdcba5a7e55307e27671594c3cd8b4669b9e7aFUJITA Tomonori spin_lock_irq(q->queue_lock); 1867aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori } 1877aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori} 1887aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori 1897aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonoristatic void sas_host_smp_request(struct request_queue *q) 1907aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori{ 1917aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori sas_smp_request(q, (struct Scsi_Host *)q->queuedata, NULL); 1927aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori} 1937aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori 1947aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonoristatic void sas_non_host_smp_request(struct request_queue *q) 1957aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori{ 1967aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori struct sas_rphy *rphy = q->queuedata; 1977aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori sas_smp_request(q, rphy_to_shost(rphy), rphy); 1987aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori} 1997aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori 20093c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonoristatic void sas_host_release(struct device *dev) 20193c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori{ 20293c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori struct Scsi_Host *shost = dev_to_shost(dev); 20393c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 20493c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori struct request_queue *q = sas_host->q; 20593c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori 20693c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori if (q) 20793c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori blk_cleanup_queue(q); 20893c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori} 20993c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori 21039dca558a5b52b63e49bc234a7e887be092aa690James Bottomleystatic int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy) 2117aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori{ 2127aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori struct request_queue *q; 2137aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori int error; 21439dca558a5b52b63e49bc234a7e887be092aa690James Bottomley struct device *dev; 21571610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers char namebuf[20]; 21639dca558a5b52b63e49bc234a7e887be092aa690James Bottomley const char *name; 21793c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori void (*release)(struct device *); 2187aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori 2197aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori if (!to_sas_internal(shost->transportt)->f->smp_handler) { 2207aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori printk("%s can't handle SMP requests\n", shost->hostt->name); 2217aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori return 0; 2227aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori } 2237aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori 22439dca558a5b52b63e49bc234a7e887be092aa690James Bottomley if (rphy) { 2257aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori q = blk_init_queue(sas_non_host_smp_request, NULL); 22639dca558a5b52b63e49bc234a7e887be092aa690James Bottomley dev = &rphy->dev; 22771610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers name = dev_name(dev); 22893c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori release = NULL; 22939dca558a5b52b63e49bc234a7e887be092aa690James Bottomley } else { 2307aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori q = blk_init_queue(sas_host_smp_request, NULL); 23139dca558a5b52b63e49bc234a7e887be092aa690James Bottomley dev = &shost->shost_gendev; 23239dca558a5b52b63e49bc234a7e887be092aa690James Bottomley snprintf(namebuf, sizeof(namebuf), 23339dca558a5b52b63e49bc234a7e887be092aa690James Bottomley "sas_host%d", shost->host_no); 23439dca558a5b52b63e49bc234a7e887be092aa690James Bottomley name = namebuf; 23593c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori release = sas_host_release; 23639dca558a5b52b63e49bc234a7e887be092aa690James Bottomley } 2377aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori if (!q) 2387aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori return -ENOMEM; 2397aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori 24093c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori error = bsg_register_queue(q, dev, name, release); 2417aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori if (error) { 2427aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori blk_cleanup_queue(q); 2437aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori return -ENOMEM; 2447aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori } 2457aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori 2467aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori if (rphy) 247b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley rphy->q = q; 248b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley else 249b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley to_sas_host_attrs(shost)->q = q; 250b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley 251b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley if (rphy) 2527aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori q->queuedata = rphy; 2537aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori else 2547aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori q->queuedata = shost; 2557aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori 25675ad23bc0fcb4f992a5d06982bf0857ab1738e9eNick Piggin queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q); 2577aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori return 0; 2587aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori} 2597aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori 260b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomleystatic void sas_bsg_remove(struct Scsi_Host *shost, struct sas_rphy *rphy) 261b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley{ 262b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley struct request_queue *q; 263b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley 264b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley if (rphy) 265b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley q = rphy->q; 266b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley else 267b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley q = to_sas_host_attrs(shost)->q; 268b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley 269b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley if (!q) 270b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley return; 271b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley 272b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley bsg_unregister_queue(q); 273b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley} 274b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley 275c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 276c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS host attributes 277c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 278c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 27937be6eeb4990c05fc7dd683ceaf1501d46ebe9a4James Bottomleystatic int sas_host_setup(struct transport_container *tc, struct device *dev, 280ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device *cdev) 281c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 282c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(dev); 283c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 284c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 285c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig INIT_LIST_HEAD(&sas_host->rphy_list); 286e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_init(&sas_host->lock); 287c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_host->next_target_id = 0; 28879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley sas_host->next_expander_id = 0; 289c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley sas_host->next_port_id = 0; 2907aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori 29139dca558a5b52b63e49bc234a7e887be092aa690James Bottomley if (sas_bsg_initialize(shost, NULL)) 2927aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori dev_printk(KERN_ERR, dev, "fail to a bsg device %d\n", 2937aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori shost->host_no); 2947aa68e80bd481faae1234bc2a7e4bcc9348f98b4FUJITA Tomonori 295c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 296c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 297c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 298b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomleystatic int sas_host_remove(struct transport_container *tc, struct device *dev, 299ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device *cdev) 300b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley{ 301b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley struct Scsi_Host *shost = dev_to_shost(dev); 302b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley 303b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley sas_bsg_remove(shost, NULL); 304b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley 305b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley return 0; 306b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley} 307b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley 308c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_host_class, 309b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley "sas_host", sas_host_setup, sas_host_remove, NULL); 310c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 311c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_host_match(struct attribute_container *cont, 312c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev) 313c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 314c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost; 315c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 316c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 317c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!scsi_is_host_device(dev)) 318c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 319c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost = dev_to_shost(dev); 320c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 321c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!shost->transportt) 322c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 323c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (shost->transportt->host_attrs.ac.class != 324c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig &sas_host_class.class) 325c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 326c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 327c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = to_sas_internal(shost->transportt); 328c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->t.host_attrs.ac == cont; 329c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 330c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 331c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int do_sas_phy_delete(struct device *dev, void *data) 332c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 33365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley int pass = (int)(unsigned long)data; 33465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 33565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (pass == 0 && scsi_is_sas_port(dev)) 33665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_delete(dev_to_sas_port(dev)); 33765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley else if (pass == 1 && scsi_is_sas_phy(dev)) 338c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_delete(dev_to_phy(dev)); 339c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 340c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 341c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 342c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 343eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_remove_children - tear down a devices SAS data structures 34465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @dev: device belonging to the sas object 34565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 34665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Removes all SAS PHYs and remote PHYs for a given object 34765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 34865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_remove_children(struct device *dev) 34965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 35065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley device_for_each_child(dev, (void *)0, do_sas_phy_delete); 35165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley device_for_each_child(dev, (void *)1, do_sas_phy_delete); 35265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 35365c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_remove_children); 35465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 35565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 356eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_remove_host - tear down a Scsi_Host's SAS data structures 357c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @shost: Scsi Host that is torn down 358c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 359c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Removes all SAS PHYs and remote PHYs for a given Scsi_Host. 360c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Must be called just before scsi_remove_host for SAS HBAs. 361c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 362c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_remove_host(struct Scsi_Host *shost) 363c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 36465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_remove_children(&shost->shost_gendev); 365c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 366c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_remove_host); 367c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 3680f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley/** 3690f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * sas_tlr_supported - checking TLR bit in vpd 0x90 3700f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * @sdev: scsi device struct 3710f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * 3720f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * Check Transport Layer Retries are supported or not. 3730f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * If vpd page 0x90 is present, TRL is supported. 3740f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * 3750f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley */ 3760f88009d5cfae890bd3466126d1622ad4f16b798James Bottomleyunsigned int 3770f88009d5cfae890bd3466126d1622ad4f16b798James Bottomleysas_tlr_supported(struct scsi_device *sdev) 3780f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley{ 3790f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley const int vpd_len = 32; 3800f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley struct sas_end_device *rdev = sas_sdev_to_rdev(sdev); 3810f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley char *buffer = kzalloc(vpd_len, GFP_KERNEL); 3820f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley int ret = 0; 3830f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley 3840f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley if (scsi_get_vpd_page(sdev, 0x90, buffer, vpd_len)) 3850f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley goto out; 3860f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley 3870f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley /* 3880f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * Magic numbers: the VPD Protocol page (0x90) 3890f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * has a 4 byte header and then one entry per device port 3900f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * the TLR bit is at offset 8 on each port entry 3910f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * if we take the first port, that's at total offset 12 3920f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley */ 3930f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley ret = buffer[12] & 0x01; 3940f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley 3950f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley out: 3960f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley kfree(buffer); 3970f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley rdev->tlr_supported = ret; 3980f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley return ret; 3990f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley 4000f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley} 4010f88009d5cfae890bd3466126d1622ad4f16b798James BottomleyEXPORT_SYMBOL_GPL(sas_tlr_supported); 4020f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley 4030f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley/** 4040f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * sas_disable_tlr - setting TLR flags 4050f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * @sdev: scsi device struct 4060f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * 4070f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * Seting tlr_enabled flag to 0. 4080f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * 4090f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley */ 4100f88009d5cfae890bd3466126d1622ad4f16b798James Bottomleyvoid 4110f88009d5cfae890bd3466126d1622ad4f16b798James Bottomleysas_disable_tlr(struct scsi_device *sdev) 4120f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley{ 4130f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley struct sas_end_device *rdev = sas_sdev_to_rdev(sdev); 4140f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley 4150f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley rdev->tlr_enabled = 0; 4160f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley} 4170f88009d5cfae890bd3466126d1622ad4f16b798James BottomleyEXPORT_SYMBOL_GPL(sas_disable_tlr); 4180f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley 4190f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley/** 4200f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * sas_enable_tlr - setting TLR flags 4210f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * @sdev: scsi device struct 4220f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * 4230f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * Seting tlr_enabled flag 1. 4240f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley * 4250f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley */ 4260f88009d5cfae890bd3466126d1622ad4f16b798James Bottomleyvoid sas_enable_tlr(struct scsi_device *sdev) 4270f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley{ 4280f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley unsigned int tlr_supported = 0; 4290f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley tlr_supported = sas_tlr_supported(sdev); 4300f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley 4310f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley if (tlr_supported) { 4320f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley struct sas_end_device *rdev = sas_sdev_to_rdev(sdev); 4330f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley 4340f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley rdev->tlr_enabled = 1; 4350f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley } 4360f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley 4370f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley return; 4380f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley} 4390f88009d5cfae890bd3466126d1622ad4f16b798James BottomleyEXPORT_SYMBOL_GPL(sas_enable_tlr); 4400f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley 4410f88009d5cfae890bd3466126d1622ad4f16b798James Bottomleyunsigned int sas_is_tlr_enabled(struct scsi_device *sdev) 4420f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley{ 4430f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley struct sas_end_device *rdev = sas_sdev_to_rdev(sdev); 4440f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley return rdev->tlr_enabled; 4450f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley} 4460f88009d5cfae890bd3466126d1622ad4f16b798James BottomleyEXPORT_SYMBOL_GPL(sas_is_tlr_enabled); 447c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 448c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 44965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * SAS Phy attributes 450c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 451c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 452c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_show_simple(field, name, format_string, cast) \ 453c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 454ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_phy_##name(struct device *dev, \ 455ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) \ 456c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 457ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_phy *phy = transport_class_to_phy(dev); \ 458c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 459c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, format_string, cast phy->field); \ 460c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 461c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 462c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_simple_attr(field, name, format_string, type) \ 463c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_show_simple(field, name, format_string, (type)) \ 464ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) 465c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 466c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_show_protocol(field, name) \ 467c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 468ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_phy_##name(struct device *dev, \ 469ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) \ 470c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 471ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_phy *phy = transport_class_to_phy(dev); \ 472c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 473c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!phy->field) \ 474c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); \ 475c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_protocol_names(phy->field, buf); \ 476c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 477c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 478c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_protocol_attr(field, name) \ 479c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_show_protocol(field, name) \ 480ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL) 481c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 482c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_show_linkspeed(field) \ 483c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 484ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_phy_##field(struct device *dev, \ 485ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) \ 486c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 487ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_phy *phy = transport_class_to_phy(dev); \ 488c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 489c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_linkspeed_names(phy->field, buf); \ 490c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 491c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 492d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley/* Fudge to tell if we're minimum or maximum */ 493d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define sas_phy_store_linkspeed(field) \ 494d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleystatic ssize_t \ 495ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstore_sas_phy_##field(struct device *dev, \ 496ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, \ 497ee959b00c335d7780136c5abda37809191fe52c3Tony Jones const char *buf, size_t count) \ 498d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley{ \ 499ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_phy *phy = transport_class_to_phy(dev); \ 500d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); \ 501d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley struct sas_internal *i = to_sas_internal(shost->transportt); \ 502d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley u32 value; \ 503d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley struct sas_phy_linkrates rates = {0}; \ 504d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley int error; \ 505d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley \ 506d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley error = set_sas_linkspeed_names(&value, buf); \ 507d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley if (error) \ 508d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley return error; \ 509d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley rates.field = value; \ 510d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley error = i->f->set_phy_speed(phy, &rates); \ 511d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley \ 512d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley return error ? error : count; \ 513d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley} 514d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley 515d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define sas_phy_linkspeed_rw_attr(field) \ 516d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley sas_phy_show_linkspeed(field) \ 517d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley sas_phy_store_linkspeed(field) \ 518ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, \ 519d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley store_sas_phy_##field) 520d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley 521c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_phy_linkspeed_attr(field) \ 522c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_phy_show_linkspeed(field) \ 523ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) 524c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 525d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley 526c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig#define sas_phy_show_linkerror(field) \ 527c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigstatic ssize_t \ 528ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_phy_##field(struct device *dev, \ 529ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) \ 530c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig{ \ 531ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_phy *phy = transport_class_to_phy(dev); \ 532c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); \ 533c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); \ 534c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig int error; \ 535c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig \ 536dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley error = i->f->get_linkerrors ? i->f->get_linkerrors(phy) : 0; \ 537c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig if (error) \ 538c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig return error; \ 539c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig return snprintf(buf, 20, "%u\n", phy->field); \ 540c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig} 541c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig 542c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig#define sas_phy_linkerror_attr(field) \ 543c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig sas_phy_show_linkerror(field) \ 544ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL) 545c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig 546c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwig 547c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t 548ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_device_type(struct device *dev, 549ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) 550c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 551ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_phy *phy = transport_class_to_phy(dev); 552c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 553c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!phy->identify.device_type) 554c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); 555c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_device_type_names(phy->identify.device_type, buf); 556c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 557ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL); 558c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 559ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t do_sas_phy_enable(struct device *dev, 560acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong size_t count, int enable) 561acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong{ 562ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_phy *phy = transport_class_to_phy(dev); 563acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 564acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong struct sas_internal *i = to_sas_internal(shost->transportt); 565acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong int error; 566acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 567acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong error = i->f->phy_enable(phy, enable); 568acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong if (error) 569acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong return error; 570acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong phy->enabled = enable; 571acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong return count; 572acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong}; 573acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 574ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t 575ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstore_sas_phy_enable(struct device *dev, struct device_attribute *attr, 576ee959b00c335d7780136c5abda37809191fe52c3Tony Jones const char *buf, size_t count) 577acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong{ 578acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong if (count < 1) 579acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong return -EINVAL; 580acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 581acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong switch (buf[0]) { 582acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong case '0': 583ee959b00c335d7780136c5abda37809191fe52c3Tony Jones do_sas_phy_enable(dev, count, 0); 584acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong break; 585acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong case '1': 586ee959b00c335d7780136c5abda37809191fe52c3Tony Jones do_sas_phy_enable(dev, count, 1); 587acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong break; 588acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong default: 589acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong return -EINVAL; 590acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong } 591acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 592acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong return count; 593acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong} 594acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 595ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t 596ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_phy_enable(struct device *dev, struct device_attribute *attr, 597ee959b00c335d7780136c5abda37809191fe52c3Tony Jones char *buf) 598acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong{ 599ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_phy *phy = transport_class_to_phy(dev); 600acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 601acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong return snprintf(buf, 20, "%d", phy->enabled); 602acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong} 603acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 604ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable, 605acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong store_sas_phy_enable); 606acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 607ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t 608ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesdo_sas_phy_reset(struct device *dev, size_t count, int hard_reset) 60907ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig{ 610ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_phy *phy = transport_class_to_phy(dev); 61107ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 61207ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); 61307ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig int error; 61407ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 61507ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig error = i->f->phy_reset(phy, hard_reset); 61607ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig if (error) 61707ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig return error; 61816d3db1b298529e6aec4a4cf0f56225d9e0bc641Dan Williams phy->enabled = 1; 61907ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig return count; 62007ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig}; 62107ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 622ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t 623ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstore_sas_link_reset(struct device *dev, struct device_attribute *attr, 624ee959b00c335d7780136c5abda37809191fe52c3Tony Jones const char *buf, size_t count) 62507ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig{ 626ee959b00c335d7780136c5abda37809191fe52c3Tony Jones return do_sas_phy_reset(dev, count, 0); 62707ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig} 628ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset); 62907ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 630ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t 631ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstore_sas_hard_reset(struct device *dev, struct device_attribute *attr, 632ee959b00c335d7780136c5abda37809191fe52c3Tony Jones const char *buf, size_t count) 63307ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig{ 634ee959b00c335d7780136c5abda37809191fe52c3Tony Jones return do_sas_phy_reset(dev, count, 1); 63507ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig} 636ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset); 63707ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 638c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_protocol_attr(identify.initiator_port_protocols, 639c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig initiator_port_protocols); 640c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_protocol_attr(identify.target_port_protocols, 641c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig target_port_protocols); 642c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", 643c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig unsigned long long); 644c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); 645c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", int); 646c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(negotiated_linkrate); 647c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(minimum_linkrate_hw); 648d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleysas_phy_linkspeed_rw_attr(minimum_linkrate); 649c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(maximum_linkrate_hw); 650d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleysas_phy_linkspeed_rw_attr(maximum_linkrate); 651c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(invalid_dword_count); 652c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(running_disparity_error_count); 653c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(loss_of_dword_sync_count); 654c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(phy_reset_problem_count); 655c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 6560b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williamsstatic int sas_phy_setup(struct transport_container *tc, struct device *dev, 6570b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams struct device *cdev) 6580b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams{ 6590b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams struct sas_phy *phy = dev_to_phy(dev); 6600b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 6610b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams struct sas_internal *i = to_sas_internal(shost->transportt); 6620b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams 6630b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams if (i->f->phy_setup) 6640b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams i->f->phy_setup(phy); 6650b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams 6660b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams return 0; 6670b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams} 668c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 669c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_phy_class, 6700b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams "sas_phy", sas_phy_setup, NULL, NULL); 671c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 672c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_phy_match(struct attribute_container *cont, struct device *dev) 673c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 674c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost; 675c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 676c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 677c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!scsi_is_sas_phy(dev)) 678c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 679c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost = dev_to_shost(dev->parent); 680c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 681c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!shost->transportt) 682c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 683c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (shost->transportt->host_attrs.ac.class != 684c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig &sas_host_class.class) 685c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 686c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 687c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = to_sas_internal(shost->transportt); 688c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->phy_attr_cont.ac == cont; 689c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 690c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 691c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic void sas_phy_release(struct device *dev) 692c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 693c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = dev_to_phy(dev); 6940b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 6950b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams struct sas_internal *i = to_sas_internal(shost->transportt); 696c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 6970b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams if (i->f->phy_release) 6980b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams i->f->phy_release(phy); 699c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(dev->parent); 700c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig kfree(phy); 701c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 702c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 703c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 704eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_phy_alloc - allocates and initialize a SAS PHY structure 705c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @parent: Parent device 706d99ca4180fe44ae7f409fc73f1a09f270b8d458aMoore, Eric * @number: Phy index 707c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 708c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Allocates an SAS PHY structure. It will be added in the device tree 709c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * below the device specified by @parent, which has to be either a Scsi_Host 710c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * or sas_rphy. 711c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 712c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 713c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS PHY allocated or %NULL if the allocation failed. 714c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 715c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct sas_phy *sas_phy_alloc(struct device *parent, int number) 716c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 717c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(parent); 718c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy; 719c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 72024669f75a3231fa37444977c92d1f4838bec1233Jes Sorensen phy = kzalloc(sizeof(*phy), GFP_KERNEL); 721c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!phy) 722c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return NULL; 723c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 724c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy->number = number; 725acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong phy->enabled = 1; 726c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 727c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig device_initialize(&phy->dev); 728c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy->dev.parent = get_device(parent); 729c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy->dev.release = sas_phy_release; 73065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley INIT_LIST_HEAD(&phy->port_siblings); 73179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (scsi_is_sas_expander_device(parent)) { 73279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent); 73371610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_set_name(&phy->dev, "phy-%d:%d:%d", shost->host_no, 73479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rphy->scsi_target_id, number); 73579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley } else 73671610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_set_name(&phy->dev, "phy-%d:%d", shost->host_no, number); 737c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 738c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_setup_device(&phy->dev); 739c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 740c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return phy; 741c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 742c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_alloc); 743c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 744c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 745eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_phy_add - add a SAS PHY to the device hierarchy 746c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy: The PHY to be added 747c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 748c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Publishes a SAS PHY to the rest of the system. 749c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 750c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint sas_phy_add(struct sas_phy *phy) 751c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 752c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 753c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 754c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = device_add(&phy->dev); 755c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!error) { 756c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_add_device(&phy->dev); 757c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_configure_device(&phy->dev); 758c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 759c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 760c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 761c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 762c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_add); 763c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 764c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 765eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_phy_free - free a SAS PHY 766c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy: SAS PHY to free 767c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 768c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Frees the specified SAS PHY. 769c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 770c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Note: 771c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * This function must only be called on a PHY that has not 772af901ca181d92aac3a7dc265144a9081a86d8f39André Goddard Rosa * successfully been added using sas_phy_add(). 773c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 774c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_phy_free(struct sas_phy *phy) 775c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 776c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_destroy_device(&phy->dev); 77792aab6464be735139f9ea38fd039c3b84c722630Mike Anderson put_device(&phy->dev); 778c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 779c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_free); 780c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 781c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 782eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_phy_delete - remove SAS PHY 783c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy: SAS PHY to remove 784c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 785c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Removes the specified SAS PHY. If the SAS PHY has an 786c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * associated remote PHY it is removed before. 787c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 788c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid 789c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_delete(struct sas_phy *phy) 790c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 791c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev = &phy->dev; 792c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 79365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* this happens if the phy is still part of a port when deleted */ 79465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley BUG_ON(!list_empty(&phy->port_siblings)); 795c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 796c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_remove_device(dev); 797c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig device_del(dev); 798c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_destroy_device(dev); 79992aab6464be735139f9ea38fd039c3b84c722630Mike Anderson put_device(dev); 800c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 801c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_delete); 802c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 803c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 804eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * scsi_is_sas_phy - check if a struct device represents a SAS PHY 805c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @dev: device to check 806c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 807c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 808c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * %1 if the device represents a SAS PHY, %0 else 809c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 810c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint scsi_is_sas_phy(const struct device *dev) 811c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 812c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return dev->release == sas_phy_release; 813c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 814c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(scsi_is_sas_phy); 815c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 816c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 81765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * SAS Port attributes 81865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 81965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define sas_port_show_simple(field, name, format_string, cast) \ 82065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic ssize_t \ 821ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_port_##name(struct device *dev, \ 822ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) \ 82365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ \ 824ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_port *port = transport_class_to_sas_port(dev); \ 82565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley \ 82665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return snprintf(buf, 20, format_string, cast port->field); \ 82765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 82865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 82965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define sas_port_simple_attr(field, name, format_string, type) \ 83065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_show_simple(field, name, format_string, (type)) \ 831ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL) 83265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 83365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleysas_port_simple_attr(num_phys, num_phys, "%d\n", int); 83465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 83565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_port_class, 83665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley "sas_port", NULL, NULL, NULL); 83765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 83865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic int sas_port_match(struct attribute_container *cont, struct device *dev) 83965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 84065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct Scsi_Host *shost; 84165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_internal *i; 84265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 84365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (!scsi_is_sas_port(dev)) 84465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return 0; 84565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley shost = dev_to_shost(dev->parent); 84665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 84765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (!shost->transportt) 84865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return 0; 84965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (shost->transportt->host_attrs.ac.class != 85065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley &sas_host_class.class) 85165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return 0; 85265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 85365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i = to_sas_internal(shost->transportt); 85465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return &i->port_attr_cont.ac == cont; 85565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 85665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 85765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 85865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic void sas_port_release(struct device *dev) 85965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 86065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *port = dev_to_sas_port(dev); 86165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 86265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley BUG_ON(!list_empty(&port->phy_list)); 86365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 86465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley put_device(dev->parent); 86565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley kfree(port); 86665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 86765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 86865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic void sas_port_create_link(struct sas_port *port, 86965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *phy) 87065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 87121434966462d57145c861b43f6206d945ac57630Darrick J. Wong int res; 87221434966462d57145c861b43f6206d945ac57630Darrick J. Wong 87321434966462d57145c861b43f6206d945ac57630Darrick J. Wong res = sysfs_create_link(&port->dev.kobj, &phy->dev.kobj, 87471610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_name(&phy->dev)); 87521434966462d57145c861b43f6206d945ac57630Darrick J. Wong if (res) 87621434966462d57145c861b43f6206d945ac57630Darrick J. Wong goto err; 87721434966462d57145c861b43f6206d945ac57630Darrick J. Wong res = sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port"); 87821434966462d57145c861b43f6206d945ac57630Darrick J. Wong if (res) 87921434966462d57145c861b43f6206d945ac57630Darrick J. Wong goto err; 88021434966462d57145c861b43f6206d945ac57630Darrick J. Wong return; 88121434966462d57145c861b43f6206d945ac57630Darrick J. Wongerr: 88221434966462d57145c861b43f6206d945ac57630Darrick J. Wong printk(KERN_ERR "%s: Cannot create port links, err=%d\n", 883cadbd4a5e36dde7e6c49b587b2c419103c0b7218Harvey Harrison __func__, res); 88465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 88565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 88665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic void sas_port_delete_link(struct sas_port *port, 88765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *phy) 88865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 88971610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers sysfs_remove_link(&port->dev.kobj, dev_name(&phy->dev)); 89065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sysfs_remove_link(&phy->dev.kobj, "port"); 89165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 89265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 89365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** sas_port_alloc - allocate and initialize a SAS port structure 89465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 89565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @parent: parent device 89665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port_id: port number 89765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 89865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Allocates a SAS port structure. It will be added to the device tree 89965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * below the device specified by @parent which must be either a Scsi_Host 90065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * or a sas_expander_device. 90165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 90265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Returns %NULL on error 90365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 90465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystruct sas_port *sas_port_alloc(struct device *parent, int port_id) 90565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 90665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct Scsi_Host *shost = dev_to_shost(parent); 90765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *port; 90865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 90965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port = kzalloc(sizeof(*port), GFP_KERNEL); 91065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (!port) 91165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return NULL; 91265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 91365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->port_identifier = port_id; 91465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 91565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley device_initialize(&port->dev); 91665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 91765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->dev.parent = get_device(parent); 91865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->dev.release = sas_port_release; 91965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 92065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_init(&port->phy_list_mutex); 92165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley INIT_LIST_HEAD(&port->phy_list); 92265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 92365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (scsi_is_sas_expander_device(parent)) { 92465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent); 92571610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_set_name(&port->dev, "port-%d:%d:%d", shost->host_no, 92671610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers rphy->scsi_target_id, port->port_identifier); 92765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } else 92871610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_set_name(&port->dev, "port-%d:%d", shost->host_no, 92971610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers port->port_identifier); 93065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 93165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_setup_device(&port->dev); 93265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 93365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return port; 93465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 93565c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_alloc); 93665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 937c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley/** sas_port_alloc_num - allocate and initialize a SAS port structure 938c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * 939c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * @parent: parent device 940c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * 941c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * Allocates a SAS port structure and a number to go with it. This 942c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * interface is really for adapters where the port number has no 943c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * meansing, so the sas class should manage them. It will be added to 944c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * the device tree below the device specified by @parent which must be 945c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * either a Scsi_Host or a sas_expander_device. 946c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * 947c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * Returns %NULL on error 948c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley */ 949c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomleystruct sas_port *sas_port_alloc_num(struct device *parent) 950c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley{ 951c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley int index; 952c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct Scsi_Host *shost = dev_to_shost(parent); 953c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 954c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley 955c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley /* FIXME: use idr for this eventually */ 956c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley mutex_lock(&sas_host->lock); 957c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley if (scsi_is_sas_expander_device(parent)) { 958c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent); 959c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct sas_expander_device *exp = rphy_to_expander_device(rphy); 960c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley 961c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley index = exp->next_port_id++; 962c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley } else 963c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley index = sas_host->next_port_id++; 964c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley mutex_unlock(&sas_host->lock); 965c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley return sas_port_alloc(parent, index); 966c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley} 967c9fefeb26457b87f4a767faefcf77321bb90db52James BottomleyEXPORT_SYMBOL(sas_port_alloc_num); 968c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley 96965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 97065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_add - add a SAS port to the device hierarchy 97165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: port to be added 97265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 97365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * publishes a port to the rest of the system 97465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 97565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyint sas_port_add(struct sas_port *port) 97665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 97765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley int error; 97865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 97965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* No phys should be added until this is made visible */ 98065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley BUG_ON(!list_empty(&port->phy_list)); 98165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 98265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley error = device_add(&port->dev); 98365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 98465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (error) 98565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return error; 98665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 98765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_add_device(&port->dev); 98865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_configure_device(&port->dev); 98965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 99065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return 0; 99165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 99265c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_add); 99365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 99465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 995eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_port_free - free a SAS PORT 99665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: SAS PORT to free 99765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 99865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Frees the specified SAS PORT. 99965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 100065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Note: 100165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * This function must only be called on a PORT that has not 1002af901ca181d92aac3a7dc265144a9081a86d8f39André Goddard Rosa * successfully been added using sas_port_add(). 100365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 100465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_free(struct sas_port *port) 100565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 100665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_destroy_device(&port->dev); 100765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley put_device(&port->dev); 100865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 100965c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_free); 101065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 101165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 1012eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_port_delete - remove SAS PORT 101365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: SAS PORT to remove 101465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 101565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Removes the specified SAS PORT. If the SAS PORT has an 101665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * associated phys, unlink them from the port as well. 101765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 101865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_delete(struct sas_port *port) 101965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 102065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct device *dev = &port->dev; 102165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *phy, *tmp_phy; 102265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 102365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (port->rphy) { 102465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_rphy_delete(port->rphy); 102565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->rphy = NULL; 102665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 102765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 102865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_lock(&port->phy_list_mutex); 102965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_for_each_entry_safe(phy, tmp_phy, &port->phy_list, 103065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port_siblings) { 103165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_delete_link(port, phy); 103265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_del_init(&phy->port_siblings); 103365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 103465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_unlock(&port->phy_list_mutex); 103565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 1036a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley if (port->is_backlink) { 1037a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley struct device *parent = port->dev.parent; 1038a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 103971610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers sysfs_remove_link(&port->dev.kobj, dev_name(parent)); 1040a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley port->is_backlink = 0; 1041a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley } 1042a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 104365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_remove_device(dev); 104465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley device_del(dev); 104565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_destroy_device(dev); 104665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley put_device(dev); 104765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 104865c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_delete); 104965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 105065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 1051eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * scsi_is_sas_port - check if a struct device represents a SAS port 105265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @dev: device to check 105365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 105465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Returns: 105565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * %1 if the device represents a SAS Port, %0 else 105665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 105765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyint scsi_is_sas_port(const struct device *dev) 105865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 105965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return dev->release == sas_port_release; 106065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 106165c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(scsi_is_sas_port); 106265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 106365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 1064f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams * sas_port_get_phy - try to take a reference on a port member 1065f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams * @port: port to check 1066f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams */ 1067f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williamsstruct sas_phy *sas_port_get_phy(struct sas_port *port) 1068f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams{ 1069f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams struct sas_phy *phy; 1070f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams 1071f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams mutex_lock(&port->phy_list_mutex); 1072f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams if (list_empty(&port->phy_list)) 1073f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams phy = NULL; 1074f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams else { 1075f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams struct list_head *ent = port->phy_list.next; 1076f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams 1077f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams phy = list_entry(ent, typeof(*phy), port_siblings); 1078f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams get_device(&phy->dev); 1079f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams } 1080f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams mutex_unlock(&port->phy_list_mutex); 1081f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams 1082f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams return phy; 1083f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams} 1084f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan WilliamsEXPORT_SYMBOL(sas_port_get_phy); 1085f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams 1086f41a0c441c3fe43e79ebeb75584dbb5bfa83e5cdDan Williams/** 108765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_add_phy - add another phy to a port to form a wide port 108865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: port to add the phy to 108965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @phy: phy to add 109065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 109165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * When a port is initially created, it is empty (has no phys). All 109265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * ports must have at least one phy to operated, and all wide ports 109365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * must have at least two. The current code makes no difference 109465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * between ports and wide ports, but the only object that can be 109565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * connected to a remote device is a port, so ports must be formed on 109665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * all devices with phys if they're connected to anything. 109765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 109865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_add_phy(struct sas_port *port, struct sas_phy *phy) 109965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 110065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_lock(&port->phy_list_mutex); 110165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (unlikely(!list_empty(&phy->port_siblings))) { 110265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* make sure we're already on this port */ 110365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *tmp; 110465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 110565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_for_each_entry(tmp, &port->phy_list, port_siblings) 110665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (tmp == phy) 110765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley break; 110865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* If this trips, you added a phy that was already 110965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * part of a different port */ 111065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (unlikely(tmp != phy)) { 111171610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_printk(KERN_ERR, &port->dev, "trying to add phy %s fails: it's already part of another port\n", 111271610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_name(&phy->dev)); 111365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley BUG(); 111465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 111565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } else { 111665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_create_link(port, phy); 111765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_add_tail(&phy->port_siblings, &port->phy_list); 111865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->num_phys++; 111965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 112065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_unlock(&port->phy_list_mutex); 112165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 112265c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_add_phy); 112365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 112465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 112565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_delete_phy - remove a phy from a port or wide port 112665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: port to remove the phy from 112765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @phy: phy to remove 112865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 112965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * This operation is used for tearing down ports again. It must be 113065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * done to every port or wide port before calling sas_port_delete. 113165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 113265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_delete_phy(struct sas_port *port, struct sas_phy *phy) 113365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 113465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_lock(&port->phy_list_mutex); 113565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_delete_link(port, phy); 113665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_del_init(&phy->port_siblings); 113765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->num_phys--; 113865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_unlock(&port->phy_list_mutex); 113965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 114065c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_delete_phy); 114165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 1142a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomleyvoid sas_port_mark_backlink(struct sas_port *port) 1143a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley{ 114421434966462d57145c861b43f6206d945ac57630Darrick J. Wong int res; 1145a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley struct device *parent = port->dev.parent->parent->parent; 1146a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 1147a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley if (port->is_backlink) 1148a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley return; 1149a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley port->is_backlink = 1; 115021434966462d57145c861b43f6206d945ac57630Darrick J. Wong res = sysfs_create_link(&port->dev.kobj, &parent->kobj, 115171610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_name(parent)); 115221434966462d57145c861b43f6206d945ac57630Darrick J. Wong if (res) 115321434966462d57145c861b43f6206d945ac57630Darrick J. Wong goto err; 115421434966462d57145c861b43f6206d945ac57630Darrick J. Wong return; 115521434966462d57145c861b43f6206d945ac57630Darrick J. Wongerr: 115621434966462d57145c861b43f6206d945ac57630Darrick J. Wong printk(KERN_ERR "%s: Cannot create port backlink, err=%d\n", 1157cadbd4a5e36dde7e6c49b587b2c419103c0b7218Harvey Harrison __func__, res); 1158a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 1159a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley} 1160a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames BottomleyEXPORT_SYMBOL(sas_port_mark_backlink); 1161a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 116265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/* 1163c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS remote PHY attributes. 1164c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1165c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1166c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_show_simple(field, name, format_string, cast) \ 1167c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 1168ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_rphy_##name(struct device *dev, \ 1169ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) \ 1170c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 1171ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_rphy *rphy = transport_class_to_rphy(dev); \ 1172c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 1173c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, format_string, cast rphy->field); \ 1174c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1175c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1176c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_simple_attr(field, name, format_string, type) \ 1177c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_rphy_show_simple(field, name, format_string, (type)) \ 1178ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(rphy, name, S_IRUGO, \ 1179c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_##name, NULL) 1180c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1181c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_show_protocol(field, name) \ 1182c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 1183ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_rphy_##name(struct device *dev, \ 1184ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) \ 1185c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 1186ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_rphy *rphy = transport_class_to_rphy(dev); \ 1187c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 1188c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!rphy->field) \ 1189c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); \ 1190c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_protocol_names(rphy->field, buf); \ 1191c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1192c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1193c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_protocol_attr(field, name) \ 1194c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_rphy_show_protocol(field, name) \ 1195ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(rphy, name, S_IRUGO, \ 1196c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_##name, NULL) 1197c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1198c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t 1199ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_rphy_device_type(struct device *dev, 1200ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) 1201c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1202ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_rphy *rphy = transport_class_to_rphy(dev); 1203c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1204c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!rphy->identify.device_type) 1205c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); 1206c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_device_type_names( 1207c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->identify.device_type, buf); 1208c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1209c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1210ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(rphy, device_type, S_IRUGO, 1211c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_device_type, NULL); 1212c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1213a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic ssize_t 1214ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_rphy_enclosure_identifier(struct device *dev, 1215ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) 1216a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig{ 1217ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_rphy *rphy = transport_class_to_rphy(dev); 1218a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_phy *phy = dev_to_phy(rphy->dev.parent); 1219a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 1220a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); 1221a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig u64 identifier; 1222a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig int error; 1223a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 1224a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig /* 1225a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig * Only devices behind an expander are supported, because the 1226a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig * enclosure identifier is a SMP feature. 1227a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig */ 1228f4ad7b5807385ad1fed0347d966e51a797cd1013James Bottomley if (scsi_is_sas_phy_local(phy)) 1229a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return -EINVAL; 1230a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 1231a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig error = i->f->get_enclosure_identifier(rphy, &identifier); 1232a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig if (error) 1233a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return error; 1234a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return sprintf(buf, "0x%llx\n", (unsigned long long)identifier); 1235a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig} 1236a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 1237ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO, 1238a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig show_sas_rphy_enclosure_identifier, NULL); 1239a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 1240a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic ssize_t 1241ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_rphy_bay_identifier(struct device *dev, 1242ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) 1243a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig{ 1244ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_rphy *rphy = transport_class_to_rphy(dev); 1245a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_phy *phy = dev_to_phy(rphy->dev.parent); 1246a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 1247a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); 1248a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig int val; 1249a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 1250f4ad7b5807385ad1fed0347d966e51a797cd1013James Bottomley if (scsi_is_sas_phy_local(phy)) 1251a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return -EINVAL; 1252a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 1253a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig val = i->f->get_bay_identifier(rphy); 1254a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig if (val < 0) 1255a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return val; 1256a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return sprintf(buf, "%d\n", val); 1257a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig} 1258a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 1259ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO, 1260a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig show_sas_rphy_bay_identifier, NULL); 1261a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 1262c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_protocol_attr(identify.initiator_port_protocols, 1263c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig initiator_port_protocols); 1264c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols); 1265c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", 1266c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig unsigned long long); 1267c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); 1268c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 126942ab03609cca4ef5079e248296f015650c626899James Bottomley/* only need 8 bytes of data plus header (4 or 8) */ 127042ab03609cca4ef5079e248296f015650c626899James Bottomley#define BUF_SIZE 64 127142ab03609cca4ef5079e248296f015650c626899James Bottomley 127242ab03609cca4ef5079e248296f015650c626899James Bottomleyint sas_read_port_mode_page(struct scsi_device *sdev) 127342ab03609cca4ef5079e248296f015650c626899James Bottomley{ 127442ab03609cca4ef5079e248296f015650c626899James Bottomley char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata; 12750f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley struct sas_end_device *rdev = sas_sdev_to_rdev(sdev); 127642ab03609cca4ef5079e248296f015650c626899James Bottomley struct scsi_mode_data mode_data; 127742ab03609cca4ef5079e248296f015650c626899James Bottomley int res, error; 127842ab03609cca4ef5079e248296f015650c626899James Bottomley 127942ab03609cca4ef5079e248296f015650c626899James Bottomley if (!buffer) 128042ab03609cca4ef5079e248296f015650c626899James Bottomley return -ENOMEM; 128142ab03609cca4ef5079e248296f015650c626899James Bottomley 128242ab03609cca4ef5079e248296f015650c626899James Bottomley res = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3, 128342ab03609cca4ef5079e248296f015650c626899James Bottomley &mode_data, NULL); 128442ab03609cca4ef5079e248296f015650c626899James Bottomley 128542ab03609cca4ef5079e248296f015650c626899James Bottomley error = -EINVAL; 128642ab03609cca4ef5079e248296f015650c626899James Bottomley if (!scsi_status_is_good(res)) 128742ab03609cca4ef5079e248296f015650c626899James Bottomley goto out; 128842ab03609cca4ef5079e248296f015650c626899James Bottomley 128942ab03609cca4ef5079e248296f015650c626899James Bottomley msdata = buffer + mode_data.header_length + 129042ab03609cca4ef5079e248296f015650c626899James Bottomley mode_data.block_descriptor_length; 129142ab03609cca4ef5079e248296f015650c626899James Bottomley 129242ab03609cca4ef5079e248296f015650c626899James Bottomley if (msdata - buffer > BUF_SIZE - 8) 129342ab03609cca4ef5079e248296f015650c626899James Bottomley goto out; 129442ab03609cca4ef5079e248296f015650c626899James Bottomley 129542ab03609cca4ef5079e248296f015650c626899James Bottomley error = 0; 129642ab03609cca4ef5079e248296f015650c626899James Bottomley 129742ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->ready_led_meaning = msdata[2] & 0x10 ? 1 : 0; 129842ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->I_T_nexus_loss_timeout = (msdata[4] << 8) + msdata[5]; 129942ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->initiator_response_timeout = (msdata[6] << 8) + msdata[7]; 130042ab03609cca4ef5079e248296f015650c626899James Bottomley 130142ab03609cca4ef5079e248296f015650c626899James Bottomley out: 130242ab03609cca4ef5079e248296f015650c626899James Bottomley kfree(buffer); 130342ab03609cca4ef5079e248296f015650c626899James Bottomley return error; 130442ab03609cca4ef5079e248296f015650c626899James Bottomley} 130542ab03609cca4ef5079e248296f015650c626899James BottomleyEXPORT_SYMBOL(sas_read_port_mode_page); 130642ab03609cca4ef5079e248296f015650c626899James Bottomley 130779cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_end_dev_class, 130879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley "sas_end_device", NULL, NULL, NULL); 130979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 131042ab03609cca4ef5079e248296f015650c626899James Bottomley#define sas_end_dev_show_simple(field, name, format_string, cast) \ 131142ab03609cca4ef5079e248296f015650c626899James Bottomleystatic ssize_t \ 1312ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_end_dev_##name(struct device *dev, \ 1313ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) \ 131442ab03609cca4ef5079e248296f015650c626899James Bottomley{ \ 1315ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_rphy *rphy = transport_class_to_rphy(dev); \ 131642ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_end_device *rdev = rphy_to_end_device(rphy); \ 131742ab03609cca4ef5079e248296f015650c626899James Bottomley \ 131842ab03609cca4ef5079e248296f015650c626899James Bottomley return snprintf(buf, 20, format_string, cast rdev->field); \ 131942ab03609cca4ef5079e248296f015650c626899James Bottomley} 132042ab03609cca4ef5079e248296f015650c626899James Bottomley 132142ab03609cca4ef5079e248296f015650c626899James Bottomley#define sas_end_dev_simple_attr(field, name, format_string, type) \ 132242ab03609cca4ef5079e248296f015650c626899James Bottomley sas_end_dev_show_simple(field, name, format_string, (type)) \ 1323ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(end_dev, name, S_IRUGO, \ 132442ab03609cca4ef5079e248296f015650c626899James Bottomley show_sas_end_dev_##name, NULL) 132542ab03609cca4ef5079e248296f015650c626899James Bottomley 132642ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(ready_led_meaning, ready_led_meaning, "%d\n", int); 132742ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(I_T_nexus_loss_timeout, I_T_nexus_loss_timeout, 132842ab03609cca4ef5079e248296f015650c626899James Bottomley "%d\n", int); 132942ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout, 133042ab03609cca4ef5079e248296f015650c626899James Bottomley "%d\n", int); 13310f88009d5cfae890bd3466126d1622ad4f16b798James Bottomleysas_end_dev_simple_attr(tlr_supported, tlr_supported, 13320f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley "%d\n", int); 13330f88009d5cfae890bd3466126d1622ad4f16b798James Bottomleysas_end_dev_simple_attr(tlr_enabled, tlr_enabled, 13340f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley "%d\n", int); 133542ab03609cca4ef5079e248296f015650c626899James Bottomley 133679cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_expander_class, 133779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley "sas_expander", NULL, NULL, NULL); 133879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 133979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define sas_expander_show_simple(field, name, format_string, cast) \ 134079cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic ssize_t \ 1341ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_expander_##name(struct device *dev, \ 1342ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) \ 134379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{ \ 1344ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_rphy *rphy = transport_class_to_rphy(dev); \ 134579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_expander_device *edev = rphy_to_expander_device(rphy); \ 134679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley \ 134779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return snprintf(buf, 20, format_string, cast edev->field); \ 134879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley} 134979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 135079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define sas_expander_simple_attr(field, name, format_string, type) \ 135179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley sas_expander_show_simple(field, name, format_string, (type)) \ 1352ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(expander, name, S_IRUGO, \ 135379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley show_sas_expander_##name, NULL) 135479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 135579cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(vendor_id, vendor_id, "%s\n", char *); 135679cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(product_id, product_id, "%s\n", char *); 135779cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(product_rev, product_rev, "%s\n", char *); 135879cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_vendor_id, component_vendor_id, 135979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley "%s\n", char *); 136079cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_id, component_id, "%u\n", unsigned int); 136179cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_revision_id, component_revision_id, "%u\n", 136279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley unsigned int); 136379cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(level, level, "%d\n", int); 136442ab03609cca4ef5079e248296f015650c626899James Bottomley 1365c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_rphy_class, 13662f8600dff2b140096a7df781884e918a16aa90e0James Bottomley "sas_device", NULL, NULL, NULL); 1367c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1368c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_rphy_match(struct attribute_container *cont, struct device *dev) 1369c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1370c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost; 1371c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 1372c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1373c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!scsi_is_sas_rphy(dev)) 1374c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1375c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost = dev_to_shost(dev->parent->parent); 1376c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1377c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!shost->transportt) 1378c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1379c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (shost->transportt->host_attrs.ac.class != 1380c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig &sas_host_class.class) 1381c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1382c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1383c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = to_sas_internal(shost->transportt); 1384c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->rphy_attr_cont.ac == cont; 1385c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1386c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 138742ab03609cca4ef5079e248296f015650c626899James Bottomleystatic int sas_end_dev_match(struct attribute_container *cont, 138842ab03609cca4ef5079e248296f015650c626899James Bottomley struct device *dev) 138942ab03609cca4ef5079e248296f015650c626899James Bottomley{ 139042ab03609cca4ef5079e248296f015650c626899James Bottomley struct Scsi_Host *shost; 139142ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_internal *i; 139242ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_rphy *rphy; 139342ab03609cca4ef5079e248296f015650c626899James Bottomley 139442ab03609cca4ef5079e248296f015650c626899James Bottomley if (!scsi_is_sas_rphy(dev)) 139542ab03609cca4ef5079e248296f015650c626899James Bottomley return 0; 139642ab03609cca4ef5079e248296f015650c626899James Bottomley shost = dev_to_shost(dev->parent->parent); 139742ab03609cca4ef5079e248296f015650c626899James Bottomley rphy = dev_to_rphy(dev); 139842ab03609cca4ef5079e248296f015650c626899James Bottomley 139942ab03609cca4ef5079e248296f015650c626899James Bottomley if (!shost->transportt) 140042ab03609cca4ef5079e248296f015650c626899James Bottomley return 0; 140142ab03609cca4ef5079e248296f015650c626899James Bottomley if (shost->transportt->host_attrs.ac.class != 140242ab03609cca4ef5079e248296f015650c626899James Bottomley &sas_host_class.class) 140342ab03609cca4ef5079e248296f015650c626899James Bottomley return 0; 140442ab03609cca4ef5079e248296f015650c626899James Bottomley 140542ab03609cca4ef5079e248296f015650c626899James Bottomley i = to_sas_internal(shost->transportt); 140642ab03609cca4ef5079e248296f015650c626899James Bottomley return &i->end_dev_attr_cont.ac == cont && 14072f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rphy->identify.device_type == SAS_END_DEVICE; 140842ab03609cca4ef5079e248296f015650c626899James Bottomley} 140942ab03609cca4ef5079e248296f015650c626899James Bottomley 141079cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic int sas_expander_match(struct attribute_container *cont, 141179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct device *dev) 141279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{ 141379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct Scsi_Host *shost; 141479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_internal *i; 141579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_rphy *rphy; 141679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 141779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (!scsi_is_sas_rphy(dev)) 141879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return 0; 141979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley shost = dev_to_shost(dev->parent->parent); 142079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rphy = dev_to_rphy(dev); 142179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 142279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (!shost->transportt) 142379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return 0; 142479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (shost->transportt->host_attrs.ac.class != 142579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley &sas_host_class.class) 142679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return 0; 142779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 142879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i = to_sas_internal(shost->transportt); 142979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return &i->expander_attr_cont.ac == cont && 143079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE || 14312f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE); 143279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley} 143379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 14342f8600dff2b140096a7df781884e918a16aa90e0James Bottomleystatic void sas_expander_release(struct device *dev) 1435c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1436c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = dev_to_rphy(dev); 14372f8600dff2b140096a7df781884e918a16aa90e0James Bottomley struct sas_expander_device *edev = rphy_to_expander_device(rphy); 1438c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 143993c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori if (rphy->q) 144093c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori blk_cleanup_queue(rphy->q); 144193c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori 1442c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(dev->parent); 14432f8600dff2b140096a7df781884e918a16aa90e0James Bottomley kfree(edev); 1444c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1445c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 14462f8600dff2b140096a7df781884e918a16aa90e0James Bottomleystatic void sas_end_device_release(struct device *dev) 1447c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 14482f8600dff2b140096a7df781884e918a16aa90e0James Bottomley struct sas_rphy *rphy = dev_to_rphy(dev); 14492f8600dff2b140096a7df781884e918a16aa90e0James Bottomley struct sas_end_device *edev = rphy_to_end_device(rphy); 1450c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 145193c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori if (rphy->q) 145293c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori blk_cleanup_queue(rphy->q); 145393c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori 14542f8600dff2b140096a7df781884e918a16aa90e0James Bottomley put_device(dev->parent); 14552f8600dff2b140096a7df781884e918a16aa90e0James Bottomley kfree(edev); 1456c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1457c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1458c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1459c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * sas_rphy_initialize - common rphy intialization 1460c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * @rphy: rphy to initialise 1461c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * 1462c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * Used by both sas_end_device_alloc() and sas_expander_alloc() to 1463c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * initialise the common rphy component of each. 1464c5943d36aebb79589ac3983eec418bbeca897573James Bottomley */ 1465c5943d36aebb79589ac3983eec418bbeca897573James Bottomleystatic void sas_rphy_initialize(struct sas_rphy *rphy) 1466c5943d36aebb79589ac3983eec418bbeca897573James Bottomley{ 1467c5943d36aebb79589ac3983eec418bbeca897573James Bottomley INIT_LIST_HEAD(&rphy->list); 1468c5943d36aebb79589ac3983eec418bbeca897573James Bottomley} 1469c5943d36aebb79589ac3983eec418bbeca897573James Bottomley 1470c5943d36aebb79589ac3983eec418bbeca897573James Bottomley/** 147142ab03609cca4ef5079e248296f015650c626899James Bottomley * sas_end_device_alloc - allocate an rphy for an end device 1472eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @parent: which port 147342ab03609cca4ef5079e248296f015650c626899James Bottomley * 147442ab03609cca4ef5079e248296f015650c626899James Bottomley * Allocates an SAS remote PHY structure, connected to @parent. 147542ab03609cca4ef5079e248296f015650c626899James Bottomley * 147642ab03609cca4ef5079e248296f015650c626899James Bottomley * Returns: 147742ab03609cca4ef5079e248296f015650c626899James Bottomley * SAS PHY allocated or %NULL if the allocation failed. 147842ab03609cca4ef5079e248296f015650c626899James Bottomley */ 147965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystruct sas_rphy *sas_end_device_alloc(struct sas_port *parent) 148042ab03609cca4ef5079e248296f015650c626899James Bottomley{ 148142ab03609cca4ef5079e248296f015650c626899James Bottomley struct Scsi_Host *shost = dev_to_shost(&parent->dev); 148242ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_end_device *rdev; 148342ab03609cca4ef5079e248296f015650c626899James Bottomley 148442ab03609cca4ef5079e248296f015650c626899James Bottomley rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 148542ab03609cca4ef5079e248296f015650c626899James Bottomley if (!rdev) { 148642ab03609cca4ef5079e248296f015650c626899James Bottomley return NULL; 148742ab03609cca4ef5079e248296f015650c626899James Bottomley } 148842ab03609cca4ef5079e248296f015650c626899James Bottomley 148942ab03609cca4ef5079e248296f015650c626899James Bottomley device_initialize(&rdev->rphy.dev); 149042ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->rphy.dev.parent = get_device(&parent->dev); 14912f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rdev->rphy.dev.release = sas_end_device_release; 149265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (scsi_is_sas_expander_device(parent->dev.parent)) { 149365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent->dev.parent); 149471610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_set_name(&rdev->rphy.dev, "end_device-%d:%d:%d", 149571610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers shost->host_no, rphy->scsi_target_id, 149671610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers parent->port_identifier); 149765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } else 149871610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_set_name(&rdev->rphy.dev, "end_device-%d:%d", 149971610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers shost->host_no, parent->port_identifier); 150042ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->rphy.identify.device_type = SAS_END_DEVICE; 1501c5943d36aebb79589ac3983eec418bbeca897573James Bottomley sas_rphy_initialize(&rdev->rphy); 150242ab03609cca4ef5079e248296f015650c626899James Bottomley transport_setup_device(&rdev->rphy.dev); 150342ab03609cca4ef5079e248296f015650c626899James Bottomley 150442ab03609cca4ef5079e248296f015650c626899James Bottomley return &rdev->rphy; 150542ab03609cca4ef5079e248296f015650c626899James Bottomley} 150642ab03609cca4ef5079e248296f015650c626899James BottomleyEXPORT_SYMBOL(sas_end_device_alloc); 150742ab03609cca4ef5079e248296f015650c626899James Bottomley 150879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley/** 150979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * sas_expander_alloc - allocate an rphy for an end device 1510eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @parent: which port 1511eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @type: SAS_EDGE_EXPANDER_DEVICE or SAS_FANOUT_EXPANDER_DEVICE 151279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * 151379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * Allocates an SAS remote PHY structure, connected to @parent. 151479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * 151579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * Returns: 151679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * SAS PHY allocated or %NULL if the allocation failed. 151779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley */ 151865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystruct sas_rphy *sas_expander_alloc(struct sas_port *parent, 151979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley enum sas_device_type type) 152079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{ 152179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct Scsi_Host *shost = dev_to_shost(&parent->dev); 152279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_expander_device *rdev; 152379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 152479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 152579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley BUG_ON(type != SAS_EDGE_EXPANDER_DEVICE && 152679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley type != SAS_FANOUT_EXPANDER_DEVICE); 152779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 152879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 152979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (!rdev) { 153079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return NULL; 153179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley } 153279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 153379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley device_initialize(&rdev->rphy.dev); 153479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev->rphy.dev.parent = get_device(&parent->dev); 15352f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rdev->rphy.dev.release = sas_expander_release; 153679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley mutex_lock(&sas_host->lock); 153779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev->rphy.scsi_target_id = sas_host->next_expander_id++; 153879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley mutex_unlock(&sas_host->lock); 153971610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_set_name(&rdev->rphy.dev, "expander-%d:%d", 154071610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers shost->host_no, rdev->rphy.scsi_target_id); 154179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev->rphy.identify.device_type = type; 1542c5943d36aebb79589ac3983eec418bbeca897573James Bottomley sas_rphy_initialize(&rdev->rphy); 154379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_setup_device(&rdev->rphy.dev); 154479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 154579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return &rdev->rphy; 154679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley} 154779cb1819e231f811211133a09a5382cb89d7ec67James BottomleyEXPORT_SYMBOL(sas_expander_alloc); 154842ab03609cca4ef5079e248296f015650c626899James Bottomley 154942ab03609cca4ef5079e248296f015650c626899James Bottomley/** 1550eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_rphy_add - add a SAS remote PHY to the device hierarchy 1551c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @rphy: The remote PHY to be added 1552c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1553c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Publishes a SAS remote PHY to the rest of the system. 1554c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1555c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint sas_rphy_add(struct sas_rphy *rphy) 1556c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 155765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *parent = dev_to_sas_port(rphy->dev.parent); 1558c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); 1559c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1560c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_identify *identify = &rphy->identify; 1561c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 1562c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1563c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (parent->rphy) 1564c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return -ENXIO; 1565c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig parent->rphy = rphy; 1566c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1567c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = device_add(&rphy->dev); 1568c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1569c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 1570c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_add_device(&rphy->dev); 1571c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_configure_device(&rphy->dev); 157239dca558a5b52b63e49bc234a7e887be092aa690James Bottomley if (sas_bsg_initialize(shost, rphy)) 157371610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers printk("fail to a bsg device %s\n", dev_name(&rphy->dev)); 157439dca558a5b52b63e49bc234a7e887be092aa690James Bottomley 1575c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1576e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 1577c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_add_tail(&rphy->list, &sas_host->rphy_list); 1578c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (identify->device_type == SAS_END_DEVICE && 1579c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig (identify->target_port_protocols & 1580c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA))) 1581c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->scsi_target_id = sas_host->next_target_id++; 15827676f83aeb774e7a3abe6af06ec92b29488b5b79James Bottomley else if (identify->device_type == SAS_END_DEVICE) 15837676f83aeb774e7a3abe6af06ec92b29488b5b79James Bottomley rphy->scsi_target_id = -1; 1584e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 1585c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 158679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (identify->device_type == SAS_END_DEVICE && 158779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rphy->scsi_target_id != -1) { 15882fc62e2ac350b8f574e0a09170b350a8f2fa4a02Dan Williams int lun; 15892fc62e2ac350b8f574e0a09170b350a8f2fa4a02Dan Williams 15902fc62e2ac350b8f574e0a09170b350a8f2fa4a02Dan Williams if (identify->target_port_protocols & SAS_PROTOCOL_SSP) 15912fc62e2ac350b8f574e0a09170b350a8f2fa4a02Dan Williams lun = SCAN_WILD_CARD; 15922fc62e2ac350b8f574e0a09170b350a8f2fa4a02Dan Williams else 15932fc62e2ac350b8f574e0a09170b350a8f2fa4a02Dan Williams lun = 0; 15942fc62e2ac350b8f574e0a09170b350a8f2fa4a02Dan Williams 15952fc62e2ac350b8f574e0a09170b350a8f2fa4a02Dan Williams scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id, lun, 0); 1596c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 1597c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1598c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1599c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1600c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_add); 1601c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1602c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1603eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_rphy_free - free a SAS remote PHY 1604eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @rphy: SAS remote PHY to free 1605c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1606c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Frees the specified SAS remote PHY. 1607c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1608c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Note: 1609c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * This function must only be called on a remote 1610af901ca181d92aac3a7dc265144a9081a86d8f39André Goddard Rosa * PHY that has not successfully been added using 16116f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * sas_rphy_add() (or has been sas_rphy_remove()'d) 1612c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1613c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_rphy_free(struct sas_rphy *rphy) 1614c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 161592aab6464be735139f9ea38fd039c3b84c722630Mike Anderson struct device *dev = &rphy->dev; 1616c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); 1617c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1618c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1619e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 1620c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_del(&rphy->list); 1621e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 1622c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1623b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley sas_bsg_remove(shost, rphy); 1624b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley 162592aab6464be735139f9ea38fd039c3b84c722630Mike Anderson transport_destroy_device(dev); 16262f8600dff2b140096a7df781884e918a16aa90e0James Bottomley 162792aab6464be735139f9ea38fd039c3b84c722630Mike Anderson put_device(dev); 1628c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1629c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_free); 1630c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1631c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1632eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_rphy_delete - remove and free SAS remote PHY 16336f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * @rphy: SAS remote PHY to remove and free 1634c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 16356f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * Removes the specified SAS remote PHY and frees it. 1636c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1637c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid 1638c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_delete(struct sas_rphy *rphy) 1639c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 16406f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong sas_rphy_remove(rphy); 16416f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong sas_rphy_free(rphy); 16426f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong} 16436f63caae2172e97e528b58319480217b0b36542eDarrick J. WongEXPORT_SYMBOL(sas_rphy_delete); 16446f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong 16456f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong/** 164687c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams * sas_rphy_unlink - unlink SAS remote PHY 164787c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams * @rphy: SAS remote phy to unlink from its parent port 164887c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams * 164987c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams * Removes port reference to an rphy 165087c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams */ 165187c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williamsvoid sas_rphy_unlink(struct sas_rphy *rphy) 165287c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams{ 165387c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams struct sas_port *parent = dev_to_sas_port(rphy->dev.parent); 165487c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams 165587c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams parent->rphy = NULL; 165687c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams} 165787c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan WilliamsEXPORT_SYMBOL(sas_rphy_unlink); 165887c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams 165987c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams/** 1660eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_rphy_remove - remove SAS remote PHY 16616f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * @rphy: SAS remote phy to remove 16626f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * 16636f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * Removes the specified SAS remote PHY. 16646f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong */ 16656f63caae2172e97e528b58319480217b0b36542eDarrick J. Wongvoid 16666f63caae2172e97e528b58319480217b0b36542eDarrick J. Wongsas_rphy_remove(struct sas_rphy *rphy) 16676f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong{ 1668c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev = &rphy->dev; 1669c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1670d4054239929479907f20b9d68c905589125ad343Christoph Hellwig switch (rphy->identify.device_type) { 1671d4054239929479907f20b9d68c905589125ad343Christoph Hellwig case SAS_END_DEVICE: 1672d4054239929479907f20b9d68c905589125ad343Christoph Hellwig scsi_remove_target(dev); 1673d4054239929479907f20b9d68c905589125ad343Christoph Hellwig break; 1674d4054239929479907f20b9d68c905589125ad343Christoph Hellwig case SAS_EDGE_EXPANDER_DEVICE: 1675d4054239929479907f20b9d68c905589125ad343Christoph Hellwig case SAS_FANOUT_EXPANDER_DEVICE: 167665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_remove_children(dev); 1677d4054239929479907f20b9d68c905589125ad343Christoph Hellwig break; 1678d4054239929479907f20b9d68c905589125ad343Christoph Hellwig default: 1679d4054239929479907f20b9d68c905589125ad343Christoph Hellwig break; 1680d4054239929479907f20b9d68c905589125ad343Christoph Hellwig } 1681c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 168287c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams sas_rphy_unlink(rphy); 1683fe8b2304e54552cea113318e2f66c45628130fdcChristoph Hellwig transport_remove_device(dev); 1684fe8b2304e54552cea113318e2f66c45628130fdcChristoph Hellwig device_del(dev); 1685c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 16866f63caae2172e97e528b58319480217b0b36542eDarrick J. WongEXPORT_SYMBOL(sas_rphy_remove); 1687c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1688c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1689eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * scsi_is_sas_rphy - check if a struct device represents a SAS remote PHY 1690c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @dev: device to check 1691c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1692c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 1693c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * %1 if the device represents a SAS remote PHY, %0 else 1694c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1695c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint scsi_is_sas_rphy(const struct device *dev) 1696c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 16972f8600dff2b140096a7df781884e918a16aa90e0James Bottomley return dev->release == sas_end_device_release || 16982f8600dff2b140096a7df781884e918a16aa90e0James Bottomley dev->release == sas_expander_release; 1699c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1700c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(scsi_is_sas_rphy); 1701c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1702c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1703c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 1704c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SCSI scan helper 1705c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1706c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1707e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwigstatic int sas_user_scan(struct Scsi_Host *shost, uint channel, 1708e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig uint id, uint lun) 1709c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1710c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1711c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy; 1712c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1713e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 1714c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_for_each_entry(rphy, &sas_host->rphy_list, list) { 17156d99a3f372181160a56d7b1ee3259dbe03663f0dJames Bottomley if (rphy->identify.device_type != SAS_END_DEVICE || 17166d99a3f372181160a56d7b1ee3259dbe03663f0dJames Bottomley rphy->scsi_target_id == -1) 1717e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig continue; 1718e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig 1719e8bf39417b578a11e2ee2cd16e794a5b2d40757bJames Bottomley if ((channel == SCAN_WILD_CARD || channel == 0) && 1720e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) { 1721e8bf39417b578a11e2ee2cd16e794a5b2d40757bJames Bottomley scsi_scan_target(&rphy->dev, 0, 1722e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig rphy->scsi_target_id, lun, 1); 1723e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig } 1724c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 1725e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 1726c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1727e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig return 0; 1728c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1729c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1730c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1731c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 1732c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Setup / Teardown code 1733c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1734c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1735d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define SETUP_TEMPLATE(attrb, field, perm, test) \ 1736ee959b00c335d7780136c5abda37809191fe52c3Tony Jones i->private_##attrb[count] = dev_attr_##field; \ 173742ab03609cca4ef5079e248296f015650c626899James Bottomley i->private_##attrb[count].attr.mode = perm; \ 173842ab03609cca4ef5079e248296f015650c626899James Bottomley i->attrb[count] = &i->private_##attrb[count]; \ 173942ab03609cca4ef5079e248296f015650c626899James Bottomley if (test) \ 174042ab03609cca4ef5079e248296f015650c626899James Bottomley count++ 174142ab03609cca4ef5079e248296f015650c626899James Bottomley 1742d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define SETUP_TEMPLATE_RW(attrb, field, perm, test, ro_test, ro_perm) \ 1743ee959b00c335d7780136c5abda37809191fe52c3Tony Jones i->private_##attrb[count] = dev_attr_##field; \ 1744d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley i->private_##attrb[count].attr.mode = perm; \ 1745d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley if (ro_test) { \ 1746d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley i->private_##attrb[count].attr.mode = ro_perm; \ 1747d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley i->private_##attrb[count].store = NULL; \ 1748d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley } \ 1749d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley i->attrb[count] = &i->private_##attrb[count]; \ 1750d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley if (test) \ 1751d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley count++ 175242ab03609cca4ef5079e248296f015650c626899James Bottomley 175342ab03609cca4ef5079e248296f015650c626899James Bottomley#define SETUP_RPORT_ATTRIBUTE(field) \ 175442ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, 1) 1755c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1756dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley#define SETUP_OPTIONAL_RPORT_ATTRIBUTE(field, func) \ 175742ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, i->f->func) 1758dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley 175965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_PHY_ATTRIBUTE(field) \ 176042ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1) 1761c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1762d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define SETUP_PHY_ATTRIBUTE_RW(field) \ 1763d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1, \ 1764d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley !i->f->set_phy_speed, S_IRUGO) 1765d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley 1766acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong#define SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(field, func) \ 1767acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1, \ 1768acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong !i->f->func, S_IRUGO) 1769acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 177065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_PORT_ATTRIBUTE(field) \ 177165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1) 177265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 177365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_OPTIONAL_PHY_ATTRIBUTE(field, func) \ 177442ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func) 1775dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley 177665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_PHY_ATTRIBUTE_WRONLY(field) \ 1777fe3b5bfe73ace420709f0cfb198b0ffc704bd38bDarrick J. Wong SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, 1) 177807ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 177965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(field, func) \ 1780fe3b5bfe73ace420709f0cfb198b0ffc704bd38bDarrick J. Wong SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, i->f->func) 1781dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley 178242ab03609cca4ef5079e248296f015650c626899James Bottomley#define SETUP_END_DEV_ATTRIBUTE(field) \ 178342ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1) 1784c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 178579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define SETUP_EXPANDER_ATTRIBUTE(field) \ 178679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_TEMPLATE(expander_attrs, expander_##field, S_IRUGO, 1) 178779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 1788c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1789eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_attach_transport - instantiate SAS transport template 1790c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @ft: SAS transport class function template 1791c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1792c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct scsi_transport_template * 1793c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_attach_transport(struct sas_function_template *ft) 1794c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1795c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 1796c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int count; 1797c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 179824669f75a3231fa37444977c92d1f4838bec1233Jes Sorensen i = kzalloc(sizeof(struct sas_internal), GFP_KERNEL); 1799c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!i) 1800c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return NULL; 1801c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1802e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig i->t.user_scan = sas_user_scan; 1803c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1804c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.attrs = &i->host_attrs[0]; 1805c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.class = &sas_host_class.class; 1806c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.match = sas_host_match; 1807c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->t.host_attrs); 1808c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_size = sizeof(struct sas_host_attrs); 1809c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1810c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.class = &sas_phy_class.class; 1811c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.attrs = &i->phy_attrs[0]; 1812c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.match = sas_phy_match; 1813c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->phy_attr_cont); 1814c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 181565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attr_cont.ac.class = &sas_port_class.class; 181665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attr_cont.ac.attrs = &i->port_attrs[0]; 181765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attr_cont.ac.match = sas_port_match; 181865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_container_register(&i->port_attr_cont); 181965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 1820c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.class = &sas_rphy_class.class; 1821c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0]; 1822c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.match = sas_rphy_match; 1823c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->rphy_attr_cont); 1824c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 182542ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attr_cont.ac.class = &sas_end_dev_class.class; 182642ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attr_cont.ac.attrs = &i->end_dev_attrs[0]; 182742ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attr_cont.ac.match = sas_end_dev_match; 182842ab03609cca4ef5079e248296f015650c626899James Bottomley transport_container_register(&i->end_dev_attr_cont); 182942ab03609cca4ef5079e248296f015650c626899James Bottomley 183079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attr_cont.ac.class = &sas_expander_class.class; 183179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attr_cont.ac.attrs = &i->expander_attrs[0]; 183279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attr_cont.ac.match = sas_expander_match; 183379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_container_register(&i->expander_attr_cont); 183479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 1835c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->f = ft; 1836c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1837c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 183865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(initiator_port_protocols); 183965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(target_port_protocols); 184065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(device_type); 184165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(sas_address); 184265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(phy_identifier); 184365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley //SETUP_PHY_ATTRIBUTE(port_identifier); 184465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(negotiated_linkrate); 184565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(minimum_linkrate_hw); 1846d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley SETUP_PHY_ATTRIBUTE_RW(minimum_linkrate); 184765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(maximum_linkrate_hw); 1848d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley SETUP_PHY_ATTRIBUTE_RW(maximum_linkrate); 184965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 185065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(invalid_dword_count); 185165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(running_disparity_error_count); 185265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(loss_of_dword_sync_count); 185365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(phy_reset_problem_count); 185465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(link_reset, phy_reset); 185565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(hard_reset, phy_reset); 1856acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(enable, phy_enable); 1857c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attrs[count] = NULL; 1858c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1859c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 186065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PORT_ATTRIBUTE(num_phys); 186165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attrs[count] = NULL; 186265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 186365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley count = 0; 1864c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols); 1865c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols); 1866c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_device_type); 1867c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_sas_address); 1868c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier); 1869dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_enclosure_identifier, 1870dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley get_enclosure_identifier); 1871dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_bay_identifier, 1872dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley get_bay_identifier); 1873c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attrs[count] = NULL; 1874c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 187542ab03609cca4ef5079e248296f015650c626899James Bottomley count = 0; 187642ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_ready_led_meaning); 187742ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_I_T_nexus_loss_timeout); 187842ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout); 18790f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_tlr_supported); 18800f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_tlr_enabled); 188142ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attrs[count] = NULL; 188242ab03609cca4ef5079e248296f015650c626899James Bottomley 188379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley count = 0; 188479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(vendor_id); 188579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(product_id); 188679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(product_rev); 188779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(component_vendor_id); 188879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(component_id); 188979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(component_revision_id); 189079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(level); 189179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attrs[count] = NULL; 189279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 1893c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->t; 1894c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1895c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_attach_transport); 1896c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1897c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1898eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_release_transport - release SAS transport template instance 1899c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @t: transport template instance 1900c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1901c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_release_transport(struct scsi_transport_template *t) 1902c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1903c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i = to_sas_internal(t); 1904c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1905c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->t.host_attrs); 1906c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->phy_attr_cont); 190765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_container_unregister(&i->port_attr_cont); 1908c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->rphy_attr_cont); 1909db82f8410ed7546792358964aa5f8dafff1c70a2James Bottomley transport_container_unregister(&i->end_dev_attr_cont); 191079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_container_unregister(&i->expander_attr_cont); 1911c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1912c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig kfree(i); 1913c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1914c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_release_transport); 1915c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1916c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic __init int sas_transport_init(void) 1917c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1918c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 1919c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1920c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = transport_class_register(&sas_host_class); 1921c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1922c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out; 1923c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = transport_class_register(&sas_phy_class); 1924c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1925c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out_unregister_transport; 192665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley error = transport_class_register(&sas_port_class); 1927c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1928c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out_unregister_phy; 192965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley error = transport_class_register(&sas_rphy_class); 193065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (error) 193165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley goto out_unregister_port; 193242ab03609cca4ef5079e248296f015650c626899James Bottomley error = transport_class_register(&sas_end_dev_class); 193342ab03609cca4ef5079e248296f015650c626899James Bottomley if (error) 193442ab03609cca4ef5079e248296f015650c626899James Bottomley goto out_unregister_rphy; 193579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley error = transport_class_register(&sas_expander_class); 193679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (error) 193779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley goto out_unregister_end_dev; 1938c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1939c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1940c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 194179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley out_unregister_end_dev: 194279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_class_unregister(&sas_end_dev_class); 194342ab03609cca4ef5079e248296f015650c626899James Bottomley out_unregister_rphy: 194442ab03609cca4ef5079e248296f015650c626899James Bottomley transport_class_unregister(&sas_rphy_class); 194565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley out_unregister_port: 194665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_class_unregister(&sas_port_class); 1947c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out_unregister_phy: 1948c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_phy_class); 1949c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out_unregister_transport: 1950c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_host_class); 1951c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out: 1952c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 1953c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1954c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1955c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1956c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic void __exit sas_transport_exit(void) 1957c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1958c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_host_class); 1959c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_phy_class); 196065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_class_unregister(&sas_port_class); 1961c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_rphy_class); 196242ab03609cca4ef5079e248296f015650c626899James Bottomley transport_class_unregister(&sas_end_dev_class); 196379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_class_unregister(&sas_expander_class); 1964c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1965c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1966c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_AUTHOR("Christoph Hellwig"); 196786b9c4c16a1589d05959af2d96d52a4352c6306eAlexis BruemmerMODULE_DESCRIPTION("SAS Transport Attributes"); 1968c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_LICENSE("GPL"); 1969c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1970c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigmodule_init(sas_transport_init); 1971c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigmodule_exit(sas_transport_exit); 1972