scsi_transport_sas.c revision 0b3e09da1350397f3f8b6fd839ab455b0b587451
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; 61807ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig return count; 61907ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig}; 62007ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 621ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t 622ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstore_sas_link_reset(struct device *dev, struct device_attribute *attr, 623ee959b00c335d7780136c5abda37809191fe52c3Tony Jones const char *buf, size_t count) 62407ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig{ 625ee959b00c335d7780136c5abda37809191fe52c3Tony Jones return do_sas_phy_reset(dev, count, 0); 62607ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig} 627ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset); 62807ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 629ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic ssize_t 630ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstore_sas_hard_reset(struct device *dev, struct device_attribute *attr, 631ee959b00c335d7780136c5abda37809191fe52c3Tony Jones const char *buf, size_t count) 63207ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig{ 633ee959b00c335d7780136c5abda37809191fe52c3Tony Jones return do_sas_phy_reset(dev, count, 1); 63407ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig} 635ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset); 63607ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 637c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_protocol_attr(identify.initiator_port_protocols, 638c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig initiator_port_protocols); 639c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_protocol_attr(identify.target_port_protocols, 640c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig target_port_protocols); 641c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", 642c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig unsigned long long); 643c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); 644c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley//sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", int); 645c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(negotiated_linkrate); 646c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(minimum_linkrate_hw); 647d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleysas_phy_linkspeed_rw_attr(minimum_linkrate); 648c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_linkspeed_attr(maximum_linkrate_hw); 649d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomleysas_phy_linkspeed_rw_attr(maximum_linkrate); 650c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(invalid_dword_count); 651c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(running_disparity_error_count); 652c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(loss_of_dword_sync_count); 653c3ee74c4e91017169c7f1fa74a57ba8502ec49c3Christoph Hellwigsas_phy_linkerror_attr(phy_reset_problem_count); 654c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 6550b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williamsstatic int sas_phy_setup(struct transport_container *tc, struct device *dev, 6560b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams struct device *cdev) 6570b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams{ 6580b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams struct sas_phy *phy = dev_to_phy(dev); 6590b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 6600b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams struct sas_internal *i = to_sas_internal(shost->transportt); 6610b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams 6620b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams if (i->f->phy_setup) 6630b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams i->f->phy_setup(phy); 6640b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams 6650b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams return 0; 6660b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams} 667c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 668c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_phy_class, 6690b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams "sas_phy", sas_phy_setup, NULL, NULL); 670c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 671c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_phy_match(struct attribute_container *cont, struct device *dev) 672c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 673c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost; 674c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 675c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 676c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!scsi_is_sas_phy(dev)) 677c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 678c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost = dev_to_shost(dev->parent); 679c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 680c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!shost->transportt) 681c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 682c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (shost->transportt->host_attrs.ac.class != 683c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig &sas_host_class.class) 684c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 685c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 686c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = to_sas_internal(shost->transportt); 687c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->phy_attr_cont.ac == cont; 688c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 689c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 690c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic void sas_phy_release(struct device *dev) 691c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 692c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy = dev_to_phy(dev); 6930b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 6940b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams struct sas_internal *i = to_sas_internal(shost->transportt); 695c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 6960b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams if (i->f->phy_release) 6970b3e09da1350397f3f8b6fd839ab455b0b587451Dan Williams i->f->phy_release(phy); 698c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(dev->parent); 699c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig kfree(phy); 700c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 701c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 702c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 703eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_phy_alloc - allocates and initialize a SAS PHY structure 704c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @parent: Parent device 705d99ca4180fe44ae7f409fc73f1a09f270b8d458aMoore, Eric * @number: Phy index 706c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 707c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Allocates an SAS PHY structure. It will be added in the device tree 708c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * below the device specified by @parent, which has to be either a Scsi_Host 709c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * or sas_rphy. 710c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 711c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 712c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS PHY allocated or %NULL if the allocation failed. 713c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 714c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct sas_phy *sas_phy_alloc(struct device *parent, int number) 715c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 716c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(parent); 717c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_phy *phy; 718c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 71924669f75a3231fa37444977c92d1f4838bec1233Jes Sorensen phy = kzalloc(sizeof(*phy), GFP_KERNEL); 720c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!phy) 721c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return NULL; 722c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 723c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy->number = number; 724acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong phy->enabled = 1; 725c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 726c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig device_initialize(&phy->dev); 727c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy->dev.parent = get_device(parent); 728c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig phy->dev.release = sas_phy_release; 72965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley INIT_LIST_HEAD(&phy->port_siblings); 73079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (scsi_is_sas_expander_device(parent)) { 73179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent); 73271610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_set_name(&phy->dev, "phy-%d:%d:%d", shost->host_no, 73379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rphy->scsi_target_id, number); 73479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley } else 73571610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_set_name(&phy->dev, "phy-%d:%d", shost->host_no, number); 736c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 737c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_setup_device(&phy->dev); 738c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 739c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return phy; 740c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 741c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_alloc); 742c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 743c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 744eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_phy_add - add a SAS PHY to the device hierarchy 745c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy: The PHY to be added 746c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 747c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Publishes a SAS PHY to the rest of the system. 748c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 749c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint sas_phy_add(struct sas_phy *phy) 750c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 751c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 752c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 753c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = device_add(&phy->dev); 754c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!error) { 755c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_add_device(&phy->dev); 756c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_configure_device(&phy->dev); 757c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 758c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 759c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 760c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 761c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_add); 762c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 763c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 764eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_phy_free - free a SAS PHY 765c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy: SAS PHY to free 766c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 767c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Frees the specified SAS PHY. 768c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 769c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Note: 770c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * This function must only be called on a PHY that has not 771af901ca181d92aac3a7dc265144a9081a86d8f39André Goddard Rosa * successfully been added using sas_phy_add(). 772c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 773c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_phy_free(struct sas_phy *phy) 774c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 775c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_destroy_device(&phy->dev); 77692aab6464be735139f9ea38fd039c3b84c722630Mike Anderson put_device(&phy->dev); 777c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 778c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_free); 779c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 780c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 781eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_phy_delete - remove SAS PHY 782c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @phy: SAS PHY to remove 783c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 784c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Removes the specified SAS PHY. If the SAS PHY has an 785c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * associated remote PHY it is removed before. 786c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 787c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid 788c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_phy_delete(struct sas_phy *phy) 789c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 790c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev = &phy->dev; 791c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 79265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* this happens if the phy is still part of a port when deleted */ 79365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley BUG_ON(!list_empty(&phy->port_siblings)); 794c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 795c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_remove_device(dev); 796c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig device_del(dev); 797c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_destroy_device(dev); 79892aab6464be735139f9ea38fd039c3b84c722630Mike Anderson put_device(dev); 799c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 800c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_phy_delete); 801c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 802c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 803eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * scsi_is_sas_phy - check if a struct device represents a SAS PHY 804c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @dev: device to check 805c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 806c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 807c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * %1 if the device represents a SAS PHY, %0 else 808c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 809c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint scsi_is_sas_phy(const struct device *dev) 810c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 811c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return dev->release == sas_phy_release; 812c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 813c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(scsi_is_sas_phy); 814c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 815c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 81665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * SAS Port attributes 81765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 81865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define sas_port_show_simple(field, name, format_string, cast) \ 81965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic ssize_t \ 820ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_port_##name(struct device *dev, \ 821ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) \ 82265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ \ 823ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_port *port = transport_class_to_sas_port(dev); \ 82465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley \ 82565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return snprintf(buf, 20, format_string, cast port->field); \ 82665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 82765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 82865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define sas_port_simple_attr(field, name, format_string, type) \ 82965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_show_simple(field, name, format_string, (type)) \ 830ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL) 83165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 83265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleysas_port_simple_attr(num_phys, num_phys, "%d\n", int); 83365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 83465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_port_class, 83565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley "sas_port", NULL, NULL, NULL); 83665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 83765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic int sas_port_match(struct attribute_container *cont, struct device *dev) 83865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 83965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct Scsi_Host *shost; 84065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_internal *i; 84165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 84265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (!scsi_is_sas_port(dev)) 84365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return 0; 84465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley shost = dev_to_shost(dev->parent); 84565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 84665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (!shost->transportt) 84765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return 0; 84865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (shost->transportt->host_attrs.ac.class != 84965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley &sas_host_class.class) 85065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return 0; 85165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 85265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i = to_sas_internal(shost->transportt); 85365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return &i->port_attr_cont.ac == cont; 85465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 85565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 85665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 85765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic void sas_port_release(struct device *dev) 85865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 85965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *port = dev_to_sas_port(dev); 86065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 86165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley BUG_ON(!list_empty(&port->phy_list)); 86265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 86365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley put_device(dev->parent); 86465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley kfree(port); 86565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 86665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 86765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic void sas_port_create_link(struct sas_port *port, 86865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *phy) 86965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 87021434966462d57145c861b43f6206d945ac57630Darrick J. Wong int res; 87121434966462d57145c861b43f6206d945ac57630Darrick J. Wong 87221434966462d57145c861b43f6206d945ac57630Darrick J. Wong res = sysfs_create_link(&port->dev.kobj, &phy->dev.kobj, 87371610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_name(&phy->dev)); 87421434966462d57145c861b43f6206d945ac57630Darrick J. Wong if (res) 87521434966462d57145c861b43f6206d945ac57630Darrick J. Wong goto err; 87621434966462d57145c861b43f6206d945ac57630Darrick J. Wong res = sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port"); 87721434966462d57145c861b43f6206d945ac57630Darrick J. Wong if (res) 87821434966462d57145c861b43f6206d945ac57630Darrick J. Wong goto err; 87921434966462d57145c861b43f6206d945ac57630Darrick J. Wong return; 88021434966462d57145c861b43f6206d945ac57630Darrick J. Wongerr: 88121434966462d57145c861b43f6206d945ac57630Darrick J. Wong printk(KERN_ERR "%s: Cannot create port links, err=%d\n", 882cadbd4a5e36dde7e6c49b587b2c419103c0b7218Harvey Harrison __func__, res); 88365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 88465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 88565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystatic void sas_port_delete_link(struct sas_port *port, 88665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *phy) 88765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 88871610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers sysfs_remove_link(&port->dev.kobj, dev_name(&phy->dev)); 88965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sysfs_remove_link(&phy->dev.kobj, "port"); 89065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 89165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 89265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** sas_port_alloc - allocate and initialize a SAS port structure 89365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 89465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @parent: parent device 89565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port_id: port number 89665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 89765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Allocates a SAS port structure. It will be added to the device tree 89865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * below the device specified by @parent which must be either a Scsi_Host 89965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * or a sas_expander_device. 90065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 90165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Returns %NULL on error 90265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 90365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystruct sas_port *sas_port_alloc(struct device *parent, int port_id) 90465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 90565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct Scsi_Host *shost = dev_to_shost(parent); 90665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *port; 90765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 90865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port = kzalloc(sizeof(*port), GFP_KERNEL); 90965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (!port) 91065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return NULL; 91165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 91265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->port_identifier = port_id; 91365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 91465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley device_initialize(&port->dev); 91565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 91665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->dev.parent = get_device(parent); 91765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->dev.release = sas_port_release; 91865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 91965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_init(&port->phy_list_mutex); 92065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley INIT_LIST_HEAD(&port->phy_list); 92165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 92265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (scsi_is_sas_expander_device(parent)) { 92365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent); 92471610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_set_name(&port->dev, "port-%d:%d:%d", shost->host_no, 92571610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers rphy->scsi_target_id, port->port_identifier); 92665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } else 92771610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_set_name(&port->dev, "port-%d:%d", shost->host_no, 92871610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers port->port_identifier); 92965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 93065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_setup_device(&port->dev); 93165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 93265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return port; 93365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 93465c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_alloc); 93565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 936c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley/** sas_port_alloc_num - allocate and initialize a SAS port structure 937c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * 938c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * @parent: parent device 939c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * 940c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * Allocates a SAS port structure and a number to go with it. This 941c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * interface is really for adapters where the port number has no 942c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * meansing, so the sas class should manage them. It will be added to 943c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * the device tree below the device specified by @parent which must be 944c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * either a Scsi_Host or a sas_expander_device. 945c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * 946c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley * Returns %NULL on error 947c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley */ 948c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomleystruct sas_port *sas_port_alloc_num(struct device *parent) 949c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley{ 950c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley int index; 951c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct Scsi_Host *shost = dev_to_shost(parent); 952c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 953c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley 954c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley /* FIXME: use idr for this eventually */ 955c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley mutex_lock(&sas_host->lock); 956c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley if (scsi_is_sas_expander_device(parent)) { 957c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent); 958c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley struct sas_expander_device *exp = rphy_to_expander_device(rphy); 959c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley 960c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley index = exp->next_port_id++; 961c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley } else 962c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley index = sas_host->next_port_id++; 963c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley mutex_unlock(&sas_host->lock); 964c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley return sas_port_alloc(parent, index); 965c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley} 966c9fefeb26457b87f4a767faefcf77321bb90db52James BottomleyEXPORT_SYMBOL(sas_port_alloc_num); 967c9fefeb26457b87f4a767faefcf77321bb90db52James Bottomley 96865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 96965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_add - add a SAS port to the device hierarchy 97065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: port to be added 97165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 97265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * publishes a port to the rest of the system 97365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 97465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyint sas_port_add(struct sas_port *port) 97565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 97665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley int error; 97765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 97865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* No phys should be added until this is made visible */ 97965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley BUG_ON(!list_empty(&port->phy_list)); 98065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 98165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley error = device_add(&port->dev); 98265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 98365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (error) 98465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return error; 98565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 98665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_add_device(&port->dev); 98765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_configure_device(&port->dev); 98865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 98965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return 0; 99065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 99165c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_add); 99265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 99365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 994eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_port_free - free a SAS PORT 99565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: SAS PORT to free 99665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 99765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Frees the specified SAS PORT. 99865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 99965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Note: 100065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * This function must only be called on a PORT that has not 1001af901ca181d92aac3a7dc265144a9081a86d8f39André Goddard Rosa * successfully been added using sas_port_add(). 100265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 100365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_free(struct sas_port *port) 100465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 100565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_destroy_device(&port->dev); 100665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley put_device(&port->dev); 100765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 100865c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_free); 100965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 101065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 1011eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_port_delete - remove SAS PORT 101265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: SAS PORT to remove 101365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 101465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Removes the specified SAS PORT. If the SAS PORT has an 101565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * associated phys, unlink them from the port as well. 101665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 101765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_delete(struct sas_port *port) 101865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 101965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct device *dev = &port->dev; 102065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *phy, *tmp_phy; 102165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 102265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (port->rphy) { 102365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_rphy_delete(port->rphy); 102465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->rphy = NULL; 102565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 102665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 102765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_lock(&port->phy_list_mutex); 102865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_for_each_entry_safe(phy, tmp_phy, &port->phy_list, 102965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port_siblings) { 103065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_delete_link(port, phy); 103165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_del_init(&phy->port_siblings); 103265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 103365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_unlock(&port->phy_list_mutex); 103465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 1035a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley if (port->is_backlink) { 1036a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley struct device *parent = port->dev.parent; 1037a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 103871610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers sysfs_remove_link(&port->dev.kobj, dev_name(parent)); 1039a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley port->is_backlink = 0; 1040a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley } 1041a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 104265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_remove_device(dev); 104365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley device_del(dev); 104465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_destroy_device(dev); 104565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley put_device(dev); 104665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 104765c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_delete); 104865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 104965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 1050eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * scsi_is_sas_port - check if a struct device represents a SAS port 105165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @dev: device to check 105265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 105365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * Returns: 105465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * %1 if the device represents a SAS Port, %0 else 105565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 105665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyint scsi_is_sas_port(const struct device *dev) 105765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 105865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley return dev->release == sas_port_release; 105965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 106065c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(scsi_is_sas_port); 106165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 106265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 106365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_add_phy - add another phy to a port to form a wide port 106465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: port to add the phy to 106565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @phy: phy to add 106665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 106765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * When a port is initially created, it is empty (has no phys). All 106865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * ports must have at least one phy to operated, and all wide ports 106965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * must have at least two. The current code makes no difference 107065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * between ports and wide ports, but the only object that can be 107165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * connected to a remote device is a port, so ports must be formed on 107265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * all devices with phys if they're connected to anything. 107365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 107465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_add_phy(struct sas_port *port, struct sas_phy *phy) 107565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 107665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_lock(&port->phy_list_mutex); 107765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (unlikely(!list_empty(&phy->port_siblings))) { 107865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* make sure we're already on this port */ 107965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_phy *tmp; 108065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 108165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_for_each_entry(tmp, &port->phy_list, port_siblings) 108265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (tmp == phy) 108365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley break; 108465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley /* If this trips, you added a phy that was already 108565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * part of a different port */ 108665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (unlikely(tmp != phy)) { 108771610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_printk(KERN_ERR, &port->dev, "trying to add phy %s fails: it's already part of another port\n", 108871610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_name(&phy->dev)); 108965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley BUG(); 109065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 109165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } else { 109265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_create_link(port, phy); 109365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_add_tail(&phy->port_siblings, &port->phy_list); 109465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->num_phys++; 109565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } 109665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_unlock(&port->phy_list_mutex); 109765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 109865c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_add_phy); 109965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 110065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/** 110165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * sas_port_delete_phy - remove a phy from a port or wide port 110265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @port: port to remove the phy from 110365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * @phy: phy to remove 110465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * 110565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * This operation is used for tearing down ports again. It must be 110665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley * done to every port or wide port before calling sas_port_delete. 110765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley */ 110865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleyvoid sas_port_delete_phy(struct sas_port *port, struct sas_phy *phy) 110965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley{ 111065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_lock(&port->phy_list_mutex); 111165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_port_delete_link(port, phy); 111265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley list_del_init(&phy->port_siblings); 111365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley port->num_phys--; 111465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley mutex_unlock(&port->phy_list_mutex); 111565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley} 111665c92b09acf0218b64f1c7ba4fdabeb8b732c876James BottomleyEXPORT_SYMBOL(sas_port_delete_phy); 111765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 1118a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomleyvoid sas_port_mark_backlink(struct sas_port *port) 1119a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley{ 112021434966462d57145c861b43f6206d945ac57630Darrick J. Wong int res; 1121a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley struct device *parent = port->dev.parent->parent->parent; 1122a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 1123a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley if (port->is_backlink) 1124a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley return; 1125a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley port->is_backlink = 1; 112621434966462d57145c861b43f6206d945ac57630Darrick J. Wong res = sysfs_create_link(&port->dev.kobj, &parent->kobj, 112771610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_name(parent)); 112821434966462d57145c861b43f6206d945ac57630Darrick J. Wong if (res) 112921434966462d57145c861b43f6206d945ac57630Darrick J. Wong goto err; 113021434966462d57145c861b43f6206d945ac57630Darrick J. Wong return; 113121434966462d57145c861b43f6206d945ac57630Darrick J. Wongerr: 113221434966462d57145c861b43f6206d945ac57630Darrick J. Wong printk(KERN_ERR "%s: Cannot create port backlink, err=%d\n", 1133cadbd4a5e36dde7e6c49b587b2c419103c0b7218Harvey Harrison __func__, res); 1134a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 1135a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley} 1136a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames BottomleyEXPORT_SYMBOL(sas_port_mark_backlink); 1137a0e1b6ef3b851fe6f1dcc259432e83de79ce5e7fJames Bottomley 113865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley/* 1139c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SAS remote PHY attributes. 1140c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1141c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1142c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_show_simple(field, name, format_string, cast) \ 1143c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 1144ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_rphy_##name(struct device *dev, \ 1145ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) \ 1146c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 1147ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_rphy *rphy = transport_class_to_rphy(dev); \ 1148c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 1149c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, format_string, cast rphy->field); \ 1150c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1151c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1152c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_simple_attr(field, name, format_string, type) \ 1153c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_rphy_show_simple(field, name, format_string, (type)) \ 1154ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(rphy, name, S_IRUGO, \ 1155c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_##name, NULL) 1156c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1157c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_show_protocol(field, name) \ 1158c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t \ 1159ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_rphy_##name(struct device *dev, \ 1160ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) \ 1161c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ \ 1162ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_rphy *rphy = transport_class_to_rphy(dev); \ 1163c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig \ 1164c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!rphy->field) \ 1165c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); \ 1166c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_protocol_names(rphy->field, buf); \ 1167c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1168c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1169c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig#define sas_rphy_protocol_attr(field, name) \ 1170c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig sas_rphy_show_protocol(field, name) \ 1171ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(rphy, name, S_IRUGO, \ 1172c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_##name, NULL) 1173c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1174c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic ssize_t 1175ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_rphy_device_type(struct device *dev, 1176ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) 1177c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1178ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_rphy *rphy = transport_class_to_rphy(dev); 1179c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1180c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!rphy->identify.device_type) 1181c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return snprintf(buf, 20, "none\n"); 1182c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return get_sas_device_type_names( 1183c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->identify.device_type, buf); 1184c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1185c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1186ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(rphy, device_type, S_IRUGO, 1187c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig show_sas_rphy_device_type, NULL); 1188c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1189a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic ssize_t 1190ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_rphy_enclosure_identifier(struct device *dev, 1191ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) 1192a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig{ 1193ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_rphy *rphy = transport_class_to_rphy(dev); 1194a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_phy *phy = dev_to_phy(rphy->dev.parent); 1195a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 1196a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); 1197a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig u64 identifier; 1198a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig int error; 1199a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 1200a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig /* 1201a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig * Only devices behind an expander are supported, because the 1202a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig * enclosure identifier is a SMP feature. 1203a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig */ 1204f4ad7b5807385ad1fed0347d966e51a797cd1013James Bottomley if (scsi_is_sas_phy_local(phy)) 1205a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return -EINVAL; 1206a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 1207a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig error = i->f->get_enclosure_identifier(rphy, &identifier); 1208a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig if (error) 1209a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return error; 1210a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return sprintf(buf, "0x%llx\n", (unsigned long long)identifier); 1211a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig} 1212a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 1213ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO, 1214a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig show_sas_rphy_enclosure_identifier, NULL); 1215a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 1216a012564136a665f8d63443c057ba368572b483dfChristoph Hellwigstatic ssize_t 1217ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_rphy_bay_identifier(struct device *dev, 1218ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) 1219a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig{ 1220ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_rphy *rphy = transport_class_to_rphy(dev); 1221a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_phy *phy = dev_to_phy(rphy->dev.parent); 1222a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); 1223a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig struct sas_internal *i = to_sas_internal(shost->transportt); 1224a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig int val; 1225a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 1226f4ad7b5807385ad1fed0347d966e51a797cd1013James Bottomley if (scsi_is_sas_phy_local(phy)) 1227a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return -EINVAL; 1228a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 1229a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig val = i->f->get_bay_identifier(rphy); 1230a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig if (val < 0) 1231a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return val; 1232a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig return sprintf(buf, "%d\n", val); 1233a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig} 1234a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 1235ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO, 1236a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig show_sas_rphy_bay_identifier, NULL); 1237a012564136a665f8d63443c057ba368572b483dfChristoph Hellwig 1238c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_protocol_attr(identify.initiator_port_protocols, 1239c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig initiator_port_protocols); 1240c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols); 1241c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n", 1242c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig unsigned long long); 1243c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8); 1244c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 124542ab03609cca4ef5079e248296f015650c626899James Bottomley/* only need 8 bytes of data plus header (4 or 8) */ 124642ab03609cca4ef5079e248296f015650c626899James Bottomley#define BUF_SIZE 64 124742ab03609cca4ef5079e248296f015650c626899James Bottomley 124842ab03609cca4ef5079e248296f015650c626899James Bottomleyint sas_read_port_mode_page(struct scsi_device *sdev) 124942ab03609cca4ef5079e248296f015650c626899James Bottomley{ 125042ab03609cca4ef5079e248296f015650c626899James Bottomley char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata; 12510f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley struct sas_end_device *rdev = sas_sdev_to_rdev(sdev); 125242ab03609cca4ef5079e248296f015650c626899James Bottomley struct scsi_mode_data mode_data; 125342ab03609cca4ef5079e248296f015650c626899James Bottomley int res, error; 125442ab03609cca4ef5079e248296f015650c626899James Bottomley 125542ab03609cca4ef5079e248296f015650c626899James Bottomley if (!buffer) 125642ab03609cca4ef5079e248296f015650c626899James Bottomley return -ENOMEM; 125742ab03609cca4ef5079e248296f015650c626899James Bottomley 125842ab03609cca4ef5079e248296f015650c626899James Bottomley res = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3, 125942ab03609cca4ef5079e248296f015650c626899James Bottomley &mode_data, NULL); 126042ab03609cca4ef5079e248296f015650c626899James Bottomley 126142ab03609cca4ef5079e248296f015650c626899James Bottomley error = -EINVAL; 126242ab03609cca4ef5079e248296f015650c626899James Bottomley if (!scsi_status_is_good(res)) 126342ab03609cca4ef5079e248296f015650c626899James Bottomley goto out; 126442ab03609cca4ef5079e248296f015650c626899James Bottomley 126542ab03609cca4ef5079e248296f015650c626899James Bottomley msdata = buffer + mode_data.header_length + 126642ab03609cca4ef5079e248296f015650c626899James Bottomley mode_data.block_descriptor_length; 126742ab03609cca4ef5079e248296f015650c626899James Bottomley 126842ab03609cca4ef5079e248296f015650c626899James Bottomley if (msdata - buffer > BUF_SIZE - 8) 126942ab03609cca4ef5079e248296f015650c626899James Bottomley goto out; 127042ab03609cca4ef5079e248296f015650c626899James Bottomley 127142ab03609cca4ef5079e248296f015650c626899James Bottomley error = 0; 127242ab03609cca4ef5079e248296f015650c626899James Bottomley 127342ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->ready_led_meaning = msdata[2] & 0x10 ? 1 : 0; 127442ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->I_T_nexus_loss_timeout = (msdata[4] << 8) + msdata[5]; 127542ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->initiator_response_timeout = (msdata[6] << 8) + msdata[7]; 127642ab03609cca4ef5079e248296f015650c626899James Bottomley 127742ab03609cca4ef5079e248296f015650c626899James Bottomley out: 127842ab03609cca4ef5079e248296f015650c626899James Bottomley kfree(buffer); 127942ab03609cca4ef5079e248296f015650c626899James Bottomley return error; 128042ab03609cca4ef5079e248296f015650c626899James Bottomley} 128142ab03609cca4ef5079e248296f015650c626899James BottomleyEXPORT_SYMBOL(sas_read_port_mode_page); 128242ab03609cca4ef5079e248296f015650c626899James Bottomley 128379cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_end_dev_class, 128479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley "sas_end_device", NULL, NULL, NULL); 128579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 128642ab03609cca4ef5079e248296f015650c626899James Bottomley#define sas_end_dev_show_simple(field, name, format_string, cast) \ 128742ab03609cca4ef5079e248296f015650c626899James Bottomleystatic ssize_t \ 1288ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_end_dev_##name(struct device *dev, \ 1289ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) \ 129042ab03609cca4ef5079e248296f015650c626899James Bottomley{ \ 1291ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_rphy *rphy = transport_class_to_rphy(dev); \ 129242ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_end_device *rdev = rphy_to_end_device(rphy); \ 129342ab03609cca4ef5079e248296f015650c626899James Bottomley \ 129442ab03609cca4ef5079e248296f015650c626899James Bottomley return snprintf(buf, 20, format_string, cast rdev->field); \ 129542ab03609cca4ef5079e248296f015650c626899James Bottomley} 129642ab03609cca4ef5079e248296f015650c626899James Bottomley 129742ab03609cca4ef5079e248296f015650c626899James Bottomley#define sas_end_dev_simple_attr(field, name, format_string, type) \ 129842ab03609cca4ef5079e248296f015650c626899James Bottomley sas_end_dev_show_simple(field, name, format_string, (type)) \ 1299ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(end_dev, name, S_IRUGO, \ 130042ab03609cca4ef5079e248296f015650c626899James Bottomley show_sas_end_dev_##name, NULL) 130142ab03609cca4ef5079e248296f015650c626899James Bottomley 130242ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(ready_led_meaning, ready_led_meaning, "%d\n", int); 130342ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(I_T_nexus_loss_timeout, I_T_nexus_loss_timeout, 130442ab03609cca4ef5079e248296f015650c626899James Bottomley "%d\n", int); 130542ab03609cca4ef5079e248296f015650c626899James Bottomleysas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout, 130642ab03609cca4ef5079e248296f015650c626899James Bottomley "%d\n", int); 13070f88009d5cfae890bd3466126d1622ad4f16b798James Bottomleysas_end_dev_simple_attr(tlr_supported, tlr_supported, 13080f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley "%d\n", int); 13090f88009d5cfae890bd3466126d1622ad4f16b798James Bottomleysas_end_dev_simple_attr(tlr_enabled, tlr_enabled, 13100f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley "%d\n", int); 131142ab03609cca4ef5079e248296f015650c626899James Bottomley 131279cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic DECLARE_TRANSPORT_CLASS(sas_expander_class, 131379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley "sas_expander", NULL, NULL, NULL); 131479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 131579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define sas_expander_show_simple(field, name, format_string, cast) \ 131679cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic ssize_t \ 1317ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesshow_sas_expander_##name(struct device *dev, \ 1318ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct device_attribute *attr, char *buf) \ 131979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{ \ 1320ee959b00c335d7780136c5abda37809191fe52c3Tony Jones struct sas_rphy *rphy = transport_class_to_rphy(dev); \ 132179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_expander_device *edev = rphy_to_expander_device(rphy); \ 132279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley \ 132379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return snprintf(buf, 20, format_string, cast edev->field); \ 132479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley} 132579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 132679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define sas_expander_simple_attr(field, name, format_string, type) \ 132779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley sas_expander_show_simple(field, name, format_string, (type)) \ 1328ee959b00c335d7780136c5abda37809191fe52c3Tony Jonesstatic SAS_DEVICE_ATTR(expander, name, S_IRUGO, \ 132979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley show_sas_expander_##name, NULL) 133079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 133179cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(vendor_id, vendor_id, "%s\n", char *); 133279cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(product_id, product_id, "%s\n", char *); 133379cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(product_rev, product_rev, "%s\n", char *); 133479cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_vendor_id, component_vendor_id, 133579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley "%s\n", char *); 133679cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_id, component_id, "%u\n", unsigned int); 133779cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(component_revision_id, component_revision_id, "%u\n", 133879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley unsigned int); 133979cb1819e231f811211133a09a5382cb89d7ec67James Bottomleysas_expander_simple_attr(level, level, "%d\n", int); 134042ab03609cca4ef5079e248296f015650c626899James Bottomley 1341c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic DECLARE_TRANSPORT_CLASS(sas_rphy_class, 13422f8600dff2b140096a7df781884e918a16aa90e0James Bottomley "sas_device", NULL, NULL, NULL); 1343c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1344c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic int sas_rphy_match(struct attribute_container *cont, struct device *dev) 1345c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1346c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost; 1347c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 1348c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1349c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!scsi_is_sas_rphy(dev)) 1350c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1351c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig shost = dev_to_shost(dev->parent->parent); 1352c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1353c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!shost->transportt) 1354c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1355c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (shost->transportt->host_attrs.ac.class != 1356c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig &sas_host_class.class) 1357c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1358c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1359c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i = to_sas_internal(shost->transportt); 1360c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->rphy_attr_cont.ac == cont; 1361c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1362c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 136342ab03609cca4ef5079e248296f015650c626899James Bottomleystatic int sas_end_dev_match(struct attribute_container *cont, 136442ab03609cca4ef5079e248296f015650c626899James Bottomley struct device *dev) 136542ab03609cca4ef5079e248296f015650c626899James Bottomley{ 136642ab03609cca4ef5079e248296f015650c626899James Bottomley struct Scsi_Host *shost; 136742ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_internal *i; 136842ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_rphy *rphy; 136942ab03609cca4ef5079e248296f015650c626899James Bottomley 137042ab03609cca4ef5079e248296f015650c626899James Bottomley if (!scsi_is_sas_rphy(dev)) 137142ab03609cca4ef5079e248296f015650c626899James Bottomley return 0; 137242ab03609cca4ef5079e248296f015650c626899James Bottomley shost = dev_to_shost(dev->parent->parent); 137342ab03609cca4ef5079e248296f015650c626899James Bottomley rphy = dev_to_rphy(dev); 137442ab03609cca4ef5079e248296f015650c626899James Bottomley 137542ab03609cca4ef5079e248296f015650c626899James Bottomley if (!shost->transportt) 137642ab03609cca4ef5079e248296f015650c626899James Bottomley return 0; 137742ab03609cca4ef5079e248296f015650c626899James Bottomley if (shost->transportt->host_attrs.ac.class != 137842ab03609cca4ef5079e248296f015650c626899James Bottomley &sas_host_class.class) 137942ab03609cca4ef5079e248296f015650c626899James Bottomley return 0; 138042ab03609cca4ef5079e248296f015650c626899James Bottomley 138142ab03609cca4ef5079e248296f015650c626899James Bottomley i = to_sas_internal(shost->transportt); 138242ab03609cca4ef5079e248296f015650c626899James Bottomley return &i->end_dev_attr_cont.ac == cont && 13832f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rphy->identify.device_type == SAS_END_DEVICE; 138442ab03609cca4ef5079e248296f015650c626899James Bottomley} 138542ab03609cca4ef5079e248296f015650c626899James Bottomley 138679cb1819e231f811211133a09a5382cb89d7ec67James Bottomleystatic int sas_expander_match(struct attribute_container *cont, 138779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct device *dev) 138879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{ 138979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct Scsi_Host *shost; 139079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_internal *i; 139179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_rphy *rphy; 139279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 139379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (!scsi_is_sas_rphy(dev)) 139479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return 0; 139579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley shost = dev_to_shost(dev->parent->parent); 139679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rphy = dev_to_rphy(dev); 139779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 139879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (!shost->transportt) 139979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return 0; 140079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (shost->transportt->host_attrs.ac.class != 140179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley &sas_host_class.class) 140279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return 0; 140379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 140479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i = to_sas_internal(shost->transportt); 140579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return &i->expander_attr_cont.ac == cont && 140679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE || 14072f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE); 140879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley} 140979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 14102f8600dff2b140096a7df781884e918a16aa90e0James Bottomleystatic void sas_expander_release(struct device *dev) 1411c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1412c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy = dev_to_rphy(dev); 14132f8600dff2b140096a7df781884e918a16aa90e0James Bottomley struct sas_expander_device *edev = rphy_to_expander_device(rphy); 1414c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 141593c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori if (rphy->q) 141693c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori blk_cleanup_queue(rphy->q); 141793c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori 1418c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig put_device(dev->parent); 14192f8600dff2b140096a7df781884e918a16aa90e0James Bottomley kfree(edev); 1420c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1421c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 14222f8600dff2b140096a7df781884e918a16aa90e0James Bottomleystatic void sas_end_device_release(struct device *dev) 1423c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 14242f8600dff2b140096a7df781884e918a16aa90e0James Bottomley struct sas_rphy *rphy = dev_to_rphy(dev); 14252f8600dff2b140096a7df781884e918a16aa90e0James Bottomley struct sas_end_device *edev = rphy_to_end_device(rphy); 1426c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 142793c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori if (rphy->q) 142893c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori blk_cleanup_queue(rphy->q); 142993c20a59af4624aedf53f8320606b355aa951bc1FUJITA Tomonori 14302f8600dff2b140096a7df781884e918a16aa90e0James Bottomley put_device(dev->parent); 14312f8600dff2b140096a7df781884e918a16aa90e0James Bottomley kfree(edev); 1432c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1433c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1434c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1435c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * sas_rphy_initialize - common rphy intialization 1436c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * @rphy: rphy to initialise 1437c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * 1438c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * Used by both sas_end_device_alloc() and sas_expander_alloc() to 1439c5943d36aebb79589ac3983eec418bbeca897573James Bottomley * initialise the common rphy component of each. 1440c5943d36aebb79589ac3983eec418bbeca897573James Bottomley */ 1441c5943d36aebb79589ac3983eec418bbeca897573James Bottomleystatic void sas_rphy_initialize(struct sas_rphy *rphy) 1442c5943d36aebb79589ac3983eec418bbeca897573James Bottomley{ 1443c5943d36aebb79589ac3983eec418bbeca897573James Bottomley INIT_LIST_HEAD(&rphy->list); 1444c5943d36aebb79589ac3983eec418bbeca897573James Bottomley} 1445c5943d36aebb79589ac3983eec418bbeca897573James Bottomley 1446c5943d36aebb79589ac3983eec418bbeca897573James Bottomley/** 144742ab03609cca4ef5079e248296f015650c626899James Bottomley * sas_end_device_alloc - allocate an rphy for an end device 1448eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @parent: which port 144942ab03609cca4ef5079e248296f015650c626899James Bottomley * 145042ab03609cca4ef5079e248296f015650c626899James Bottomley * Allocates an SAS remote PHY structure, connected to @parent. 145142ab03609cca4ef5079e248296f015650c626899James Bottomley * 145242ab03609cca4ef5079e248296f015650c626899James Bottomley * Returns: 145342ab03609cca4ef5079e248296f015650c626899James Bottomley * SAS PHY allocated or %NULL if the allocation failed. 145442ab03609cca4ef5079e248296f015650c626899James Bottomley */ 145565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystruct sas_rphy *sas_end_device_alloc(struct sas_port *parent) 145642ab03609cca4ef5079e248296f015650c626899James Bottomley{ 145742ab03609cca4ef5079e248296f015650c626899James Bottomley struct Scsi_Host *shost = dev_to_shost(&parent->dev); 145842ab03609cca4ef5079e248296f015650c626899James Bottomley struct sas_end_device *rdev; 145942ab03609cca4ef5079e248296f015650c626899James Bottomley 146042ab03609cca4ef5079e248296f015650c626899James Bottomley rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 146142ab03609cca4ef5079e248296f015650c626899James Bottomley if (!rdev) { 146242ab03609cca4ef5079e248296f015650c626899James Bottomley return NULL; 146342ab03609cca4ef5079e248296f015650c626899James Bottomley } 146442ab03609cca4ef5079e248296f015650c626899James Bottomley 146542ab03609cca4ef5079e248296f015650c626899James Bottomley device_initialize(&rdev->rphy.dev); 146642ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->rphy.dev.parent = get_device(&parent->dev); 14672f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rdev->rphy.dev.release = sas_end_device_release; 146865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (scsi_is_sas_expander_device(parent->dev.parent)) { 146965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_rphy *rphy = dev_to_rphy(parent->dev.parent); 147071610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_set_name(&rdev->rphy.dev, "end_device-%d:%d:%d", 147171610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers shost->host_no, rphy->scsi_target_id, 147271610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers parent->port_identifier); 147365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley } else 147471610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_set_name(&rdev->rphy.dev, "end_device-%d:%d", 147571610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers shost->host_no, parent->port_identifier); 147642ab03609cca4ef5079e248296f015650c626899James Bottomley rdev->rphy.identify.device_type = SAS_END_DEVICE; 1477c5943d36aebb79589ac3983eec418bbeca897573James Bottomley sas_rphy_initialize(&rdev->rphy); 147842ab03609cca4ef5079e248296f015650c626899James Bottomley transport_setup_device(&rdev->rphy.dev); 147942ab03609cca4ef5079e248296f015650c626899James Bottomley 148042ab03609cca4ef5079e248296f015650c626899James Bottomley return &rdev->rphy; 148142ab03609cca4ef5079e248296f015650c626899James Bottomley} 148242ab03609cca4ef5079e248296f015650c626899James BottomleyEXPORT_SYMBOL(sas_end_device_alloc); 148342ab03609cca4ef5079e248296f015650c626899James Bottomley 148479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley/** 148579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * sas_expander_alloc - allocate an rphy for an end device 1486eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @parent: which port 1487eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @type: SAS_EDGE_EXPANDER_DEVICE or SAS_FANOUT_EXPANDER_DEVICE 148879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * 148979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * Allocates an SAS remote PHY structure, connected to @parent. 149079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * 149179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * Returns: 149279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley * SAS PHY allocated or %NULL if the allocation failed. 149379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley */ 149465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomleystruct sas_rphy *sas_expander_alloc(struct sas_port *parent, 149579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley enum sas_device_type type) 149679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley{ 149779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct Scsi_Host *shost = dev_to_shost(&parent->dev); 149879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_expander_device *rdev; 149979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 150079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 150179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley BUG_ON(type != SAS_EDGE_EXPANDER_DEVICE && 150279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley type != SAS_FANOUT_EXPANDER_DEVICE); 150379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 150479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); 150579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (!rdev) { 150679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return NULL; 150779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley } 150879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 150979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley device_initialize(&rdev->rphy.dev); 151079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev->rphy.dev.parent = get_device(&parent->dev); 15112f8600dff2b140096a7df781884e918a16aa90e0James Bottomley rdev->rphy.dev.release = sas_expander_release; 151279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley mutex_lock(&sas_host->lock); 151379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev->rphy.scsi_target_id = sas_host->next_expander_id++; 151479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley mutex_unlock(&sas_host->lock); 151571610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers dev_set_name(&rdev->rphy.dev, "expander-%d:%d", 151671610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers shost->host_no, rdev->rphy.scsi_target_id); 151779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rdev->rphy.identify.device_type = type; 1518c5943d36aebb79589ac3983eec418bbeca897573James Bottomley sas_rphy_initialize(&rdev->rphy); 151979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_setup_device(&rdev->rphy.dev); 152079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 152179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley return &rdev->rphy; 152279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley} 152379cb1819e231f811211133a09a5382cb89d7ec67James BottomleyEXPORT_SYMBOL(sas_expander_alloc); 152442ab03609cca4ef5079e248296f015650c626899James Bottomley 152542ab03609cca4ef5079e248296f015650c626899James Bottomley/** 1526eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_rphy_add - add a SAS remote PHY to the device hierarchy 1527c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @rphy: The remote PHY to be added 1528c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1529c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Publishes a SAS remote PHY to the rest of the system. 1530c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1531c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint sas_rphy_add(struct sas_rphy *rphy) 1532c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 153365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley struct sas_port *parent = dev_to_sas_port(rphy->dev.parent); 1534c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(parent->dev.parent); 1535c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1536c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_identify *identify = &rphy->identify; 1537c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 1538c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1539c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (parent->rphy) 1540c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return -ENXIO; 1541c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig parent->rphy = rphy; 1542c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1543c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = device_add(&rphy->dev); 1544c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1545c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 1546c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_add_device(&rphy->dev); 1547c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_configure_device(&rphy->dev); 154839dca558a5b52b63e49bc234a7e887be092aa690James Bottomley if (sas_bsg_initialize(shost, rphy)) 154971610f55fa4db63dbf5385929a47c9fb2451f332Kay Sievers printk("fail to a bsg device %s\n", dev_name(&rphy->dev)); 155039dca558a5b52b63e49bc234a7e887be092aa690James Bottomley 1551c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1552e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 1553c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_add_tail(&rphy->list, &sas_host->rphy_list); 1554c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (identify->device_type == SAS_END_DEVICE && 1555c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig (identify->target_port_protocols & 1556c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA))) 1557c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig rphy->scsi_target_id = sas_host->next_target_id++; 15587676f83aeb774e7a3abe6af06ec92b29488b5b79James Bottomley else if (identify->device_type == SAS_END_DEVICE) 15597676f83aeb774e7a3abe6af06ec92b29488b5b79James Bottomley rphy->scsi_target_id = -1; 1560e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 1561c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 156279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (identify->device_type == SAS_END_DEVICE && 156379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley rphy->scsi_target_id != -1) { 15642fc62e2ac350b8f574e0a09170b350a8f2fa4a02Dan Williams int lun; 15652fc62e2ac350b8f574e0a09170b350a8f2fa4a02Dan Williams 15662fc62e2ac350b8f574e0a09170b350a8f2fa4a02Dan Williams if (identify->target_port_protocols & SAS_PROTOCOL_SSP) 15672fc62e2ac350b8f574e0a09170b350a8f2fa4a02Dan Williams lun = SCAN_WILD_CARD; 15682fc62e2ac350b8f574e0a09170b350a8f2fa4a02Dan Williams else 15692fc62e2ac350b8f574e0a09170b350a8f2fa4a02Dan Williams lun = 0; 15702fc62e2ac350b8f574e0a09170b350a8f2fa4a02Dan Williams 15712fc62e2ac350b8f574e0a09170b350a8f2fa4a02Dan Williams scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id, lun, 0); 1572c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 1573c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1574c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1575c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1576c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_add); 1577c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1578c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1579eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_rphy_free - free a SAS remote PHY 1580eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * @rphy: SAS remote PHY to free 1581c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1582c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Frees the specified SAS remote PHY. 1583c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1584c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Note: 1585c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * This function must only be called on a remote 1586af901ca181d92aac3a7dc265144a9081a86d8f39André Goddard Rosa * PHY that has not successfully been added using 15876f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * sas_rphy_add() (or has been sas_rphy_remove()'d) 1588c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1589c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_rphy_free(struct sas_rphy *rphy) 1590c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 159192aab6464be735139f9ea38fd039c3b84c722630Mike Anderson struct device *dev = &rphy->dev; 1592c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); 1593c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1594c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1595e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 1596c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_del(&rphy->list); 1597e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 1598c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1599b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley sas_bsg_remove(shost, rphy); 1600b6aff66953a29e40e0683be9b39c369ade143a5bJames Bottomley 160192aab6464be735139f9ea38fd039c3b84c722630Mike Anderson transport_destroy_device(dev); 16022f8600dff2b140096a7df781884e918a16aa90e0James Bottomley 160392aab6464be735139f9ea38fd039c3b84c722630Mike Anderson put_device(dev); 1604c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1605c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_rphy_free); 1606c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1607c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1608eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_rphy_delete - remove and free SAS remote PHY 16096f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * @rphy: SAS remote PHY to remove and free 1610c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 16116f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * Removes the specified SAS remote PHY and frees it. 1612c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1613c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid 1614c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_rphy_delete(struct sas_rphy *rphy) 1615c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 16166f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong sas_rphy_remove(rphy); 16176f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong sas_rphy_free(rphy); 16186f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong} 16196f63caae2172e97e528b58319480217b0b36542eDarrick J. WongEXPORT_SYMBOL(sas_rphy_delete); 16206f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong 16216f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong/** 162287c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams * sas_rphy_unlink - unlink SAS remote PHY 162387c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams * @rphy: SAS remote phy to unlink from its parent port 162487c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams * 162587c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams * Removes port reference to an rphy 162687c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams */ 162787c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williamsvoid sas_rphy_unlink(struct sas_rphy *rphy) 162887c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams{ 162987c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams struct sas_port *parent = dev_to_sas_port(rphy->dev.parent); 163087c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams 163187c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams parent->rphy = NULL; 163287c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams} 163387c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan WilliamsEXPORT_SYMBOL(sas_rphy_unlink); 163487c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams 163587c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams/** 1636eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_rphy_remove - remove SAS remote PHY 16376f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * @rphy: SAS remote phy to remove 16386f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * 16396f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong * Removes the specified SAS remote PHY. 16406f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong */ 16416f63caae2172e97e528b58319480217b0b36542eDarrick J. Wongvoid 16426f63caae2172e97e528b58319480217b0b36542eDarrick J. Wongsas_rphy_remove(struct sas_rphy *rphy) 16436f63caae2172e97e528b58319480217b0b36542eDarrick J. Wong{ 1644c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct device *dev = &rphy->dev; 1645c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1646d4054239929479907f20b9d68c905589125ad343Christoph Hellwig switch (rphy->identify.device_type) { 1647d4054239929479907f20b9d68c905589125ad343Christoph Hellwig case SAS_END_DEVICE: 1648d4054239929479907f20b9d68c905589125ad343Christoph Hellwig scsi_remove_target(dev); 1649d4054239929479907f20b9d68c905589125ad343Christoph Hellwig break; 1650d4054239929479907f20b9d68c905589125ad343Christoph Hellwig case SAS_EDGE_EXPANDER_DEVICE: 1651d4054239929479907f20b9d68c905589125ad343Christoph Hellwig case SAS_FANOUT_EXPANDER_DEVICE: 165265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley sas_remove_children(dev); 1653d4054239929479907f20b9d68c905589125ad343Christoph Hellwig break; 1654d4054239929479907f20b9d68c905589125ad343Christoph Hellwig default: 1655d4054239929479907f20b9d68c905589125ad343Christoph Hellwig break; 1656d4054239929479907f20b9d68c905589125ad343Christoph Hellwig } 1657c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 165887c8331fcf72e501c3a3c0cdc5c9391ec72f7cf2Dan Williams sas_rphy_unlink(rphy); 1659fe8b2304e54552cea113318e2f66c45628130fdcChristoph Hellwig transport_remove_device(dev); 1660fe8b2304e54552cea113318e2f66c45628130fdcChristoph Hellwig device_del(dev); 1661c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 16626f63caae2172e97e528b58319480217b0b36542eDarrick J. WongEXPORT_SYMBOL(sas_rphy_remove); 1663c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1664c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1665eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * scsi_is_sas_rphy - check if a struct device represents a SAS remote PHY 1666c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @dev: device to check 1667c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * 1668c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Returns: 1669c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * %1 if the device represents a SAS remote PHY, %0 else 1670c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1671c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigint scsi_is_sas_rphy(const struct device *dev) 1672c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 16732f8600dff2b140096a7df781884e918a16aa90e0James Bottomley return dev->release == sas_end_device_release || 16742f8600dff2b140096a7df781884e918a16aa90e0James Bottomley dev->release == sas_expander_release; 1675c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1676c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(scsi_is_sas_rphy); 1677c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1678c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1679c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 1680c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * SCSI scan helper 1681c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1682c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1683e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwigstatic int sas_user_scan(struct Scsi_Host *shost, uint channel, 1684e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig uint id, uint lun) 1685c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1686c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); 1687c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_rphy *rphy; 1688c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1689e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_lock(&sas_host->lock); 1690c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig list_for_each_entry(rphy, &sas_host->rphy_list, list) { 16916d99a3f372181160a56d7b1ee3259dbe03663f0dJames Bottomley if (rphy->identify.device_type != SAS_END_DEVICE || 16926d99a3f372181160a56d7b1ee3259dbe03663f0dJames Bottomley rphy->scsi_target_id == -1) 1693e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig continue; 1694e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig 1695e8bf39417b578a11e2ee2cd16e794a5b2d40757bJames Bottomley if ((channel == SCAN_WILD_CARD || channel == 0) && 1696e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) { 1697e8bf39417b578a11e2ee2cd16e794a5b2d40757bJames Bottomley scsi_scan_target(&rphy->dev, 0, 1698e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig rphy->scsi_target_id, lun, 1); 1699e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig } 1700c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig } 1701e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig mutex_unlock(&sas_host->lock); 1702c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1703e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig return 0; 1704c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1705c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1706c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1707c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/* 1708c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * Setup / Teardown code 1709c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1710c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1711d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define SETUP_TEMPLATE(attrb, field, perm, test) \ 1712ee959b00c335d7780136c5abda37809191fe52c3Tony Jones i->private_##attrb[count] = dev_attr_##field; \ 171342ab03609cca4ef5079e248296f015650c626899James Bottomley i->private_##attrb[count].attr.mode = perm; \ 171442ab03609cca4ef5079e248296f015650c626899James Bottomley i->attrb[count] = &i->private_##attrb[count]; \ 171542ab03609cca4ef5079e248296f015650c626899James Bottomley if (test) \ 171642ab03609cca4ef5079e248296f015650c626899James Bottomley count++ 171742ab03609cca4ef5079e248296f015650c626899James Bottomley 1718d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define SETUP_TEMPLATE_RW(attrb, field, perm, test, ro_test, ro_perm) \ 1719ee959b00c335d7780136c5abda37809191fe52c3Tony Jones i->private_##attrb[count] = dev_attr_##field; \ 1720d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley i->private_##attrb[count].attr.mode = perm; \ 1721d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley if (ro_test) { \ 1722d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley i->private_##attrb[count].attr.mode = ro_perm; \ 1723d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley i->private_##attrb[count].store = NULL; \ 1724d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley } \ 1725d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley i->attrb[count] = &i->private_##attrb[count]; \ 1726d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley if (test) \ 1727d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley count++ 172842ab03609cca4ef5079e248296f015650c626899James Bottomley 172942ab03609cca4ef5079e248296f015650c626899James Bottomley#define SETUP_RPORT_ATTRIBUTE(field) \ 173042ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, 1) 1731c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1732dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley#define SETUP_OPTIONAL_RPORT_ATTRIBUTE(field, func) \ 173342ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, i->f->func) 1734dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley 173565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_PHY_ATTRIBUTE(field) \ 173642ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1) 1737c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1738d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley#define SETUP_PHY_ATTRIBUTE_RW(field) \ 1739d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1, \ 1740d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley !i->f->set_phy_speed, S_IRUGO) 1741d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley 1742acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong#define SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(field, func) \ 1743acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1, \ 1744acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong !i->f->func, S_IRUGO) 1745acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong 174665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_PORT_ATTRIBUTE(field) \ 174765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1) 174865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 174965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_OPTIONAL_PHY_ATTRIBUTE(field, func) \ 175042ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func) 1751dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley 175265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_PHY_ATTRIBUTE_WRONLY(field) \ 1753fe3b5bfe73ace420709f0cfb198b0ffc704bd38bDarrick J. Wong SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, 1) 175407ba3a954714da10cbd3f6249d93ac2c1df72c4fChristoph Hellwig 175565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley#define SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(field, func) \ 1756fe3b5bfe73ace420709f0cfb198b0ffc704bd38bDarrick J. Wong SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, i->f->func) 1757dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley 175842ab03609cca4ef5079e248296f015650c626899James Bottomley#define SETUP_END_DEV_ATTRIBUTE(field) \ 175942ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1) 1760c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 176179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley#define SETUP_EXPANDER_ATTRIBUTE(field) \ 176279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_TEMPLATE(expander_attrs, expander_##field, S_IRUGO, 1) 176379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 1764c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1765eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_attach_transport - instantiate SAS transport template 1766c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @ft: SAS transport class function template 1767c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1768c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstruct scsi_transport_template * 1769c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigsas_attach_transport(struct sas_function_template *ft) 1770c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1771c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i; 1772c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int count; 1773c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 177424669f75a3231fa37444977c92d1f4838bec1233Jes Sorensen i = kzalloc(sizeof(struct sas_internal), GFP_KERNEL); 1775c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (!i) 1776c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return NULL; 1777c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1778e02f3f59225d8c3b2a0ad0dc941a09865e27da61Christoph Hellwig i->t.user_scan = sas_user_scan; 1779c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1780c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.attrs = &i->host_attrs[0]; 1781c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.class = &sas_host_class.class; 1782c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_attrs.ac.match = sas_host_match; 1783c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->t.host_attrs); 1784c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->t.host_size = sizeof(struct sas_host_attrs); 1785c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1786c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.class = &sas_phy_class.class; 1787c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.attrs = &i->phy_attrs[0]; 1788c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attr_cont.ac.match = sas_phy_match; 1789c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->phy_attr_cont); 1790c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 179165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attr_cont.ac.class = &sas_port_class.class; 179265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attr_cont.ac.attrs = &i->port_attrs[0]; 179365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attr_cont.ac.match = sas_port_match; 179465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_container_register(&i->port_attr_cont); 179565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 1796c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.class = &sas_rphy_class.class; 1797c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0]; 1798c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attr_cont.ac.match = sas_rphy_match; 1799c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_register(&i->rphy_attr_cont); 1800c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 180142ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attr_cont.ac.class = &sas_end_dev_class.class; 180242ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attr_cont.ac.attrs = &i->end_dev_attrs[0]; 180342ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attr_cont.ac.match = sas_end_dev_match; 180442ab03609cca4ef5079e248296f015650c626899James Bottomley transport_container_register(&i->end_dev_attr_cont); 180542ab03609cca4ef5079e248296f015650c626899James Bottomley 180679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attr_cont.ac.class = &sas_expander_class.class; 180779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attr_cont.ac.attrs = &i->expander_attrs[0]; 180879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attr_cont.ac.match = sas_expander_match; 180979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_container_register(&i->expander_attr_cont); 181079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 1811c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->f = ft; 1812c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1813c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 181465c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(initiator_port_protocols); 181565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(target_port_protocols); 181665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(device_type); 181765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(sas_address); 181865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(phy_identifier); 181965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley //SETUP_PHY_ATTRIBUTE(port_identifier); 182065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(negotiated_linkrate); 182165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(minimum_linkrate_hw); 1822d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley SETUP_PHY_ATTRIBUTE_RW(minimum_linkrate); 182365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(maximum_linkrate_hw); 1824d24e1eeb3a16e4944288c2f3bf082e1513f4b425James Bottomley SETUP_PHY_ATTRIBUTE_RW(maximum_linkrate); 182565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 182665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(invalid_dword_count); 182765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(running_disparity_error_count); 182865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(loss_of_dword_sync_count); 182965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PHY_ATTRIBUTE(phy_reset_problem_count); 183065c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(link_reset, phy_reset); 183165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(hard_reset, phy_reset); 1832acbf167d4ad8c27f9743a4b539d51ae9535bf21cDarrick J. Wong SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(enable, phy_enable); 1833c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->phy_attrs[count] = NULL; 1834c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1835c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig count = 0; 183665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley SETUP_PORT_ATTRIBUTE(num_phys); 183765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley i->port_attrs[count] = NULL; 183865c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley 183965c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley count = 0; 1840c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols); 1841c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols); 1842c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_device_type); 1843c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_sas_address); 1844c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier); 1845dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_enclosure_identifier, 1846dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley get_enclosure_identifier); 1847dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_bay_identifier, 1848dd9fbb52134693f1394a928c05d5f3cd3fdaf6e0James Bottomley get_bay_identifier); 1849c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig i->rphy_attrs[count] = NULL; 1850c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 185142ab03609cca4ef5079e248296f015650c626899James Bottomley count = 0; 185242ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_ready_led_meaning); 185342ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_I_T_nexus_loss_timeout); 185442ab03609cca4ef5079e248296f015650c626899James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout); 18550f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_tlr_supported); 18560f88009d5cfae890bd3466126d1622ad4f16b798James Bottomley SETUP_END_DEV_ATTRIBUTE(end_dev_tlr_enabled); 185742ab03609cca4ef5079e248296f015650c626899James Bottomley i->end_dev_attrs[count] = NULL; 185842ab03609cca4ef5079e248296f015650c626899James Bottomley 185979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley count = 0; 186079cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(vendor_id); 186179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(product_id); 186279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(product_rev); 186379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(component_vendor_id); 186479cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(component_id); 186579cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(component_revision_id); 186679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley SETUP_EXPANDER_ATTRIBUTE(level); 186779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley i->expander_attrs[count] = NULL; 186879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley 1869c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return &i->t; 1870c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1871c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_attach_transport); 1872c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1873c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig/** 1874eb44820c28bc9a042e1157b41c677018a8fdfc74Rob Landley * sas_release_transport - release SAS transport template instance 1875c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig * @t: transport template instance 1876c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig */ 1877c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigvoid sas_release_transport(struct scsi_transport_template *t) 1878c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1879c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig struct sas_internal *i = to_sas_internal(t); 1880c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1881c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->t.host_attrs); 1882c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->phy_attr_cont); 188365c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_container_unregister(&i->port_attr_cont); 1884c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_container_unregister(&i->rphy_attr_cont); 1885db82f8410ed7546792358964aa5f8dafff1c70a2James Bottomley transport_container_unregister(&i->end_dev_attr_cont); 188679cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_container_unregister(&i->expander_attr_cont); 1887c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1888c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig kfree(i); 1889c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1890c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigEXPORT_SYMBOL(sas_release_transport); 1891c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1892c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic __init int sas_transport_init(void) 1893c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1894c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig int error; 1895c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1896c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = transport_class_register(&sas_host_class); 1897c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1898c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out; 1899c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig error = transport_class_register(&sas_phy_class); 1900c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1901c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out_unregister_transport; 190265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley error = transport_class_register(&sas_port_class); 1903c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig if (error) 1904c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig goto out_unregister_phy; 190565c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley error = transport_class_register(&sas_rphy_class); 190665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley if (error) 190765c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley goto out_unregister_port; 190842ab03609cca4ef5079e248296f015650c626899James Bottomley error = transport_class_register(&sas_end_dev_class); 190942ab03609cca4ef5079e248296f015650c626899James Bottomley if (error) 191042ab03609cca4ef5079e248296f015650c626899James Bottomley goto out_unregister_rphy; 191179cb1819e231f811211133a09a5382cb89d7ec67James Bottomley error = transport_class_register(&sas_expander_class); 191279cb1819e231f811211133a09a5382cb89d7ec67James Bottomley if (error) 191379cb1819e231f811211133a09a5382cb89d7ec67James Bottomley goto out_unregister_end_dev; 1914c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1915c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return 0; 1916c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 191779cb1819e231f811211133a09a5382cb89d7ec67James Bottomley out_unregister_end_dev: 191879cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_class_unregister(&sas_end_dev_class); 191942ab03609cca4ef5079e248296f015650c626899James Bottomley out_unregister_rphy: 192042ab03609cca4ef5079e248296f015650c626899James Bottomley transport_class_unregister(&sas_rphy_class); 192165c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley out_unregister_port: 192265c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_class_unregister(&sas_port_class); 1923c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out_unregister_phy: 1924c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_phy_class); 1925c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out_unregister_transport: 1926c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_host_class); 1927c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig out: 1928c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig return error; 1929c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1930c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1931c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1932c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigstatic void __exit sas_transport_exit(void) 1933c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig{ 1934c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_host_class); 1935c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_phy_class); 193665c92b09acf0218b64f1c7ba4fdabeb8b732c876James Bottomley transport_class_unregister(&sas_port_class); 1937c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig transport_class_unregister(&sas_rphy_class); 193842ab03609cca4ef5079e248296f015650c626899James Bottomley transport_class_unregister(&sas_end_dev_class); 193979cb1819e231f811211133a09a5382cb89d7ec67James Bottomley transport_class_unregister(&sas_expander_class); 1940c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig} 1941c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1942c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_AUTHOR("Christoph Hellwig"); 194386b9c4c16a1589d05959af2d96d52a4352c6306eAlexis BruemmerMODULE_DESCRIPTION("SAS Transport Attributes"); 1944c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph HellwigMODULE_LICENSE("GPL"); 1945c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwig 1946c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigmodule_init(sas_transport_init); 1947c7ebbbce366c02e5657ac6b6059933fe0353b175Christoph Hellwigmodule_exit(sas_transport_exit); 1948