brintos

brintos / linux-shallow public Read only

0
0
Text · 52.0 KiB · 4e33f16 Raw
1954 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2005-2006 Dell Inc.4 *5 * Serial Attached SCSI (SAS) transport class.6 *7 * The SAS transport class contains common code to deal with SAS HBAs,8 * an aproximated representation of SAS topologies in the driver model,9 * and various sysfs attributes to expose these topologies and management10 * interfaces to userspace.11 *12 * In addition to the basic SCSI core objects this transport class13 * introduces two additional intermediate objects:  The SAS PHY14 * as represented by struct sas_phy defines an "outgoing" PHY on15 * a SAS HBA or Expander, and the SAS remote PHY represented by16 * struct sas_rphy defines an "incoming" PHY on a SAS Expander or17 * end device.  Note that this is purely a software concept, the18 * underlying hardware for a PHY and a remote PHY is the exactly19 * the same.20 *21 * There is no concept of a SAS port in this code, users can see22 * what PHYs form a wide port based on the port_identifier attribute,23 * which is the same for all PHYs in a port.24 */25 26#include <linux/init.h>27#include <linux/module.h>28#include <linux/jiffies.h>29#include <linux/err.h>30#include <linux/slab.h>31#include <linux/string.h>32#include <linux/blkdev.h>33#include <linux/bsg.h>34 35#include <scsi/scsi.h>36#include <scsi/scsi_cmnd.h>37#include <scsi/scsi_device.h>38#include <scsi/scsi_host.h>39#include <scsi/scsi_transport.h>40#include <scsi/scsi_transport_sas.h>41 42#include "scsi_sas_internal.h"43struct sas_host_attrs {44	struct list_head rphy_list;45	struct mutex lock;46	struct request_queue *q;47	u32 next_target_id;48	u32 next_expander_id;49	int next_port_id;50};51#define to_sas_host_attrs(host)	((struct sas_host_attrs *)(host)->shost_data)52 53 54/*55 * Hack to allow attributes of the same name in different objects.56 */57#define SAS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \58	struct device_attribute dev_attr_##_prefix##_##_name = \59	__ATTR(_name,_mode,_show,_store)60 61 62/*63 * Pretty printing helpers64 */65 66#define sas_bitfield_name_match(title, table)			\67static ssize_t							\68get_sas_##title##_names(u32 table_key, char *buf)		\69{								\70	char *prefix = "";					\71	ssize_t len = 0;					\72	int i;							\73								\74	for (i = 0; i < ARRAY_SIZE(table); i++) {		\75		if (table[i].value & table_key) {		\76			len += sprintf(buf + len, "%s%s",	\77				prefix, table[i].name);		\78			prefix = ", ";				\79		}						\80	}							\81	len += sprintf(buf + len, "\n");			\82	return len;						\83}84 85#define sas_bitfield_name_set(title, table)			\86static ssize_t							\87set_sas_##title##_names(u32 *table_key, const char *buf)	\88{								\89	ssize_t len = 0;					\90	int i;							\91								\92	for (i = 0; i < ARRAY_SIZE(table); i++) {		\93		len = strlen(table[i].name);			\94		if (strncmp(buf, table[i].name, len) == 0 &&	\95		    (buf[len] == '\n' || buf[len] == '\0')) {	\96			*table_key = table[i].value;		\97			return 0;				\98		}						\99	}							\100	return -EINVAL;						\101}102 103#define sas_bitfield_name_search(title, table)			\104static ssize_t							\105get_sas_##title##_names(u32 table_key, char *buf)		\106{								\107	ssize_t len = 0;					\108	int i;							\109								\110	for (i = 0; i < ARRAY_SIZE(table); i++) {		\111		if (table[i].value == table_key) {		\112			len += sprintf(buf + len, "%s",		\113				table[i].name);			\114			break;					\115		}						\116	}							\117	len += sprintf(buf + len, "\n");			\118	return len;						\119}120 121static struct {122	u32		value;123	char		*name;124} sas_device_type_names[] = {125	{ SAS_PHY_UNUSED,		"unused" },126	{ SAS_END_DEVICE,		"end device" },127	{ SAS_EDGE_EXPANDER_DEVICE,	"edge expander" },128	{ SAS_FANOUT_EXPANDER_DEVICE,	"fanout expander" },129};130sas_bitfield_name_search(device_type, sas_device_type_names)131 132 133static struct {134	u32		value;135	char		*name;136} sas_protocol_names[] = {137	{ SAS_PROTOCOL_SATA,		"sata" },138	{ SAS_PROTOCOL_SMP,		"smp" },139	{ SAS_PROTOCOL_STP,		"stp" },140	{ SAS_PROTOCOL_SSP,		"ssp" },141};142sas_bitfield_name_match(protocol, sas_protocol_names)143 144static struct {145	u32		value;146	char		*name;147} sas_linkspeed_names[] = {148	{ SAS_LINK_RATE_UNKNOWN,	"Unknown" },149	{ SAS_PHY_DISABLED,		"Phy disabled" },150	{ SAS_LINK_RATE_FAILED,		"Link Rate failed" },151	{ SAS_SATA_SPINUP_HOLD,		"Spin-up hold" },152	{ SAS_LINK_RATE_1_5_GBPS,	"1.5 Gbit" },153	{ SAS_LINK_RATE_3_0_GBPS,	"3.0 Gbit" },154	{ SAS_LINK_RATE_6_0_GBPS,	"6.0 Gbit" },155	{ SAS_LINK_RATE_12_0_GBPS,	"12.0 Gbit" },156	{ SAS_LINK_RATE_22_5_GBPS,	"22.5 Gbit" },157};158sas_bitfield_name_search(linkspeed, sas_linkspeed_names)159sas_bitfield_name_set(linkspeed, sas_linkspeed_names)160 161static struct sas_end_device *sas_sdev_to_rdev(struct scsi_device *sdev)162{163	struct sas_rphy *rphy = target_to_rphy(sdev->sdev_target);164	struct sas_end_device *rdev;165 166	BUG_ON(rphy->identify.device_type != SAS_END_DEVICE);167 168	rdev = rphy_to_end_device(rphy);169	return rdev;170}171 172static int sas_smp_dispatch(struct bsg_job *job)173{174	struct Scsi_Host *shost = dev_to_shost(job->dev);175	struct sas_rphy *rphy = NULL;176 177	if (!scsi_is_host_device(job->dev))178		rphy = dev_to_rphy(job->dev);179 180	if (!job->reply_payload.payload_len) {181		dev_warn(job->dev, "space for a smp response is missing\n");182		bsg_job_done(job, -EINVAL, 0);183		return 0;184	}185 186	to_sas_internal(shost->transportt)->f->smp_handler(job, shost, rphy);187	return 0;188}189 190static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)191{192	struct request_queue *q;193 194	if (!to_sas_internal(shost->transportt)->f->smp_handler) {195		printk("%s can't handle SMP requests\n", shost->hostt->name);196		return 0;197	}198 199	if (rphy) {200		q = bsg_setup_queue(&rphy->dev, dev_name(&rphy->dev), NULL,201				sas_smp_dispatch, NULL, 0);202		if (IS_ERR(q))203			return PTR_ERR(q);204		rphy->q = q;205	} else {206		char name[20];207 208		snprintf(name, sizeof(name), "sas_host%d", shost->host_no);209		q = bsg_setup_queue(&shost->shost_gendev, name, NULL,210				sas_smp_dispatch, NULL, 0);211		if (IS_ERR(q))212			return PTR_ERR(q);213		to_sas_host_attrs(shost)->q = q;214	}215 216	return 0;217}218 219/*220 * SAS host attributes221 */222 223static int sas_host_setup(struct transport_container *tc, struct device *dev,224			  struct device *cdev)225{226	struct Scsi_Host *shost = dev_to_shost(dev);227	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);228	struct device *dma_dev = shost->dma_dev;229 230	INIT_LIST_HEAD(&sas_host->rphy_list);231	mutex_init(&sas_host->lock);232	sas_host->next_target_id = 0;233	sas_host->next_expander_id = 0;234	sas_host->next_port_id = 0;235 236	if (sas_bsg_initialize(shost, NULL))237		dev_printk(KERN_ERR, dev, "fail to a bsg device %d\n",238			   shost->host_no);239 240	if (dma_dev->dma_mask) {241		shost->opt_sectors = min_t(unsigned int, shost->max_sectors,242				dma_opt_mapping_size(dma_dev) >> SECTOR_SHIFT);243	}244 245	return 0;246}247 248static int sas_host_remove(struct transport_container *tc, struct device *dev,249			   struct device *cdev)250{251	struct Scsi_Host *shost = dev_to_shost(dev);252	struct request_queue *q = to_sas_host_attrs(shost)->q;253 254	bsg_remove_queue(q);255	return 0;256}257 258static DECLARE_TRANSPORT_CLASS(sas_host_class,259		"sas_host", sas_host_setup, sas_host_remove, NULL);260 261static int sas_host_match(struct attribute_container *cont,262			    struct device *dev)263{264	struct Scsi_Host *shost;265	struct sas_internal *i;266 267	if (!scsi_is_host_device(dev))268		return 0;269	shost = dev_to_shost(dev);270 271	if (!shost->transportt)272		return 0;273	if (shost->transportt->host_attrs.ac.class !=274			&sas_host_class.class)275		return 0;276 277	i = to_sas_internal(shost->transportt);278	return &i->t.host_attrs.ac == cont;279}280 281static int do_sas_phy_delete(struct device *dev, void *data)282{283	int pass = (int)(unsigned long)data;284 285	if (pass == 0 && scsi_is_sas_port(dev))286		sas_port_delete(dev_to_sas_port(dev));287	else if (pass == 1 && scsi_is_sas_phy(dev))288		sas_phy_delete(dev_to_phy(dev));289	return 0;290}291 292/**293 * sas_remove_children  -  tear down a devices SAS data structures294 * @dev:	device belonging to the sas object295 *296 * Removes all SAS PHYs and remote PHYs for a given object297 */298void sas_remove_children(struct device *dev)299{300	device_for_each_child(dev, (void *)0, do_sas_phy_delete);301	device_for_each_child(dev, (void *)1, do_sas_phy_delete);302}303EXPORT_SYMBOL(sas_remove_children);304 305/**306 * sas_remove_host  -  tear down a Scsi_Host's SAS data structures307 * @shost:	Scsi Host that is torn down308 *309 * Removes all SAS PHYs and remote PHYs for a given Scsi_Host and remove the310 * Scsi_Host as well.311 *312 * Note: Do not call scsi_remove_host() on the Scsi_Host any more, as it is313 * already removed.314 */315void sas_remove_host(struct Scsi_Host *shost)316{317	sas_remove_children(&shost->shost_gendev);318	scsi_remove_host(shost);319}320EXPORT_SYMBOL(sas_remove_host);321 322/**323 * sas_get_address - return the SAS address of the device324 * @sdev: scsi device325 *326 * Returns the SAS address of the scsi device327 */328u64 sas_get_address(struct scsi_device *sdev)329{330	struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);331 332	return rdev->rphy.identify.sas_address;333}334EXPORT_SYMBOL(sas_get_address);335 336/**337 * sas_tlr_supported - checking TLR bit in vpd 0x90338 * @sdev: scsi device struct339 *340 * Check Transport Layer Retries are supported or not.341 * If vpd page 0x90 is present, TRL is supported.342 *343 */344unsigned int345sas_tlr_supported(struct scsi_device *sdev)346{347	const int vpd_len = 32;348	struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);349	char *buffer = kzalloc(vpd_len, GFP_KERNEL);350	int ret = 0;351 352	if (!buffer)353		goto out;354 355	if (scsi_get_vpd_page(sdev, 0x90, buffer, vpd_len))356		goto out;357 358	/*359	 * Magic numbers: the VPD Protocol page (0x90)360	 * has a 4 byte header and then one entry per device port361	 * the TLR bit is at offset 8 on each port entry362	 * if we take the first port, that's at total offset 12363	 */364	ret = buffer[12] & 0x01;365 366 out:367	kfree(buffer);368	rdev->tlr_supported = ret;369	return ret;370 371}372EXPORT_SYMBOL_GPL(sas_tlr_supported);373 374/**375 * sas_disable_tlr - setting TLR flags376 * @sdev: scsi device struct377 *378 * Seting tlr_enabled flag to 0.379 *380 */381void382sas_disable_tlr(struct scsi_device *sdev)383{384	struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);385 386	rdev->tlr_enabled = 0;387}388EXPORT_SYMBOL_GPL(sas_disable_tlr);389 390/**391 * sas_enable_tlr - setting TLR flags392 * @sdev: scsi device struct393 *394 * Seting tlr_enabled flag 1.395 *396 */397void sas_enable_tlr(struct scsi_device *sdev)398{399	unsigned int tlr_supported = 0;400	tlr_supported  = sas_tlr_supported(sdev);401 402	if (tlr_supported) {403		struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);404 405		rdev->tlr_enabled = 1;406	}407 408	return;409}410EXPORT_SYMBOL_GPL(sas_enable_tlr);411 412unsigned int sas_is_tlr_enabled(struct scsi_device *sdev)413{414	struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);415	return rdev->tlr_enabled;416}417EXPORT_SYMBOL_GPL(sas_is_tlr_enabled);418 419/**420 * sas_ata_ncq_prio_supported - Check for ATA NCQ command priority support421 * @sdev: SCSI device422 *423 * Check if an ATA device supports NCQ priority using VPD page 89h (ATA424 * Information). Since this VPD page is implemented only for ATA devices,425 * this function always returns false for SCSI devices.426 */427bool sas_ata_ncq_prio_supported(struct scsi_device *sdev)428{429	struct scsi_vpd *vpd;430	bool ncq_prio_supported = false;431 432	rcu_read_lock();433	vpd = rcu_dereference(sdev->vpd_pg89);434	if (vpd && vpd->len >= 214)435		ncq_prio_supported = (vpd->data[213] >> 4) & 1;436	rcu_read_unlock();437 438	return ncq_prio_supported;439}440EXPORT_SYMBOL_GPL(sas_ata_ncq_prio_supported);441 442/*443 * SAS Phy attributes444 */445 446#define sas_phy_show_simple(field, name, format_string, cast)		\447static ssize_t								\448show_sas_phy_##name(struct device *dev, 				\449		    struct device_attribute *attr, char *buf)		\450{									\451	struct sas_phy *phy = transport_class_to_phy(dev);		\452									\453	return snprintf(buf, 20, format_string, cast phy->field);	\454}455 456#define sas_phy_simple_attr(field, name, format_string, type)		\457	sas_phy_show_simple(field, name, format_string, (type))	\458static DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)459 460#define sas_phy_show_protocol(field, name)				\461static ssize_t								\462show_sas_phy_##name(struct device *dev, 				\463		    struct device_attribute *attr, char *buf)		\464{									\465	struct sas_phy *phy = transport_class_to_phy(dev);		\466									\467	if (!phy->field)						\468		return snprintf(buf, 20, "none\n");			\469	return get_sas_protocol_names(phy->field, buf);		\470}471 472#define sas_phy_protocol_attr(field, name)				\473	sas_phy_show_protocol(field, name)				\474static DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)475 476#define sas_phy_show_linkspeed(field)					\477static ssize_t								\478show_sas_phy_##field(struct device *dev, 				\479		     struct device_attribute *attr, char *buf)		\480{									\481	struct sas_phy *phy = transport_class_to_phy(dev);		\482									\483	return get_sas_linkspeed_names(phy->field, buf);		\484}485 486/* Fudge to tell if we're minimum or maximum */487#define sas_phy_store_linkspeed(field)					\488static ssize_t								\489store_sas_phy_##field(struct device *dev, 				\490		      struct device_attribute *attr, 			\491		      const char *buf,	size_t count)			\492{									\493	struct sas_phy *phy = transport_class_to_phy(dev);		\494	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);	\495	struct sas_internal *i = to_sas_internal(shost->transportt);	\496	u32 value;							\497	struct sas_phy_linkrates rates = {0};				\498	int error;							\499									\500	error = set_sas_linkspeed_names(&value, buf);			\501	if (error)							\502		return error;						\503	rates.field = value;						\504	error = i->f->set_phy_speed(phy, &rates);			\505									\506	return error ? error : count;					\507}508 509#define sas_phy_linkspeed_rw_attr(field)				\510	sas_phy_show_linkspeed(field)					\511	sas_phy_store_linkspeed(field)					\512static DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field,		\513	store_sas_phy_##field)514 515#define sas_phy_linkspeed_attr(field)					\516	sas_phy_show_linkspeed(field)					\517static DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)518 519 520#define sas_phy_show_linkerror(field)					\521static ssize_t								\522show_sas_phy_##field(struct device *dev, 				\523		     struct device_attribute *attr, char *buf)		\524{									\525	struct sas_phy *phy = transport_class_to_phy(dev);		\526	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);	\527	struct sas_internal *i = to_sas_internal(shost->transportt);	\528	int error;							\529									\530	error = i->f->get_linkerrors ? i->f->get_linkerrors(phy) : 0;	\531	if (error)							\532		return error;						\533	return snprintf(buf, 20, "%u\n", phy->field);			\534}535 536#define sas_phy_linkerror_attr(field)					\537	sas_phy_show_linkerror(field)					\538static DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)539 540 541static ssize_t542show_sas_device_type(struct device *dev,543		     struct device_attribute *attr, char *buf)544{545	struct sas_phy *phy = transport_class_to_phy(dev);546 547	if (!phy->identify.device_type)548		return snprintf(buf, 20, "none\n");549	return get_sas_device_type_names(phy->identify.device_type, buf);550}551static DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL);552 553static ssize_t do_sas_phy_enable(struct device *dev,554		size_t count, int enable)555{556	struct sas_phy *phy = transport_class_to_phy(dev);557	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);558	struct sas_internal *i = to_sas_internal(shost->transportt);559	int error;560 561	error = i->f->phy_enable(phy, enable);562	if (error)563		return error;564	phy->enabled = enable;565	return count;566};567 568static ssize_t569store_sas_phy_enable(struct device *dev, struct device_attribute *attr,570		     const char *buf, size_t count)571{572	if (count < 1)573		return -EINVAL;574 575	switch (buf[0]) {576	case '0':577		do_sas_phy_enable(dev, count, 0);578		break;579	case '1':580		do_sas_phy_enable(dev, count, 1);581		break;582	default:583		return -EINVAL;584	}585 586	return count;587}588 589static ssize_t590show_sas_phy_enable(struct device *dev, struct device_attribute *attr,591		    char *buf)592{593	struct sas_phy *phy = transport_class_to_phy(dev);594 595	return snprintf(buf, 20, "%d\n", phy->enabled);596}597 598static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, show_sas_phy_enable,599			 store_sas_phy_enable);600 601static ssize_t602do_sas_phy_reset(struct device *dev, size_t count, int hard_reset)603{604	struct sas_phy *phy = transport_class_to_phy(dev);605	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);606	struct sas_internal *i = to_sas_internal(shost->transportt);607	int error;608 609	error = i->f->phy_reset(phy, hard_reset);610	if (error)611		return error;612	phy->enabled = 1;613	return count;614};615 616static ssize_t617store_sas_link_reset(struct device *dev, struct device_attribute *attr,618		     const char *buf, size_t count)619{620	return do_sas_phy_reset(dev, count, 0);621}622static DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset);623 624static ssize_t625store_sas_hard_reset(struct device *dev, struct device_attribute *attr,626		     const char *buf, size_t count)627{628	return do_sas_phy_reset(dev, count, 1);629}630static DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset);631 632sas_phy_protocol_attr(identify.initiator_port_protocols,633		initiator_port_protocols);634sas_phy_protocol_attr(identify.target_port_protocols,635		target_port_protocols);636sas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",637		unsigned long long);638sas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);639sas_phy_linkspeed_attr(negotiated_linkrate);640sas_phy_linkspeed_attr(minimum_linkrate_hw);641sas_phy_linkspeed_rw_attr(minimum_linkrate);642sas_phy_linkspeed_attr(maximum_linkrate_hw);643sas_phy_linkspeed_rw_attr(maximum_linkrate);644sas_phy_linkerror_attr(invalid_dword_count);645sas_phy_linkerror_attr(running_disparity_error_count);646sas_phy_linkerror_attr(loss_of_dword_sync_count);647sas_phy_linkerror_attr(phy_reset_problem_count);648 649static int sas_phy_setup(struct transport_container *tc, struct device *dev,650			 struct device *cdev)651{652	struct sas_phy *phy = dev_to_phy(dev);653	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);654	struct sas_internal *i = to_sas_internal(shost->transportt);655 656	if (i->f->phy_setup)657		i->f->phy_setup(phy);658 659	return 0;660}661 662static DECLARE_TRANSPORT_CLASS(sas_phy_class,663		"sas_phy", sas_phy_setup, NULL, NULL);664 665static int sas_phy_match(struct attribute_container *cont, struct device *dev)666{667	struct Scsi_Host *shost;668	struct sas_internal *i;669 670	if (!scsi_is_sas_phy(dev))671		return 0;672	shost = dev_to_shost(dev->parent);673 674	if (!shost->transportt)675		return 0;676	if (shost->transportt->host_attrs.ac.class !=677			&sas_host_class.class)678		return 0;679 680	i = to_sas_internal(shost->transportt);681	return &i->phy_attr_cont.ac == cont;682}683 684static void sas_phy_release(struct device *dev)685{686	struct sas_phy *phy = dev_to_phy(dev);687	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);688	struct sas_internal *i = to_sas_internal(shost->transportt);689 690	if (i->f->phy_release)691		i->f->phy_release(phy);692	put_device(dev->parent);693	kfree(phy);694}695 696/**697 * sas_phy_alloc  -  allocates and initialize a SAS PHY structure698 * @parent:	Parent device699 * @number:	Phy index700 *701 * Allocates an SAS PHY structure.  It will be added in the device tree702 * below the device specified by @parent, which has to be either a Scsi_Host703 * or sas_rphy.704 *705 * Returns:706 *	SAS PHY allocated or %NULL if the allocation failed.707 */708struct sas_phy *sas_phy_alloc(struct device *parent, int number)709{710	struct Scsi_Host *shost = dev_to_shost(parent);711	struct sas_phy *phy;712 713	phy = kzalloc(sizeof(*phy), GFP_KERNEL);714	if (!phy)715		return NULL;716 717	phy->number = number;718	phy->enabled = 1;719 720	device_initialize(&phy->dev);721	phy->dev.parent = get_device(parent);722	phy->dev.release = sas_phy_release;723	INIT_LIST_HEAD(&phy->port_siblings);724	if (scsi_is_sas_expander_device(parent)) {725		struct sas_rphy *rphy = dev_to_rphy(parent);726		dev_set_name(&phy->dev, "phy-%d:%d:%d", shost->host_no,727			rphy->scsi_target_id, number);728	} else729		dev_set_name(&phy->dev, "phy-%d:%d", shost->host_no, number);730 731	transport_setup_device(&phy->dev);732 733	return phy;734}735EXPORT_SYMBOL(sas_phy_alloc);736 737/**738 * sas_phy_add  -  add a SAS PHY to the device hierarchy739 * @phy:	The PHY to be added740 *741 * Publishes a SAS PHY to the rest of the system.742 */743int sas_phy_add(struct sas_phy *phy)744{745	int error;746 747	error = device_add(&phy->dev);748	if (error)749		return error;750 751	error = transport_add_device(&phy->dev);752	if (error) {753		device_del(&phy->dev);754		return error;755	}756	transport_configure_device(&phy->dev);757 758	return 0;759}760EXPORT_SYMBOL(sas_phy_add);761 762/**763 * sas_phy_free  -  free a SAS PHY764 * @phy:	SAS PHY to free765 *766 * Frees the specified SAS PHY.767 *768 * Note:769 *   This function must only be called on a PHY that has not770 *   successfully been added using sas_phy_add().771 */772void sas_phy_free(struct sas_phy *phy)773{774	transport_destroy_device(&phy->dev);775	put_device(&phy->dev);776}777EXPORT_SYMBOL(sas_phy_free);778 779/**780 * sas_phy_delete  -  remove SAS PHY781 * @phy:	SAS PHY to remove782 *783 * Removes the specified SAS PHY.  If the SAS PHY has an784 * associated remote PHY it is removed before.785 */786void787sas_phy_delete(struct sas_phy *phy)788{789	struct device *dev = &phy->dev;790 791	/* this happens if the phy is still part of a port when deleted */792	BUG_ON(!list_empty(&phy->port_siblings));793 794	transport_remove_device(dev);795	device_del(dev);796	transport_destroy_device(dev);797	put_device(dev);798}799EXPORT_SYMBOL(sas_phy_delete);800 801/**802 * scsi_is_sas_phy  -  check if a struct device represents a SAS PHY803 * @dev:	device to check804 *805 * Returns:806 *	%1 if the device represents a SAS PHY, %0 else807 */808int scsi_is_sas_phy(const struct device *dev)809{810	return dev->release == sas_phy_release;811}812EXPORT_SYMBOL(scsi_is_sas_phy);813 814/*815 * SAS Port attributes816 */817#define sas_port_show_simple(field, name, format_string, cast)		\818static ssize_t								\819show_sas_port_##name(struct device *dev, 				\820		     struct device_attribute *attr, char *buf)		\821{									\822	struct sas_port *port = transport_class_to_sas_port(dev);	\823									\824	return snprintf(buf, 20, format_string, cast port->field);	\825}826 827#define sas_port_simple_attr(field, name, format_string, type)		\828	sas_port_show_simple(field, name, format_string, (type))	\829static DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL)830 831sas_port_simple_attr(num_phys, num_phys, "%d\n", int);832 833static DECLARE_TRANSPORT_CLASS(sas_port_class,834			       "sas_port", NULL, NULL, NULL);835 836static int sas_port_match(struct attribute_container *cont, struct device *dev)837{838	struct Scsi_Host *shost;839	struct sas_internal *i;840 841	if (!scsi_is_sas_port(dev))842		return 0;843	shost = dev_to_shost(dev->parent);844 845	if (!shost->transportt)846		return 0;847	if (shost->transportt->host_attrs.ac.class !=848			&sas_host_class.class)849		return 0;850 851	i = to_sas_internal(shost->transportt);852	return &i->port_attr_cont.ac == cont;853}854 855 856static void sas_port_release(struct device *dev)857{858	struct sas_port *port = dev_to_sas_port(dev);859 860	BUG_ON(!list_empty(&port->phy_list));861 862	put_device(dev->parent);863	kfree(port);864}865 866static void sas_port_create_link(struct sas_port *port,867				 struct sas_phy *phy)868{869	int res;870 871	res = sysfs_create_link(&port->dev.kobj, &phy->dev.kobj,872				dev_name(&phy->dev));873	if (res)874		goto err;875	res = sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port");876	if (res)877		goto err;878	return;879err:880	printk(KERN_ERR "%s: Cannot create port links, err=%d\n",881	       __func__, res);882}883 884static void sas_port_delete_link(struct sas_port *port,885				 struct sas_phy *phy)886{887	sysfs_remove_link(&port->dev.kobj, dev_name(&phy->dev));888	sysfs_remove_link(&phy->dev.kobj, "port");889}890 891/** sas_port_alloc - allocate and initialize a SAS port structure892 *893 * @parent:	parent device894 * @port_id:	port number895 *896 * Allocates a SAS port structure.  It will be added to the device tree897 * below the device specified by @parent which must be either a Scsi_Host898 * or a sas_expander_device.899 *900 * Returns %NULL on error901 */902struct sas_port *sas_port_alloc(struct device *parent, int port_id)903{904	struct Scsi_Host *shost = dev_to_shost(parent);905	struct sas_port *port;906 907	port = kzalloc(sizeof(*port), GFP_KERNEL);908	if (!port)909		return NULL;910 911	port->port_identifier = port_id;912 913	device_initialize(&port->dev);914 915	port->dev.parent = get_device(parent);916	port->dev.release = sas_port_release;917 918	mutex_init(&port->phy_list_mutex);919	INIT_LIST_HEAD(&port->phy_list);920 921	if (scsi_is_sas_expander_device(parent)) {922		struct sas_rphy *rphy = dev_to_rphy(parent);923		dev_set_name(&port->dev, "port-%d:%d:%d", shost->host_no,924			     rphy->scsi_target_id, port->port_identifier);925	} else926		dev_set_name(&port->dev, "port-%d:%d", shost->host_no,927			     port->port_identifier);928 929	transport_setup_device(&port->dev);930 931	return port;932}933EXPORT_SYMBOL(sas_port_alloc);934 935/** sas_port_alloc_num - allocate and initialize a SAS port structure936 *937 * @parent:	parent device938 *939 * Allocates a SAS port structure and a number to go with it.  This940 * interface is really for adapters where the port number has no941 * meansing, so the sas class should manage them.  It will be added to942 * the device tree below the device specified by @parent which must be943 * either a Scsi_Host or a sas_expander_device.944 *945 * Returns %NULL on error946 */947struct sas_port *sas_port_alloc_num(struct device *parent)948{949	int index;950	struct Scsi_Host *shost = dev_to_shost(parent);951	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);952 953	/* FIXME: use idr for this eventually */954	mutex_lock(&sas_host->lock);955	if (scsi_is_sas_expander_device(parent)) {956		struct sas_rphy *rphy = dev_to_rphy(parent);957		struct sas_expander_device *exp = rphy_to_expander_device(rphy);958 959		index = exp->next_port_id++;960	} else961		index = sas_host->next_port_id++;962	mutex_unlock(&sas_host->lock);963	return sas_port_alloc(parent, index);964}965EXPORT_SYMBOL(sas_port_alloc_num);966 967/**968 * sas_port_add - add a SAS port to the device hierarchy969 * @port:	port to be added970 *971 * publishes a port to the rest of the system972 */973int sas_port_add(struct sas_port *port)974{975	int error;976 977	/* No phys should be added until this is made visible */978	BUG_ON(!list_empty(&port->phy_list));979 980	error = device_add(&port->dev);981 982	if (error)983		return error;984 985	transport_add_device(&port->dev);986	transport_configure_device(&port->dev);987 988	return 0;989}990EXPORT_SYMBOL(sas_port_add);991 992/**993 * sas_port_free  -  free a SAS PORT994 * @port:	SAS PORT to free995 *996 * Frees the specified SAS PORT.997 *998 * Note:999 *   This function must only be called on a PORT that has not1000 *   successfully been added using sas_port_add().1001 */1002void sas_port_free(struct sas_port *port)1003{1004	transport_destroy_device(&port->dev);1005	put_device(&port->dev);1006}1007EXPORT_SYMBOL(sas_port_free);1008 1009/**1010 * sas_port_delete  -  remove SAS PORT1011 * @port:	SAS PORT to remove1012 *1013 * Removes the specified SAS PORT.  If the SAS PORT has an1014 * associated phys, unlink them from the port as well.1015 */1016void sas_port_delete(struct sas_port *port)1017{1018	struct device *dev = &port->dev;1019	struct sas_phy *phy, *tmp_phy;1020 1021	if (port->rphy) {1022		sas_rphy_delete(port->rphy);1023		port->rphy = NULL;1024	}1025 1026	mutex_lock(&port->phy_list_mutex);1027	list_for_each_entry_safe(phy, tmp_phy, &port->phy_list,1028				 port_siblings) {1029		sas_port_delete_link(port, phy);1030		list_del_init(&phy->port_siblings);1031	}1032	mutex_unlock(&port->phy_list_mutex);1033 1034	if (port->is_backlink) {1035		struct device *parent = port->dev.parent;1036 1037		sysfs_remove_link(&port->dev.kobj, dev_name(parent));1038		port->is_backlink = 0;1039	}1040 1041	transport_remove_device(dev);1042	device_del(dev);1043	transport_destroy_device(dev);1044	put_device(dev);1045}1046EXPORT_SYMBOL(sas_port_delete);1047 1048/**1049 * scsi_is_sas_port -  check if a struct device represents a SAS port1050 * @dev:	device to check1051 *1052 * Returns:1053 *	%1 if the device represents a SAS Port, %0 else1054 */1055int scsi_is_sas_port(const struct device *dev)1056{1057	return dev->release == sas_port_release;1058}1059EXPORT_SYMBOL(scsi_is_sas_port);1060 1061/**1062 * sas_port_get_phy - try to take a reference on a port member1063 * @port: port to check1064 */1065struct sas_phy *sas_port_get_phy(struct sas_port *port)1066{1067	struct sas_phy *phy;1068 1069	mutex_lock(&port->phy_list_mutex);1070	if (list_empty(&port->phy_list))1071		phy = NULL;1072	else {1073		struct list_head *ent = port->phy_list.next;1074 1075		phy = list_entry(ent, typeof(*phy), port_siblings);1076		get_device(&phy->dev);1077	}1078	mutex_unlock(&port->phy_list_mutex);1079 1080	return phy;1081}1082EXPORT_SYMBOL(sas_port_get_phy);1083 1084/**1085 * sas_port_add_phy - add another phy to a port to form a wide port1086 * @port:	port to add the phy to1087 * @phy:	phy to add1088 *1089 * When a port is initially created, it is empty (has no phys).  All1090 * ports must have at least one phy to operated, and all wide ports1091 * must have at least two.  The current code makes no difference1092 * between ports and wide ports, but the only object that can be1093 * connected to a remote device is a port, so ports must be formed on1094 * all devices with phys if they're connected to anything.1095 */1096void sas_port_add_phy(struct sas_port *port, struct sas_phy *phy)1097{1098	mutex_lock(&port->phy_list_mutex);1099	if (unlikely(!list_empty(&phy->port_siblings))) {1100		/* make sure we're already on this port */1101		struct sas_phy *tmp;1102 1103		list_for_each_entry(tmp, &port->phy_list, port_siblings)1104			if (tmp == phy)1105				break;1106		/* If this trips, you added a phy that was already1107		 * part of a different port */1108		if (unlikely(tmp != phy)) {1109			dev_printk(KERN_ERR, &port->dev, "trying to add phy %s fails: it's already part of another port\n",1110				   dev_name(&phy->dev));1111			BUG();1112		}1113	} else {1114		sas_port_create_link(port, phy);1115		list_add_tail(&phy->port_siblings, &port->phy_list);1116		port->num_phys++;1117	}1118	mutex_unlock(&port->phy_list_mutex);1119}1120EXPORT_SYMBOL(sas_port_add_phy);1121 1122/**1123 * sas_port_delete_phy - remove a phy from a port or wide port1124 * @port:	port to remove the phy from1125 * @phy:	phy to remove1126 *1127 * This operation is used for tearing down ports again.  It must be1128 * done to every port or wide port before calling sas_port_delete.1129 */1130void sas_port_delete_phy(struct sas_port *port, struct sas_phy *phy)1131{1132	mutex_lock(&port->phy_list_mutex);1133	sas_port_delete_link(port, phy);1134	list_del_init(&phy->port_siblings);1135	port->num_phys--;1136	mutex_unlock(&port->phy_list_mutex);1137}1138EXPORT_SYMBOL(sas_port_delete_phy);1139 1140void sas_port_mark_backlink(struct sas_port *port)1141{1142	int res;1143	struct device *parent = port->dev.parent->parent->parent;1144 1145	if (port->is_backlink)1146		return;1147	port->is_backlink = 1;1148	res = sysfs_create_link(&port->dev.kobj, &parent->kobj,1149				dev_name(parent));1150	if (res)1151		goto err;1152	return;1153err:1154	printk(KERN_ERR "%s: Cannot create port backlink, err=%d\n",1155	       __func__, res);1156 1157}1158EXPORT_SYMBOL(sas_port_mark_backlink);1159 1160/*1161 * SAS remote PHY attributes.1162 */1163 1164#define sas_rphy_show_simple(field, name, format_string, cast)		\1165static ssize_t								\1166show_sas_rphy_##name(struct device *dev, 				\1167		     struct device_attribute *attr, char *buf)		\1168{									\1169	struct sas_rphy *rphy = transport_class_to_rphy(dev);		\1170									\1171	return snprintf(buf, 20, format_string, cast rphy->field);	\1172}1173 1174#define sas_rphy_simple_attr(field, name, format_string, type)		\1175	sas_rphy_show_simple(field, name, format_string, (type))	\1176static SAS_DEVICE_ATTR(rphy, name, S_IRUGO, 			\1177		show_sas_rphy_##name, NULL)1178 1179#define sas_rphy_show_protocol(field, name)				\1180static ssize_t								\1181show_sas_rphy_##name(struct device *dev, 				\1182		     struct device_attribute *attr, char *buf)		\1183{									\1184	struct sas_rphy *rphy = transport_class_to_rphy(dev);		\1185									\1186	if (!rphy->field)					\1187		return snprintf(buf, 20, "none\n");			\1188	return get_sas_protocol_names(rphy->field, buf);	\1189}1190 1191#define sas_rphy_protocol_attr(field, name)				\1192	sas_rphy_show_protocol(field, name)				\1193static SAS_DEVICE_ATTR(rphy, name, S_IRUGO,			\1194		show_sas_rphy_##name, NULL)1195 1196static ssize_t1197show_sas_rphy_device_type(struct device *dev,1198			  struct device_attribute *attr, char *buf)1199{1200	struct sas_rphy *rphy = transport_class_to_rphy(dev);1201 1202	if (!rphy->identify.device_type)1203		return snprintf(buf, 20, "none\n");1204	return get_sas_device_type_names(1205			rphy->identify.device_type, buf);1206}1207 1208static SAS_DEVICE_ATTR(rphy, device_type, S_IRUGO,1209		show_sas_rphy_device_type, NULL);1210 1211static ssize_t1212show_sas_rphy_enclosure_identifier(struct device *dev,1213				   struct device_attribute *attr, char *buf)1214{1215	struct sas_rphy *rphy = transport_class_to_rphy(dev);1216	struct sas_phy *phy = dev_to_phy(rphy->dev.parent);1217	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);1218	struct sas_internal *i = to_sas_internal(shost->transportt);1219	u64 identifier;1220	int error;1221 1222	error = i->f->get_enclosure_identifier(rphy, &identifier);1223	if (error)1224		return error;1225	return sprintf(buf, "0x%llx\n", (unsigned long long)identifier);1226}1227 1228static SAS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO,1229		show_sas_rphy_enclosure_identifier, NULL);1230 1231static ssize_t1232show_sas_rphy_bay_identifier(struct device *dev,1233			     struct device_attribute *attr, char *buf)1234{1235	struct sas_rphy *rphy = transport_class_to_rphy(dev);1236	struct sas_phy *phy = dev_to_phy(rphy->dev.parent);1237	struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);1238	struct sas_internal *i = to_sas_internal(shost->transportt);1239	int val;1240 1241	val = i->f->get_bay_identifier(rphy);1242	if (val < 0)1243		return val;1244	return sprintf(buf, "%d\n", val);1245}1246 1247static SAS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO,1248		show_sas_rphy_bay_identifier, NULL);1249 1250sas_rphy_protocol_attr(identify.initiator_port_protocols,1251		initiator_port_protocols);1252sas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols);1253sas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",1254		unsigned long long);1255sas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);1256sas_rphy_simple_attr(scsi_target_id, scsi_target_id, "%d\n", u32);1257 1258/* only need 8 bytes of data plus header (4 or 8) */1259#define BUF_SIZE 641260 1261int sas_read_port_mode_page(struct scsi_device *sdev)1262{1263	char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata;1264	struct sas_end_device *rdev = sas_sdev_to_rdev(sdev);1265	struct scsi_mode_data mode_data;1266	int error;1267 1268	if (!buffer)1269		return -ENOMEM;1270 1271	error = scsi_mode_sense(sdev, 1, 0x19, 0, buffer, BUF_SIZE, 30*HZ, 3,1272				&mode_data, NULL);1273 1274	if (error)1275		goto out;1276 1277	msdata = buffer +  mode_data.header_length +1278		mode_data.block_descriptor_length;1279 1280	if (msdata - buffer > BUF_SIZE - 8)1281		goto out;1282 1283	error = 0;1284 1285	rdev->ready_led_meaning = msdata[2] & 0x10 ? 1 : 0;1286	rdev->I_T_nexus_loss_timeout = (msdata[4] << 8) + msdata[5];1287	rdev->initiator_response_timeout = (msdata[6] << 8) + msdata[7];1288 1289 out:1290	kfree(buffer);1291	return error;1292}1293EXPORT_SYMBOL(sas_read_port_mode_page);1294 1295static DECLARE_TRANSPORT_CLASS(sas_end_dev_class,1296			       "sas_end_device", NULL, NULL, NULL);1297 1298#define sas_end_dev_show_simple(field, name, format_string, cast)	\1299static ssize_t								\1300show_sas_end_dev_##name(struct device *dev, 				\1301			struct device_attribute *attr, char *buf)	\1302{									\1303	struct sas_rphy *rphy = transport_class_to_rphy(dev);		\1304	struct sas_end_device *rdev = rphy_to_end_device(rphy);		\1305									\1306	return snprintf(buf, 20, format_string, cast rdev->field);	\1307}1308 1309#define sas_end_dev_simple_attr(field, name, format_string, type)	\1310	sas_end_dev_show_simple(field, name, format_string, (type))	\1311static SAS_DEVICE_ATTR(end_dev, name, S_IRUGO, 			\1312		show_sas_end_dev_##name, NULL)1313 1314sas_end_dev_simple_attr(ready_led_meaning, ready_led_meaning, "%d\n", int);1315sas_end_dev_simple_attr(I_T_nexus_loss_timeout, I_T_nexus_loss_timeout,1316			"%d\n", int);1317sas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout,1318			"%d\n", int);1319sas_end_dev_simple_attr(tlr_supported, tlr_supported,1320			"%d\n", int);1321sas_end_dev_simple_attr(tlr_enabled, tlr_enabled,1322			"%d\n", int);1323 1324static DECLARE_TRANSPORT_CLASS(sas_expander_class,1325			       "sas_expander", NULL, NULL, NULL);1326 1327#define sas_expander_show_simple(field, name, format_string, cast)	\1328static ssize_t								\1329show_sas_expander_##name(struct device *dev, 				\1330			 struct device_attribute *attr, char *buf)	\1331{									\1332	struct sas_rphy *rphy = transport_class_to_rphy(dev);		\1333	struct sas_expander_device *edev = rphy_to_expander_device(rphy); \1334									\1335	return snprintf(buf, 20, format_string, cast edev->field);	\1336}1337 1338#define sas_expander_simple_attr(field, name, format_string, type)	\1339	sas_expander_show_simple(field, name, format_string, (type))	\1340static SAS_DEVICE_ATTR(expander, name, S_IRUGO, 			\1341		show_sas_expander_##name, NULL)1342 1343sas_expander_simple_attr(vendor_id, vendor_id, "%s\n", char *);1344sas_expander_simple_attr(product_id, product_id, "%s\n", char *);1345sas_expander_simple_attr(product_rev, product_rev, "%s\n", char *);1346sas_expander_simple_attr(component_vendor_id, component_vendor_id,1347			 "%s\n", char *);1348sas_expander_simple_attr(component_id, component_id, "%u\n", unsigned int);1349sas_expander_simple_attr(component_revision_id, component_revision_id, "%u\n",1350			 unsigned int);1351sas_expander_simple_attr(level, level, "%d\n", int);1352 1353static DECLARE_TRANSPORT_CLASS(sas_rphy_class,1354		"sas_device", NULL, NULL, NULL);1355 1356static int sas_rphy_match(struct attribute_container *cont, struct device *dev)1357{1358	struct Scsi_Host *shost;1359	struct sas_internal *i;1360 1361	if (!scsi_is_sas_rphy(dev))1362		return 0;1363	shost = dev_to_shost(dev->parent->parent);1364 1365	if (!shost->transportt)1366		return 0;1367	if (shost->transportt->host_attrs.ac.class !=1368			&sas_host_class.class)1369		return 0;1370 1371	i = to_sas_internal(shost->transportt);1372	return &i->rphy_attr_cont.ac == cont;1373}1374 1375static int sas_end_dev_match(struct attribute_container *cont,1376			     struct device *dev)1377{1378	struct Scsi_Host *shost;1379	struct sas_internal *i;1380	struct sas_rphy *rphy;1381 1382	if (!scsi_is_sas_rphy(dev))1383		return 0;1384	shost = dev_to_shost(dev->parent->parent);1385	rphy = dev_to_rphy(dev);1386 1387	if (!shost->transportt)1388		return 0;1389	if (shost->transportt->host_attrs.ac.class !=1390			&sas_host_class.class)1391		return 0;1392 1393	i = to_sas_internal(shost->transportt);1394	return &i->end_dev_attr_cont.ac == cont &&1395		rphy->identify.device_type == SAS_END_DEVICE;1396}1397 1398static int sas_expander_match(struct attribute_container *cont,1399			      struct device *dev)1400{1401	struct Scsi_Host *shost;1402	struct sas_internal *i;1403	struct sas_rphy *rphy;1404 1405	if (!scsi_is_sas_rphy(dev))1406		return 0;1407	shost = dev_to_shost(dev->parent->parent);1408	rphy = dev_to_rphy(dev);1409 1410	if (!shost->transportt)1411		return 0;1412	if (shost->transportt->host_attrs.ac.class !=1413			&sas_host_class.class)1414		return 0;1415 1416	i = to_sas_internal(shost->transportt);1417	return &i->expander_attr_cont.ac == cont &&1418		(rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||1419		 rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE);1420}1421 1422static void sas_expander_release(struct device *dev)1423{1424	struct sas_rphy *rphy = dev_to_rphy(dev);1425	struct sas_expander_device *edev = rphy_to_expander_device(rphy);1426 1427	put_device(dev->parent);1428	kfree(edev);1429}1430 1431static void sas_end_device_release(struct device *dev)1432{1433	struct sas_rphy *rphy = dev_to_rphy(dev);1434	struct sas_end_device *edev = rphy_to_end_device(rphy);1435 1436	put_device(dev->parent);1437	kfree(edev);1438}1439 1440/**1441 * sas_rphy_initialize - common rphy initialization1442 * @rphy:	rphy to initialise1443 *1444 * Used by both sas_end_device_alloc() and sas_expander_alloc() to1445 * initialise the common rphy component of each.1446 */1447static void sas_rphy_initialize(struct sas_rphy *rphy)1448{1449	INIT_LIST_HEAD(&rphy->list);1450}1451 1452/**1453 * sas_end_device_alloc - allocate an rphy for an end device1454 * @parent: which port1455 *1456 * Allocates an SAS remote PHY structure, connected to @parent.1457 *1458 * Returns:1459 *	SAS PHY allocated or %NULL if the allocation failed.1460 */1461struct sas_rphy *sas_end_device_alloc(struct sas_port *parent)1462{1463	struct Scsi_Host *shost = dev_to_shost(&parent->dev);1464	struct sas_end_device *rdev;1465 1466	rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);1467	if (!rdev) {1468		return NULL;1469	}1470 1471	device_initialize(&rdev->rphy.dev);1472	rdev->rphy.dev.parent = get_device(&parent->dev);1473	rdev->rphy.dev.release = sas_end_device_release;1474	if (scsi_is_sas_expander_device(parent->dev.parent)) {1475		struct sas_rphy *rphy = dev_to_rphy(parent->dev.parent);1476		dev_set_name(&rdev->rphy.dev, "end_device-%d:%d:%d",1477			     shost->host_no, rphy->scsi_target_id,1478			     parent->port_identifier);1479	} else1480		dev_set_name(&rdev->rphy.dev, "end_device-%d:%d",1481			     shost->host_no, parent->port_identifier);1482	rdev->rphy.identify.device_type = SAS_END_DEVICE;1483	sas_rphy_initialize(&rdev->rphy);1484	transport_setup_device(&rdev->rphy.dev);1485 1486	return &rdev->rphy;1487}1488EXPORT_SYMBOL(sas_end_device_alloc);1489 1490/**1491 * sas_expander_alloc - allocate an rphy for an end device1492 * @parent: which port1493 * @type: SAS_EDGE_EXPANDER_DEVICE or SAS_FANOUT_EXPANDER_DEVICE1494 *1495 * Allocates an SAS remote PHY structure, connected to @parent.1496 *1497 * Returns:1498 *	SAS PHY allocated or %NULL if the allocation failed.1499 */1500struct sas_rphy *sas_expander_alloc(struct sas_port *parent,1501				    enum sas_device_type type)1502{1503	struct Scsi_Host *shost = dev_to_shost(&parent->dev);1504	struct sas_expander_device *rdev;1505	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);1506 1507	BUG_ON(type != SAS_EDGE_EXPANDER_DEVICE &&1508	       type != SAS_FANOUT_EXPANDER_DEVICE);1509 1510	rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);1511	if (!rdev) {1512		return NULL;1513	}1514 1515	device_initialize(&rdev->rphy.dev);1516	rdev->rphy.dev.parent = get_device(&parent->dev);1517	rdev->rphy.dev.release = sas_expander_release;1518	mutex_lock(&sas_host->lock);1519	rdev->rphy.scsi_target_id = sas_host->next_expander_id++;1520	mutex_unlock(&sas_host->lock);1521	dev_set_name(&rdev->rphy.dev, "expander-%d:%d",1522		     shost->host_no, rdev->rphy.scsi_target_id);1523	rdev->rphy.identify.device_type = type;1524	sas_rphy_initialize(&rdev->rphy);1525	transport_setup_device(&rdev->rphy.dev);1526 1527	return &rdev->rphy;1528}1529EXPORT_SYMBOL(sas_expander_alloc);1530 1531/**1532 * sas_rphy_add  -  add a SAS remote PHY to the device hierarchy1533 * @rphy:	The remote PHY to be added1534 *1535 * Publishes a SAS remote PHY to the rest of the system.1536 */1537int sas_rphy_add(struct sas_rphy *rphy)1538{1539	struct sas_port *parent = dev_to_sas_port(rphy->dev.parent);1540	struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);1541	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);1542	struct sas_identify *identify = &rphy->identify;1543	int error;1544 1545	if (parent->rphy)1546		return -ENXIO;1547	parent->rphy = rphy;1548 1549	error = device_add(&rphy->dev);1550	if (error)1551		return error;1552	transport_add_device(&rphy->dev);1553	transport_configure_device(&rphy->dev);1554	if (sas_bsg_initialize(shost, rphy))1555		printk("fail to a bsg device %s\n", dev_name(&rphy->dev));1556 1557 1558	mutex_lock(&sas_host->lock);1559	list_add_tail(&rphy->list, &sas_host->rphy_list);1560	if (identify->device_type == SAS_END_DEVICE &&1561	    (identify->target_port_protocols &1562	     (SAS_PROTOCOL_SSP | SAS_PROTOCOL_STP | SAS_PROTOCOL_SATA)))1563		rphy->scsi_target_id = sas_host->next_target_id++;1564	else if (identify->device_type == SAS_END_DEVICE)1565		rphy->scsi_target_id = -1;1566	mutex_unlock(&sas_host->lock);1567 1568	if (identify->device_type == SAS_END_DEVICE &&1569	    rphy->scsi_target_id != -1) {1570		int lun;1571 1572		if (identify->target_port_protocols & SAS_PROTOCOL_SSP)1573			lun = SCAN_WILD_CARD;1574		else1575			lun = 0;1576 1577		scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id, lun,1578				 SCSI_SCAN_INITIAL);1579	}1580 1581	return 0;1582}1583EXPORT_SYMBOL(sas_rphy_add);1584 1585/**1586 * sas_rphy_free  -  free a SAS remote PHY1587 * @rphy: SAS remote PHY to free1588 *1589 * Frees the specified SAS remote PHY.1590 *1591 * Note:1592 *   This function must only be called on a remote1593 *   PHY that has not successfully been added using1594 *   sas_rphy_add() (or has been sas_rphy_remove()'d)1595 */1596void sas_rphy_free(struct sas_rphy *rphy)1597{1598	struct device *dev = &rphy->dev;1599	struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);1600	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);1601 1602	mutex_lock(&sas_host->lock);1603	list_del(&rphy->list);1604	mutex_unlock(&sas_host->lock);1605 1606	transport_destroy_device(dev);1607 1608	put_device(dev);1609}1610EXPORT_SYMBOL(sas_rphy_free);1611 1612/**1613 * sas_rphy_delete  -  remove and free SAS remote PHY1614 * @rphy:	SAS remote PHY to remove and free1615 *1616 * Removes the specified SAS remote PHY and frees it.1617 */1618void1619sas_rphy_delete(struct sas_rphy *rphy)1620{1621	sas_rphy_remove(rphy);1622	sas_rphy_free(rphy);1623}1624EXPORT_SYMBOL(sas_rphy_delete);1625 1626/**1627 * sas_rphy_unlink  -  unlink SAS remote PHY1628 * @rphy:	SAS remote phy to unlink from its parent port1629 *1630 * Removes port reference to an rphy1631 */1632void sas_rphy_unlink(struct sas_rphy *rphy)1633{1634	struct sas_port *parent = dev_to_sas_port(rphy->dev.parent);1635 1636	parent->rphy = NULL;1637}1638EXPORT_SYMBOL(sas_rphy_unlink);1639 1640/**1641 * sas_rphy_remove  -  remove SAS remote PHY1642 * @rphy:	SAS remote phy to remove1643 *1644 * Removes the specified SAS remote PHY.1645 */1646void1647sas_rphy_remove(struct sas_rphy *rphy)1648{1649	struct device *dev = &rphy->dev;1650 1651	switch (rphy->identify.device_type) {1652	case SAS_END_DEVICE:1653		scsi_remove_target(dev);1654		break;1655	case SAS_EDGE_EXPANDER_DEVICE:1656	case SAS_FANOUT_EXPANDER_DEVICE:1657		sas_remove_children(dev);1658		break;1659	default:1660		break;1661	}1662 1663	sas_rphy_unlink(rphy);1664	bsg_remove_queue(rphy->q);1665	transport_remove_device(dev);1666	device_del(dev);1667}1668EXPORT_SYMBOL(sas_rphy_remove);1669 1670/**1671 * scsi_is_sas_rphy  -  check if a struct device represents a SAS remote PHY1672 * @dev:	device to check1673 *1674 * Returns:1675 *	%1 if the device represents a SAS remote PHY, %0 else1676 */1677int scsi_is_sas_rphy(const struct device *dev)1678{1679	return dev->release == sas_end_device_release ||1680		dev->release == sas_expander_release;1681}1682EXPORT_SYMBOL(scsi_is_sas_rphy);1683 1684 1685/*1686 * SCSI scan helper1687 */1688 1689static int sas_user_scan(struct Scsi_Host *shost, uint channel,1690		uint id, u64 lun)1691{1692	struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);1693	struct sas_rphy *rphy;1694 1695	mutex_lock(&sas_host->lock);1696	list_for_each_entry(rphy, &sas_host->rphy_list, list) {1697		if (rphy->identify.device_type != SAS_END_DEVICE ||1698		    rphy->scsi_target_id == -1)1699			continue;1700 1701		if ((channel == SCAN_WILD_CARD || channel == 0) &&1702		    (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) {1703			scsi_scan_target(&rphy->dev, 0, rphy->scsi_target_id,1704					 lun, SCSI_SCAN_MANUAL);1705		}1706	}1707	mutex_unlock(&sas_host->lock);1708 1709	return 0;1710}1711 1712 1713/*1714 * Setup / Teardown code1715 */1716 1717#define SETUP_TEMPLATE(attrb, field, perm, test)			\1718	i->private_##attrb[count] = dev_attr_##field;		\1719	i->private_##attrb[count].attr.mode = perm;			\1720	i->attrb[count] = &i->private_##attrb[count];			\1721	if (test)							\1722		count++1723 1724#define SETUP_TEMPLATE_RW(attrb, field, perm, test, ro_test, ro_perm)	\1725	i->private_##attrb[count] = dev_attr_##field;		\1726	i->private_##attrb[count].attr.mode = perm;			\1727	if (ro_test) {							\1728		i->private_##attrb[count].attr.mode = ro_perm;		\1729		i->private_##attrb[count].store = NULL;			\1730	}								\1731	i->attrb[count] = &i->private_##attrb[count];			\1732	if (test)							\1733		count++1734 1735#define SETUP_RPORT_ATTRIBUTE(field) 					\1736	SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, 1)1737 1738#define SETUP_OPTIONAL_RPORT_ATTRIBUTE(field, func)			\1739	SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, i->f->func)1740 1741#define SETUP_PHY_ATTRIBUTE(field)					\1742	SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1)1743 1744#define SETUP_PHY_ATTRIBUTE_RW(field)					\1745	SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1,	\1746			!i->f->set_phy_speed, S_IRUGO)1747 1748#define SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(field, func)			\1749	SETUP_TEMPLATE_RW(phy_attrs, field, S_IRUGO | S_IWUSR, 1,	\1750			  !i->f->func, S_IRUGO)1751 1752#define SETUP_PORT_ATTRIBUTE(field)					\1753	SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1)1754 1755#define SETUP_OPTIONAL_PHY_ATTRIBUTE(field, func)			\1756	SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func)1757 1758#define SETUP_PHY_ATTRIBUTE_WRONLY(field)				\1759	SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, 1)1760 1761#define SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(field, func)		\1762	SETUP_TEMPLATE(phy_attrs, field, S_IWUSR, i->f->func)1763 1764#define SETUP_END_DEV_ATTRIBUTE(field)					\1765	SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1)1766 1767#define SETUP_EXPANDER_ATTRIBUTE(field)					\1768	SETUP_TEMPLATE(expander_attrs, expander_##field, S_IRUGO, 1)1769 1770/**1771 * sas_attach_transport  -  instantiate SAS transport template1772 * @ft:		SAS transport class function template1773 */1774struct scsi_transport_template *1775sas_attach_transport(struct sas_function_template *ft)1776{1777	struct sas_internal *i;1778	int count;1779 1780	i = kzalloc(sizeof(struct sas_internal), GFP_KERNEL);1781	if (!i)1782		return NULL;1783 1784	i->t.user_scan = sas_user_scan;1785 1786	i->t.host_attrs.ac.attrs = &i->host_attrs[0];1787	i->t.host_attrs.ac.class = &sas_host_class.class;1788	i->t.host_attrs.ac.match = sas_host_match;1789	transport_container_register(&i->t.host_attrs);1790	i->t.host_size = sizeof(struct sas_host_attrs);1791 1792	i->phy_attr_cont.ac.class = &sas_phy_class.class;1793	i->phy_attr_cont.ac.attrs = &i->phy_attrs[0];1794	i->phy_attr_cont.ac.match = sas_phy_match;1795	transport_container_register(&i->phy_attr_cont);1796 1797	i->port_attr_cont.ac.class = &sas_port_class.class;1798	i->port_attr_cont.ac.attrs = &i->port_attrs[0];1799	i->port_attr_cont.ac.match = sas_port_match;1800	transport_container_register(&i->port_attr_cont);1801 1802	i->rphy_attr_cont.ac.class = &sas_rphy_class.class;1803	i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0];1804	i->rphy_attr_cont.ac.match = sas_rphy_match;1805	transport_container_register(&i->rphy_attr_cont);1806 1807	i->end_dev_attr_cont.ac.class = &sas_end_dev_class.class;1808	i->end_dev_attr_cont.ac.attrs = &i->end_dev_attrs[0];1809	i->end_dev_attr_cont.ac.match = sas_end_dev_match;1810	transport_container_register(&i->end_dev_attr_cont);1811 1812	i->expander_attr_cont.ac.class = &sas_expander_class.class;1813	i->expander_attr_cont.ac.attrs = &i->expander_attrs[0];1814	i->expander_attr_cont.ac.match = sas_expander_match;1815	transport_container_register(&i->expander_attr_cont);1816 1817	i->f = ft;1818 1819	count = 0;1820	SETUP_PHY_ATTRIBUTE(initiator_port_protocols);1821	SETUP_PHY_ATTRIBUTE(target_port_protocols);1822	SETUP_PHY_ATTRIBUTE(device_type);1823	SETUP_PHY_ATTRIBUTE(sas_address);1824	SETUP_PHY_ATTRIBUTE(phy_identifier);1825	SETUP_PHY_ATTRIBUTE(negotiated_linkrate);1826	SETUP_PHY_ATTRIBUTE(minimum_linkrate_hw);1827	SETUP_PHY_ATTRIBUTE_RW(minimum_linkrate);1828	SETUP_PHY_ATTRIBUTE(maximum_linkrate_hw);1829	SETUP_PHY_ATTRIBUTE_RW(maximum_linkrate);1830 1831	SETUP_PHY_ATTRIBUTE(invalid_dword_count);1832	SETUP_PHY_ATTRIBUTE(running_disparity_error_count);1833	SETUP_PHY_ATTRIBUTE(loss_of_dword_sync_count);1834	SETUP_PHY_ATTRIBUTE(phy_reset_problem_count);1835	SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(link_reset, phy_reset);1836	SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(hard_reset, phy_reset);1837	SETUP_OPTIONAL_PHY_ATTRIBUTE_RW(enable, phy_enable);1838	i->phy_attrs[count] = NULL;1839 1840	count = 0;1841	SETUP_PORT_ATTRIBUTE(num_phys);1842	i->port_attrs[count] = NULL;1843 1844	count = 0;1845	SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols);1846	SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols);1847	SETUP_RPORT_ATTRIBUTE(rphy_device_type);1848	SETUP_RPORT_ATTRIBUTE(rphy_sas_address);1849	SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier);1850	SETUP_RPORT_ATTRIBUTE(rphy_scsi_target_id);1851	SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_enclosure_identifier,1852				       get_enclosure_identifier);1853	SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_bay_identifier,1854				       get_bay_identifier);1855	i->rphy_attrs[count] = NULL;1856 1857	count = 0;1858	SETUP_END_DEV_ATTRIBUTE(end_dev_ready_led_meaning);1859	SETUP_END_DEV_ATTRIBUTE(end_dev_I_T_nexus_loss_timeout);1860	SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout);1861	SETUP_END_DEV_ATTRIBUTE(end_dev_tlr_supported);1862	SETUP_END_DEV_ATTRIBUTE(end_dev_tlr_enabled);1863	i->end_dev_attrs[count] = NULL;1864 1865	count = 0;1866	SETUP_EXPANDER_ATTRIBUTE(vendor_id);1867	SETUP_EXPANDER_ATTRIBUTE(product_id);1868	SETUP_EXPANDER_ATTRIBUTE(product_rev);1869	SETUP_EXPANDER_ATTRIBUTE(component_vendor_id);1870	SETUP_EXPANDER_ATTRIBUTE(component_id);1871	SETUP_EXPANDER_ATTRIBUTE(component_revision_id);1872	SETUP_EXPANDER_ATTRIBUTE(level);1873	i->expander_attrs[count] = NULL;1874 1875	return &i->t;1876}1877EXPORT_SYMBOL(sas_attach_transport);1878 1879/**1880 * sas_release_transport  -  release SAS transport template instance1881 * @t:		transport template instance1882 */1883void sas_release_transport(struct scsi_transport_template *t)1884{1885	struct sas_internal *i = to_sas_internal(t);1886 1887	transport_container_unregister(&i->t.host_attrs);1888	transport_container_unregister(&i->phy_attr_cont);1889	transport_container_unregister(&i->port_attr_cont);1890	transport_container_unregister(&i->rphy_attr_cont);1891	transport_container_unregister(&i->end_dev_attr_cont);1892	transport_container_unregister(&i->expander_attr_cont);1893 1894	kfree(i);1895}1896EXPORT_SYMBOL(sas_release_transport);1897 1898static __init int sas_transport_init(void)1899{1900	int error;1901 1902	error = transport_class_register(&sas_host_class);1903	if (error)1904		goto out;1905	error = transport_class_register(&sas_phy_class);1906	if (error)1907		goto out_unregister_transport;1908	error = transport_class_register(&sas_port_class);1909	if (error)1910		goto out_unregister_phy;1911	error = transport_class_register(&sas_rphy_class);1912	if (error)1913		goto out_unregister_port;1914	error = transport_class_register(&sas_end_dev_class);1915	if (error)1916		goto out_unregister_rphy;1917	error = transport_class_register(&sas_expander_class);1918	if (error)1919		goto out_unregister_end_dev;1920 1921	return 0;1922 1923 out_unregister_end_dev:1924	transport_class_unregister(&sas_end_dev_class);1925 out_unregister_rphy:1926	transport_class_unregister(&sas_rphy_class);1927 out_unregister_port:1928	transport_class_unregister(&sas_port_class);1929 out_unregister_phy:1930	transport_class_unregister(&sas_phy_class);1931 out_unregister_transport:1932	transport_class_unregister(&sas_host_class);1933 out:1934	return error;1935 1936}1937 1938static void __exit sas_transport_exit(void)1939{1940	transport_class_unregister(&sas_host_class);1941	transport_class_unregister(&sas_phy_class);1942	transport_class_unregister(&sas_port_class);1943	transport_class_unregister(&sas_rphy_class);1944	transport_class_unregister(&sas_end_dev_class);1945	transport_class_unregister(&sas_expander_class);1946}1947 1948MODULE_AUTHOR("Christoph Hellwig");1949MODULE_DESCRIPTION("SAS Transport Attributes");1950MODULE_LICENSE("GPL");1951 1952module_init(sas_transport_init);1953module_exit(sas_transport_exit);1954