2005-09-09 18:22:50 +04:00
# ifndef SCSI_TRANSPORT_SAS_H
# define SCSI_TRANSPORT_SAS_H
# include <linux/transport_class.h>
# include <linux/types.h>
2006-06-28 20:22:50 +04:00
# include <linux/mutex.h>
2007-11-05 22:51:17 +03:00
# include <scsi/sas.h>
2005-09-09 18:22:50 +04:00
struct scsi_transport_template ;
struct sas_rphy ;
2007-07-09 07:52:06 +04:00
struct request ;
2005-09-09 18:22:50 +04:00
enum sas_device_type {
2007-12-29 01:35:17 +03:00
SAS_PHY_UNUSED = 0 ,
SAS_END_DEVICE = 1 ,
SAS_EDGE_EXPANDER_DEVICE = 2 ,
SAS_FANOUT_EXPANDER_DEVICE = 3 ,
2005-09-09 18:22:50 +04:00
} ;
2007-07-16 22:41:04 +04:00
static inline int sas_protocol_ata ( enum sas_protocol proto )
{
return ( ( proto & SAS_PROTOCOL_SATA ) | |
( proto & SAS_PROTOCOL_STP ) ) ? 1 : 0 ;
}
2005-09-09 18:22:50 +04:00
enum sas_linkrate {
2006-09-07 02:36:13 +04:00
/* These Values are defined in the SAS standard */
SAS_LINK_RATE_UNKNOWN = 0 ,
SAS_PHY_DISABLED = 1 ,
SAS_PHY_RESET_PROBLEM = 2 ,
SAS_SATA_SPINUP_HOLD = 3 ,
SAS_SATA_PORT_SELECTOR = 4 ,
SAS_PHY_RESET_IN_PROGRESS = 5 ,
SAS_LINK_RATE_1_5_GBPS = 8 ,
SAS_LINK_RATE_G1 = SAS_LINK_RATE_1_5_GBPS ,
SAS_LINK_RATE_3_0_GBPS = 9 ,
SAS_LINK_RATE_G2 = SAS_LINK_RATE_3_0_GBPS ,
SAS_LINK_RATE_6_0_GBPS = 10 ,
/* These are virtual to the transport class and may never
* be signalled normally since the standard defined field
* is only 4 bits */
SAS_LINK_RATE_FAILED = 0x10 ,
SAS_PHY_VIRTUAL = 0x11 ,
2005-09-09 18:22:50 +04:00
} ;
struct sas_identify {
enum sas_device_type device_type ;
enum sas_protocol initiator_port_protocols ;
enum sas_protocol target_port_protocols ;
u64 sas_address ;
u8 phy_identifier ;
} ;
struct sas_phy {
struct device dev ;
int number ;
2007-01-12 01:14:57 +03:00
int enabled ;
2005-09-19 23:59:42 +04:00
/* phy identification */
2005-09-09 18:22:50 +04:00
struct sas_identify identify ;
2005-09-19 23:59:42 +04:00
/* phy attributes */
2005-09-09 18:22:50 +04:00
enum sas_linkrate negotiated_linkrate ;
enum sas_linkrate minimum_linkrate_hw ;
enum sas_linkrate minimum_linkrate ;
enum sas_linkrate maximum_linkrate_hw ;
enum sas_linkrate maximum_linkrate ;
2005-09-19 23:59:42 +04:00
/* link error statistics */
u32 invalid_dword_count ;
u32 running_disparity_error_count ;
u32 loss_of_dword_sync_count ;
u32 phy_reset_problem_count ;
2006-06-28 20:22:50 +04:00
/* for the list of phys belonging to a port */
struct list_head port_siblings ;
2006-11-08 04:28:55 +03:00
struct work_struct reset_work ;
2005-09-09 18:22:50 +04:00
} ;
# define dev_to_phy(d) \
container_of ( ( d ) , struct sas_phy , dev )
2008-02-22 02:13:36 +03:00
# define transport_class_to_phy(dev) \
dev_to_phy ( ( dev ) - > parent )
2005-09-09 18:22:50 +04:00
# define phy_to_shost(phy) \
dev_to_shost ( ( phy ) - > dev . parent )
2007-07-20 20:10:05 +04:00
struct request_queue ;
2005-09-09 18:22:50 +04:00
struct sas_rphy {
struct device dev ;
struct sas_identify identify ;
struct list_head list ;
2007-07-20 20:10:05 +04:00
struct request_queue * q ;
2005-09-09 18:22:50 +04:00
u32 scsi_target_id ;
} ;
# define dev_to_rphy(d) \
container_of ( ( d ) , struct sas_rphy , dev )
2008-02-22 02:13:36 +03:00
# define transport_class_to_rphy(dev) \
dev_to_rphy ( ( dev ) - > parent )
2005-09-09 18:22:50 +04:00
# define rphy_to_shost(rphy) \
dev_to_shost ( ( rphy ) - > dev . parent )
2006-03-04 18:10:18 +03:00
# define target_to_rphy(targ) \
dev_to_rphy ( ( targ ) - > dev . parent )
struct sas_end_device {
struct sas_rphy rphy ;
/* flags */
unsigned ready_led_meaning : 1 ;
2010-01-18 19:14:51 +03:00
unsigned tlr_supported : 1 ;
unsigned tlr_enabled : 1 ;
2006-03-04 18:10:18 +03:00
/* parameters */
u16 I_T_nexus_loss_timeout ;
u16 initiator_response_timeout ;
} ;
# define rphy_to_end_device(r) \
container_of ( ( r ) , struct sas_end_device , rphy )
2005-09-09 18:22:50 +04:00
2006-03-13 22:50:04 +03:00
struct sas_expander_device {
int level ;
2006-07-02 20:10:18 +04:00
int next_port_id ;
2006-03-13 22:50:04 +03:00
# define SAS_EXPANDER_VENDOR_ID_LEN 8
char vendor_id [ SAS_EXPANDER_VENDOR_ID_LEN + 1 ] ;
# define SAS_EXPANDER_PRODUCT_ID_LEN 16
char product_id [ SAS_EXPANDER_PRODUCT_ID_LEN + 1 ] ;
# define SAS_EXPANDER_PRODUCT_REV_LEN 4
char product_rev [ SAS_EXPANDER_PRODUCT_REV_LEN + 1 ] ;
# define SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN 8
char component_vendor_id [ SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN + 1 ] ;
u16 component_id ;
u8 component_revision_id ;
struct sas_rphy rphy ;
} ;
# define rphy_to_expander_device(r) \
container_of ( ( r ) , struct sas_expander_device , rphy )
2005-09-19 23:59:42 +04:00
2006-06-28 20:22:50 +04:00
struct sas_port {
struct device dev ;
2006-07-02 20:10:18 +04:00
int port_identifier ;
2006-06-28 20:22:50 +04:00
int num_phys ;
2006-07-09 21:38:19 +04:00
/* port flags */
unsigned int is_backlink : 1 ;
2006-06-28 20:22:50 +04:00
/* the other end of the link */
struct sas_rphy * rphy ;
struct mutex phy_list_mutex ;
struct list_head phy_list ;
} ;
# define dev_to_sas_port(d) \
container_of ( ( d ) , struct sas_port , dev )
2008-02-22 02:13:36 +03:00
# define transport_class_to_sas_port(dev) \
dev_to_sas_port ( ( dev ) - > parent )
2006-06-28 20:22:50 +04:00
2006-09-07 04:25:22 +04:00
struct sas_phy_linkrates {
enum sas_linkrate maximum_linkrate ;
enum sas_linkrate minimum_linkrate ;
} ;
2005-09-19 23:59:42 +04:00
/* The functions by which the transport class and the driver communicate */
struct sas_function_template {
int ( * get_linkerrors ) ( struct sas_phy * ) ;
2006-02-16 15:31:47 +03:00
int ( * get_enclosure_identifier ) ( struct sas_rphy * , u64 * ) ;
int ( * get_bay_identifier ) ( struct sas_rphy * ) ;
2005-10-19 22:01:31 +04:00
int ( * phy_reset ) ( struct sas_phy * , int ) ;
2007-01-12 01:14:57 +03:00
int ( * phy_enable ) ( struct sas_phy * , int ) ;
2006-09-07 04:25:22 +04:00
int ( * set_phy_speed ) ( struct sas_phy * , struct sas_phy_linkrates * ) ;
2007-07-09 07:52:06 +04:00
int ( * smp_handler ) ( struct Scsi_Host * , struct sas_rphy * , struct request * ) ;
2005-09-19 23:59:42 +04:00
} ;
2006-06-28 20:22:50 +04:00
void sas_remove_children ( struct device * ) ;
2005-09-09 18:22:50 +04:00
extern void sas_remove_host ( struct Scsi_Host * ) ;
extern struct sas_phy * sas_phy_alloc ( struct device * , int ) ;
extern void sas_phy_free ( struct sas_phy * ) ;
extern int sas_phy_add ( struct sas_phy * ) ;
extern void sas_phy_delete ( struct sas_phy * ) ;
extern int scsi_is_sas_phy ( const struct device * ) ;
2010-01-18 19:14:51 +03:00
unsigned int sas_tlr_supported ( struct scsi_device * ) ;
unsigned int sas_is_tlr_enabled ( struct scsi_device * ) ;
void sas_disable_tlr ( struct scsi_device * ) ;
void sas_enable_tlr ( struct scsi_device * ) ;
2006-06-28 20:22:50 +04:00
extern struct sas_rphy * sas_end_device_alloc ( struct sas_port * ) ;
extern struct sas_rphy * sas_expander_alloc ( struct sas_port * , enum sas_device_type ) ;
2005-09-09 18:22:50 +04:00
void sas_rphy_free ( struct sas_rphy * ) ;
extern int sas_rphy_add ( struct sas_rphy * ) ;
2007-01-27 01:08:43 +03:00
extern void sas_rphy_remove ( struct sas_rphy * ) ;
2005-09-09 18:22:50 +04:00
extern void sas_rphy_delete ( struct sas_rphy * ) ;
extern int scsi_is_sas_rphy ( const struct device * ) ;
2006-06-28 20:22:50 +04:00
struct sas_port * sas_port_alloc ( struct device * , int ) ;
2006-07-02 20:10:18 +04:00
struct sas_port * sas_port_alloc_num ( struct device * ) ;
2006-06-28 20:22:50 +04:00
int sas_port_add ( struct sas_port * ) ;
void sas_port_free ( struct sas_port * ) ;
void sas_port_delete ( struct sas_port * ) ;
void sas_port_add_phy ( struct sas_port * , struct sas_phy * ) ;
void sas_port_delete_phy ( struct sas_port * , struct sas_phy * ) ;
2006-07-09 21:38:19 +04:00
void sas_port_mark_backlink ( struct sas_port * ) ;
2006-06-28 20:22:50 +04:00
int scsi_is_sas_port ( const struct device * ) ;
2005-09-09 18:22:50 +04:00
extern struct scsi_transport_template *
sas_attach_transport ( struct sas_function_template * ) ;
extern void sas_release_transport ( struct scsi_transport_template * ) ;
2006-03-04 18:10:18 +03:00
int sas_read_port_mode_page ( struct scsi_device * ) ;
2005-09-09 18:22:50 +04:00
2006-03-13 22:50:04 +03:00
static inline int
scsi_is_sas_expander_device ( struct device * dev )
{
struct sas_rphy * rphy ;
if ( ! scsi_is_sas_rphy ( dev ) )
return 0 ;
rphy = dev_to_rphy ( dev ) ;
return rphy - > identify . device_type = = SAS_FANOUT_EXPANDER_DEVICE | |
rphy - > identify . device_type = = SAS_EDGE_EXPANDER_DEVICE ;
}
2006-08-25 22:48:18 +04:00
# define scsi_is_sas_phy_local(phy) scsi_is_host_device((phy)->dev.parent)
2005-09-09 18:22:50 +04:00
# endif /* SCSI_TRANSPORT_SAS_H */