2006-08-29 09:22:51 -05:00
/*
* Serial Attached SCSI ( SAS ) class internal header file
*
* Copyright ( C ) 2005 Adaptec , Inc . All rights reserved .
* Copyright ( C ) 2005 Luben Tuikov < luben_tuikov @ adaptec . com >
*
* This file is licensed under GPLv2 .
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation ; either version 2 of the
* License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307
* USA
*
*/
# ifndef _SAS_INTERNAL_H_
# define _SAS_INTERNAL_H_
# include <scsi/scsi.h>
# include <scsi/scsi_host.h>
# include <scsi/scsi_transport_sas.h>
# include <scsi/libsas.h>
2012-01-28 17:24:40 -08:00
# include <scsi/sas_ata.h>
2006-08-29 09:22:51 -05:00
# define sas_printk(fmt, ...) printk(KERN_NOTICE "sas: " fmt, ## __VA_ARGS__)
2011-01-23 08:19:00 -06:00
# define SAS_DPRINTK(fmt, ...) printk(KERN_DEBUG "sas: " fmt, ## __VA_ARGS__)
2006-08-29 09:22:51 -05:00
2007-01-30 01:18:58 -08:00
# define TO_SAS_TASK(_scsi_cmd) ((void *)(_scsi_cmd)->host_scribble)
# define ASSIGN_SAS_TASK(_sc, _t) do { (_sc)->host_scribble = (void *) _t; } while (0)
2011-12-20 01:03:48 -08:00
struct sas_phy_data {
/* let reset be performed in sas_queue_work() context */
struct sas_phy * phy ;
struct mutex event_lock ;
int hard_reset ;
int reset_result ;
2012-03-09 11:00:06 -08:00
struct sas_work reset_work ;
2011-12-04 00:06:57 -08:00
int enable ;
int enable_result ;
2012-03-09 11:00:06 -08:00
struct sas_work enable_work ;
2011-12-20 01:03:48 -08:00
} ;
2006-08-29 09:22:51 -05:00
void sas_scsi_recover_host ( struct Scsi_Host * shost ) ;
int sas_show_class ( enum sas_class class , char * buf ) ;
2007-11-05 11:51:17 -08:00
int sas_show_proto ( enum sas_protocol proto , char * buf ) ;
2006-09-06 17:36:13 -05:00
int sas_show_linkrate ( enum sas_linkrate linkrate , char * buf ) ;
2006-08-29 09:22:51 -05:00
int sas_show_oob_mode ( enum sas_oob_mode oob_mode , char * buf ) ;
int sas_register_phys ( struct sas_ha_struct * sas_ha ) ;
void sas_unregister_phys ( struct sas_ha_struct * sas_ha ) ;
int sas_register_ports ( struct sas_ha_struct * sas_ha ) ;
void sas_unregister_ports ( struct sas_ha_struct * sas_ha ) ;
int sas_init_events ( struct sas_ha_struct * sas_ha ) ;
2011-11-17 17:59:51 -08:00
void sas_disable_revalidation ( struct sas_ha_struct * ha ) ;
void sas_enable_revalidation ( struct sas_ha_struct * ha ) ;
2012-01-12 11:47:24 -08:00
void __sas_drain_work ( struct sas_ha_struct * ha ) ;
2006-08-29 09:22:51 -05:00
2011-05-24 13:17:53 -07:00
void sas_deform_port ( struct asd_sas_phy * phy , int gone ) ;
2006-08-29 09:22:51 -05:00
2006-11-22 14:57:56 +00:00
void sas_porte_bytes_dmaed ( struct work_struct * work ) ;
void sas_porte_broadcast_rcvd ( struct work_struct * work ) ;
void sas_porte_link_reset_err ( struct work_struct * work ) ;
void sas_porte_timer_event ( struct work_struct * work ) ;
void sas_porte_hard_reset ( struct work_struct * work ) ;
2017-06-14 13:52:43 +02:00
int sas_queue_work ( struct sas_ha_struct * ha , struct sas_work * sw ) ;
2006-08-29 09:22:51 -05:00
int sas_notify_lldd_dev_found ( struct domain_device * ) ;
void sas_notify_lldd_dev_gone ( struct domain_device * ) ;
2017-08-25 17:37:41 +02:00
void sas_smp_handler ( struct bsg_job * job , struct Scsi_Host * shost ,
struct sas_rphy * rphy ) ;
2006-08-29 09:22:51 -05:00
int sas_smp_phy_control ( struct domain_device * dev , int phy_id ,
2006-09-06 19:28:07 -05:00
enum phy_func phy_func , struct sas_phy_linkrates * ) ;
2006-08-29 09:22:51 -05:00
int sas_smp_get_phy_events ( struct sas_phy * phy ) ;
2017-06-14 13:52:43 +02:00
int sas_notify_phy_event ( struct asd_sas_phy * phy , enum phy_event event ) ;
2011-12-21 21:33:17 -08:00
void sas_device_set_phy ( struct domain_device * dev , struct sas_port * port ) ;
2006-08-29 09:22:51 -05:00
struct domain_device * sas_find_dev_by_rphy ( struct sas_rphy * rphy ) ;
2011-12-02 16:07:01 -08:00
struct domain_device * sas_ex_to_ata ( struct domain_device * ex_dev , int phy_id ) ;
2012-01-12 17:57:35 -08:00
int sas_ex_phy_discover ( struct domain_device * dev , int single ) ;
int sas_get_report_phy_sata ( struct domain_device * dev , int phy_id ,
struct smp_resp * rps_resp ) ;
2012-01-11 13:13:44 -08:00
int sas_try_ata_reset ( struct asd_sas_phy * phy ) ;
2006-11-22 14:57:56 +00:00
void sas_hae_reset ( struct work_struct * work ) ;
2006-08-29 09:22:51 -05:00
2011-11-17 17:59:47 -08:00
void sas_free_device ( struct kref * kref ) ;
2007-12-28 16:35:17 -06:00
# ifdef CONFIG_SCSI_SAS_HOST_SMP
2017-08-25 17:37:41 +02:00
extern void sas_smp_host_handler ( struct bsg_job * job , struct Scsi_Host * shost ) ;
2007-12-28 16:35:17 -06:00
# else
2017-08-25 17:37:41 +02:00
static inline void sas_smp_host_handler ( struct bsg_job * job ,
struct Scsi_Host * shost )
2007-12-28 16:35:17 -06:00
{
shost_printk ( KERN_ERR , shost ,
" Cannot send SMP to a sas host (not enabled in CONFIG) \n " ) ;
2017-08-25 17:37:41 +02:00
bsg_job_done ( job , - EINVAL , 0 ) ;
2007-12-28 16:35:17 -06:00
}
# endif
2012-01-18 20:47:01 -08:00
static inline void sas_fail_probe ( struct domain_device * dev , const char * func , int err )
{
SAS_DPRINTK ( " %s: for %s device %16llx returned %d \n " ,
func , dev - > parent ? " exp-attached " :
" direct-attached " ,
SAS_ADDR ( dev - > sas_addr ) , err ) ;
sas_unregister_dev ( dev - > port , dev ) ;
}
2006-08-29 09:22:51 -05:00
static inline void sas_fill_in_rphy ( struct domain_device * dev ,
struct sas_rphy * rphy )
{
rphy - > identify . sas_address = SAS_ADDR ( dev - > sas_addr ) ;
rphy - > identify . initiator_port_protocols = dev - > iproto ;
rphy - > identify . target_port_protocols = dev - > tproto ;
switch ( dev - > dev_type ) {
2013-05-07 14:44:06 -07:00
case SAS_SATA_DEV :
2006-08-29 09:22:51 -05:00
/* FIXME: need sata device type */
2013-05-07 14:44:06 -07:00
case SAS_END_DEVICE :
case SAS_SATA_PENDING :
2006-08-29 09:22:51 -05:00
rphy - > identify . device_type = SAS_END_DEVICE ;
break ;
2013-05-07 14:44:06 -07:00
case SAS_EDGE_EXPANDER_DEVICE :
2006-08-29 09:22:51 -05:00
rphy - > identify . device_type = SAS_EDGE_EXPANDER_DEVICE ;
break ;
2013-05-07 14:44:06 -07:00
case SAS_FANOUT_EXPANDER_DEVICE :
2006-08-29 09:22:51 -05:00
rphy - > identify . device_type = SAS_FANOUT_EXPANDER_DEVICE ;
break ;
default :
rphy - > identify . device_type = SAS_PHY_UNUSED ;
break ;
}
}
2012-01-28 17:24:40 -08:00
static inline void sas_phy_set_target ( struct asd_sas_phy * p , struct domain_device * dev )
{
struct sas_phy * phy = p - > phy ;
if ( dev ) {
if ( dev_is_sata ( dev ) )
phy - > identify . device_type = SAS_END_DEVICE ;
else
phy - > identify . device_type = dev - > dev_type ;
phy - > identify . target_port_protocols = dev - > tproto ;
} else {
phy - > identify . device_type = SAS_PHY_UNUSED ;
phy - > identify . target_port_protocols = 0 ;
}
}
2006-08-29 09:22:51 -05:00
static inline void sas_add_parent_port ( struct domain_device * dev , int phy_id )
{
struct expander_device * ex = & dev - > ex_dev ;
struct ex_phy * ex_phy = & ex - > ex_phy [ phy_id ] ;
if ( ! ex - > parent_port ) {
ex - > parent_port = sas_port_alloc ( & dev - > rphy - > dev , phy_id ) ;
/* FIXME: error handling */
BUG_ON ( ! ex - > parent_port ) ;
BUG_ON ( sas_port_add ( ex - > parent_port ) ) ;
sas_port_mark_backlink ( ex - > parent_port ) ;
}
sas_port_add_phy ( ex - > parent_port , ex_phy - > phy ) ;
}
2011-11-17 17:59:47 -08:00
static inline struct domain_device * sas_alloc_device ( void )
{
struct domain_device * dev = kzalloc ( sizeof ( * dev ) , GFP_KERNEL ) ;
if ( dev ) {
INIT_LIST_HEAD ( & dev - > siblings ) ;
INIT_LIST_HEAD ( & dev - > dev_list_node ) ;
2011-11-17 17:59:51 -08:00
INIT_LIST_HEAD ( & dev - > disco_list_node ) ;
2011-11-17 17:59:47 -08:00
kref_init ( & dev - > kref ) ;
2011-11-28 11:29:20 -08:00
spin_lock_init ( & dev - > done_lock ) ;
2011-11-17 17:59:47 -08:00
}
return dev ;
}
static inline void sas_put_device ( struct domain_device * dev )
{
kref_put ( & dev - > kref , sas_free_device ) ;
}
2006-08-29 09:22:51 -05:00
# endif /* _SAS_INTERNAL_H_ */