162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * SAS host prototypes and structures header file 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2005 Adaptec, Inc. All rights reserved. 662306a36Sopenharmony_ci * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#ifndef _LIBSAS_H_ 1062306a36Sopenharmony_ci#define _LIBSAS_H_ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <linux/timer.h> 1462306a36Sopenharmony_ci#include <linux/pci.h> 1562306a36Sopenharmony_ci#include <scsi/sas.h> 1662306a36Sopenharmony_ci#include <linux/libata.h> 1762306a36Sopenharmony_ci#include <linux/list.h> 1862306a36Sopenharmony_ci#include <scsi/scsi_device.h> 1962306a36Sopenharmony_ci#include <scsi/scsi_cmnd.h> 2062306a36Sopenharmony_ci#include <scsi/scsi_transport_sas.h> 2162306a36Sopenharmony_ci#include <linux/scatterlist.h> 2262306a36Sopenharmony_ci#include <linux/slab.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistruct block_device; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cienum sas_phy_role { 2762306a36Sopenharmony_ci PHY_ROLE_NONE = 0, 2862306a36Sopenharmony_ci PHY_ROLE_TARGET = 0x40, 2962306a36Sopenharmony_ci PHY_ROLE_INITIATOR = 0x80, 3062306a36Sopenharmony_ci}; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* The events are mnemonically described in sas_dump.c 3362306a36Sopenharmony_ci * so when updating/adding events here, please also 3462306a36Sopenharmony_ci * update the other file too. 3562306a36Sopenharmony_ci */ 3662306a36Sopenharmony_cienum port_event { 3762306a36Sopenharmony_ci PORTE_BYTES_DMAED = 0U, 3862306a36Sopenharmony_ci PORTE_BROADCAST_RCVD, 3962306a36Sopenharmony_ci PORTE_LINK_RESET_ERR, 4062306a36Sopenharmony_ci PORTE_TIMER_EVENT, 4162306a36Sopenharmony_ci PORTE_HARD_RESET, 4262306a36Sopenharmony_ci PORT_NUM_EVENTS, 4362306a36Sopenharmony_ci}; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cienum phy_event { 4662306a36Sopenharmony_ci PHYE_LOSS_OF_SIGNAL = 0U, 4762306a36Sopenharmony_ci PHYE_OOB_DONE, 4862306a36Sopenharmony_ci PHYE_OOB_ERROR, 4962306a36Sopenharmony_ci PHYE_SPINUP_HOLD, /* hot plug SATA, no COMWAKE sent */ 5062306a36Sopenharmony_ci PHYE_RESUME_TIMEOUT, 5162306a36Sopenharmony_ci PHYE_SHUTDOWN, 5262306a36Sopenharmony_ci PHY_NUM_EVENTS, 5362306a36Sopenharmony_ci}; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cienum discover_event { 5662306a36Sopenharmony_ci DISCE_DISCOVER_DOMAIN = 0U, 5762306a36Sopenharmony_ci DISCE_REVALIDATE_DOMAIN, 5862306a36Sopenharmony_ci DISCE_SUSPEND, 5962306a36Sopenharmony_ci DISCE_RESUME, 6062306a36Sopenharmony_ci DISC_NUM_EVENTS, 6162306a36Sopenharmony_ci}; 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/* ---------- Expander Devices ---------- */ 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci#define to_dom_device(_obj) container_of(_obj, struct domain_device, dev_obj) 6662306a36Sopenharmony_ci#define to_dev_attr(_attr) container_of(_attr, struct domain_dev_attribute,\ 6762306a36Sopenharmony_ci attr) 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cienum routing_attribute { 7062306a36Sopenharmony_ci DIRECT_ROUTING, 7162306a36Sopenharmony_ci SUBTRACTIVE_ROUTING, 7262306a36Sopenharmony_ci TABLE_ROUTING, 7362306a36Sopenharmony_ci}; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_cienum ex_phy_state { 7662306a36Sopenharmony_ci PHY_EMPTY, 7762306a36Sopenharmony_ci PHY_VACANT, 7862306a36Sopenharmony_ci PHY_NOT_PRESENT, 7962306a36Sopenharmony_ci PHY_DEVICE_DISCOVERED 8062306a36Sopenharmony_ci}; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistruct ex_phy { 8362306a36Sopenharmony_ci int phy_id; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci enum ex_phy_state phy_state; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci enum sas_device_type attached_dev_type; 8862306a36Sopenharmony_ci enum sas_linkrate linkrate; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci u8 attached_sata_host:1; 9162306a36Sopenharmony_ci u8 attached_sata_dev:1; 9262306a36Sopenharmony_ci u8 attached_sata_ps:1; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci enum sas_protocol attached_tproto; 9562306a36Sopenharmony_ci enum sas_protocol attached_iproto; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci u8 attached_sas_addr[SAS_ADDR_SIZE]; 9862306a36Sopenharmony_ci u8 attached_phy_id; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci int phy_change_count; 10162306a36Sopenharmony_ci enum routing_attribute routing_attr; 10262306a36Sopenharmony_ci u8 virtual:1; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci int last_da_index; 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci struct sas_phy *phy; 10762306a36Sopenharmony_ci struct sas_port *port; 10862306a36Sopenharmony_ci}; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistruct expander_device { 11162306a36Sopenharmony_ci struct list_head children; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci int ex_change_count; 11462306a36Sopenharmony_ci u16 max_route_indexes; 11562306a36Sopenharmony_ci u8 num_phys; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci u8 t2t_supp:1; 11862306a36Sopenharmony_ci u8 configuring:1; 11962306a36Sopenharmony_ci u8 conf_route_table:1; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci u8 enclosure_logical_id[8]; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci struct ex_phy *ex_phy; 12462306a36Sopenharmony_ci struct sas_port *parent_port; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci struct mutex cmd_mutex; 12762306a36Sopenharmony_ci}; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci/* ---------- SATA device ---------- */ 13062306a36Sopenharmony_ci#define ATA_RESP_FIS_SIZE 24 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistruct sata_device { 13362306a36Sopenharmony_ci unsigned int class; 13462306a36Sopenharmony_ci u8 port_no; /* port number, if this is a PM (Port) */ 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci struct ata_port *ap; 13762306a36Sopenharmony_ci struct ata_host *ata_host; 13862306a36Sopenharmony_ci struct smp_rps_resp rps_resp ____cacheline_aligned; /* report_phy_sata_resp */ 13962306a36Sopenharmony_ci u8 fis[ATA_RESP_FIS_SIZE]; 14062306a36Sopenharmony_ci}; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistruct ssp_device { 14362306a36Sopenharmony_ci struct list_head eh_list_node; /* pending a user requested eh action */ 14462306a36Sopenharmony_ci struct scsi_lun reset_lun; 14562306a36Sopenharmony_ci}; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cienum { 14862306a36Sopenharmony_ci SAS_DEV_GONE, 14962306a36Sopenharmony_ci SAS_DEV_FOUND, /* device notified to lldd */ 15062306a36Sopenharmony_ci SAS_DEV_DESTROY, 15162306a36Sopenharmony_ci SAS_DEV_EH_PENDING, 15262306a36Sopenharmony_ci SAS_DEV_LU_RESET, 15362306a36Sopenharmony_ci SAS_DEV_RESET, 15462306a36Sopenharmony_ci}; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cistruct domain_device { 15762306a36Sopenharmony_ci spinlock_t done_lock; 15862306a36Sopenharmony_ci enum sas_device_type dev_type; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci enum sas_linkrate linkrate; 16162306a36Sopenharmony_ci enum sas_linkrate min_linkrate; 16262306a36Sopenharmony_ci enum sas_linkrate max_linkrate; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci int pathways; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci struct domain_device *parent; 16762306a36Sopenharmony_ci struct list_head siblings; /* devices on the same level */ 16862306a36Sopenharmony_ci struct asd_sas_port *port; /* shortcut to root of the tree */ 16962306a36Sopenharmony_ci struct sas_phy *phy; 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci struct list_head dev_list_node; 17262306a36Sopenharmony_ci struct list_head disco_list_node; /* awaiting probe or destruct */ 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci enum sas_protocol iproto; 17562306a36Sopenharmony_ci enum sas_protocol tproto; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci struct sas_rphy *rphy; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci u8 sas_addr[SAS_ADDR_SIZE]; 18062306a36Sopenharmony_ci u8 hashed_sas_addr[HASHED_SAS_ADDR_SIZE]; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci u8 frame_rcvd[32]; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci union { 18562306a36Sopenharmony_ci struct expander_device ex_dev; 18662306a36Sopenharmony_ci struct sata_device sata_dev; /* STP & directly attached */ 18762306a36Sopenharmony_ci struct ssp_device ssp_dev; 18862306a36Sopenharmony_ci }; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci void *lldd_dev; 19162306a36Sopenharmony_ci unsigned long state; 19262306a36Sopenharmony_ci struct kref kref; 19362306a36Sopenharmony_ci}; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cistruct sas_work { 19662306a36Sopenharmony_ci struct list_head drain_node; 19762306a36Sopenharmony_ci struct work_struct work; 19862306a36Sopenharmony_ci}; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic inline bool dev_is_expander(enum sas_device_type type) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci return type == SAS_EDGE_EXPANDER_DEVICE || 20362306a36Sopenharmony_ci type == SAS_FANOUT_EXPANDER_DEVICE; 20462306a36Sopenharmony_ci} 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_cistatic inline void INIT_SAS_WORK(struct sas_work *sw, void (*fn)(struct work_struct *)) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci INIT_WORK(&sw->work, fn); 20962306a36Sopenharmony_ci INIT_LIST_HEAD(&sw->drain_node); 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistruct sas_discovery_event { 21362306a36Sopenharmony_ci struct sas_work work; 21462306a36Sopenharmony_ci struct asd_sas_port *port; 21562306a36Sopenharmony_ci}; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_cistatic inline struct sas_discovery_event *to_sas_discovery_event(struct work_struct *work) 21862306a36Sopenharmony_ci{ 21962306a36Sopenharmony_ci struct sas_discovery_event *ev = container_of(work, typeof(*ev), work.work); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci return ev; 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistruct sas_discovery { 22562306a36Sopenharmony_ci struct sas_discovery_event disc_work[DISC_NUM_EVENTS]; 22662306a36Sopenharmony_ci unsigned long pending; 22762306a36Sopenharmony_ci u8 fanout_sas_addr[SAS_ADDR_SIZE]; 22862306a36Sopenharmony_ci u8 eeds_a[SAS_ADDR_SIZE]; 22962306a36Sopenharmony_ci u8 eeds_b[SAS_ADDR_SIZE]; 23062306a36Sopenharmony_ci int max_level; 23162306a36Sopenharmony_ci}; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci/* The port struct is Class:RW, driver:RO */ 23462306a36Sopenharmony_cistruct asd_sas_port { 23562306a36Sopenharmony_ci/* private: */ 23662306a36Sopenharmony_ci struct sas_discovery disc; 23762306a36Sopenharmony_ci struct domain_device *port_dev; 23862306a36Sopenharmony_ci spinlock_t dev_list_lock; 23962306a36Sopenharmony_ci struct list_head dev_list; 24062306a36Sopenharmony_ci struct list_head disco_list; 24162306a36Sopenharmony_ci struct list_head destroy_list; 24262306a36Sopenharmony_ci struct list_head sas_port_del_list; 24362306a36Sopenharmony_ci enum sas_linkrate linkrate; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci struct sas_work work; 24662306a36Sopenharmony_ci int suspended; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci/* public: */ 24962306a36Sopenharmony_ci int id; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci u8 sas_addr[SAS_ADDR_SIZE]; 25262306a36Sopenharmony_ci u8 attached_sas_addr[SAS_ADDR_SIZE]; 25362306a36Sopenharmony_ci enum sas_protocol iproto; 25462306a36Sopenharmony_ci enum sas_protocol tproto; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci enum sas_oob_mode oob_mode; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci spinlock_t phy_list_lock; 25962306a36Sopenharmony_ci struct list_head phy_list; 26062306a36Sopenharmony_ci int num_phys; 26162306a36Sopenharmony_ci u32 phy_mask; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci struct sas_ha_struct *ha; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci struct sas_port *port; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci void *lldd_port; /* not touched by the sas class code */ 26862306a36Sopenharmony_ci}; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistruct asd_sas_event { 27162306a36Sopenharmony_ci struct sas_work work; 27262306a36Sopenharmony_ci struct asd_sas_phy *phy; 27362306a36Sopenharmony_ci int event; 27462306a36Sopenharmony_ci}; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_cistatic inline struct asd_sas_event *to_asd_sas_event(struct work_struct *work) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci struct asd_sas_event *ev = container_of(work, typeof(*ev), work.work); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci return ev; 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic inline void INIT_SAS_EVENT(struct asd_sas_event *ev, 28462306a36Sopenharmony_ci void (*fn)(struct work_struct *), 28562306a36Sopenharmony_ci struct asd_sas_phy *phy, int event) 28662306a36Sopenharmony_ci{ 28762306a36Sopenharmony_ci INIT_SAS_WORK(&ev->work, fn); 28862306a36Sopenharmony_ci ev->phy = phy; 28962306a36Sopenharmony_ci ev->event = event; 29062306a36Sopenharmony_ci} 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci#define SAS_PHY_SHUTDOWN_THRES 1024 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci/* The phy pretty much is controlled by the LLDD. 29562306a36Sopenharmony_ci * The class only reads those fields. 29662306a36Sopenharmony_ci */ 29762306a36Sopenharmony_cistruct asd_sas_phy { 29862306a36Sopenharmony_ci/* private: */ 29962306a36Sopenharmony_ci atomic_t event_nr; 30062306a36Sopenharmony_ci int in_shutdown; 30162306a36Sopenharmony_ci int error; 30262306a36Sopenharmony_ci int suspended; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci struct sas_phy *phy; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci/* public: */ 30762306a36Sopenharmony_ci /* The following are class:RO, driver:R/W */ 30862306a36Sopenharmony_ci int enabled; /* must be set */ 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci int id; /* must be set */ 31162306a36Sopenharmony_ci enum sas_protocol iproto; 31262306a36Sopenharmony_ci enum sas_protocol tproto; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci enum sas_phy_role role; 31562306a36Sopenharmony_ci enum sas_oob_mode oob_mode; 31662306a36Sopenharmony_ci enum sas_linkrate linkrate; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci u8 *sas_addr; /* must be set */ 31962306a36Sopenharmony_ci u8 attached_sas_addr[SAS_ADDR_SIZE]; /* class:RO, driver: R/W */ 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci spinlock_t frame_rcvd_lock; 32262306a36Sopenharmony_ci u8 *frame_rcvd; /* must be set */ 32362306a36Sopenharmony_ci int frame_rcvd_size; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci spinlock_t sas_prim_lock; 32662306a36Sopenharmony_ci u32 sas_prim; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci struct list_head port_phy_el; /* driver:RO */ 32962306a36Sopenharmony_ci struct asd_sas_port *port; /* Class:RW, driver: RO */ 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci struct sas_ha_struct *ha; /* may be set; the class sets it anyway */ 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci void *lldd_phy; /* not touched by the sas_class_code */ 33462306a36Sopenharmony_ci}; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_cienum sas_ha_state { 33762306a36Sopenharmony_ci SAS_HA_REGISTERED, 33862306a36Sopenharmony_ci SAS_HA_DRAINING, 33962306a36Sopenharmony_ci SAS_HA_ATA_EH_ACTIVE, 34062306a36Sopenharmony_ci SAS_HA_FROZEN, 34162306a36Sopenharmony_ci SAS_HA_RESUMING, 34262306a36Sopenharmony_ci}; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistruct sas_ha_struct { 34562306a36Sopenharmony_ci/* private: */ 34662306a36Sopenharmony_ci struct list_head defer_q; /* work queued while draining */ 34762306a36Sopenharmony_ci struct mutex drain_mutex; 34862306a36Sopenharmony_ci unsigned long state; 34962306a36Sopenharmony_ci spinlock_t lock; 35062306a36Sopenharmony_ci int eh_active; 35162306a36Sopenharmony_ci wait_queue_head_t eh_wait_q; 35262306a36Sopenharmony_ci struct list_head eh_dev_q; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci struct mutex disco_mutex; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci struct Scsi_Host *shost; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci/* public: */ 35962306a36Sopenharmony_ci char *sas_ha_name; 36062306a36Sopenharmony_ci struct device *dev; /* should be set */ 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci struct workqueue_struct *event_q; 36362306a36Sopenharmony_ci struct workqueue_struct *disco_q; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci u8 *sas_addr; /* must be set */ 36662306a36Sopenharmony_ci u8 hashed_sas_addr[HASHED_SAS_ADDR_SIZE]; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci spinlock_t phy_port_lock; 36962306a36Sopenharmony_ci struct asd_sas_phy **sas_phy; /* array of valid pointers, must be set */ 37062306a36Sopenharmony_ci struct asd_sas_port **sas_port; /* array of valid pointers, must be set */ 37162306a36Sopenharmony_ci int num_phys; /* must be set, gt 0, static */ 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci int strict_wide_ports; /* both sas_addr and attached_sas_addr must match 37462306a36Sopenharmony_ci * their siblings when forming wide ports */ 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci void *lldd_ha; /* not touched by sas class code */ 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci struct list_head eh_done_q; /* complete via scsi_eh_flush_done_q */ 37962306a36Sopenharmony_ci struct list_head eh_ata_q; /* scmds to promote from sas to ata eh */ 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci int event_thres; 38262306a36Sopenharmony_ci}; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci#define SHOST_TO_SAS_HA(_shost) (*(struct sas_ha_struct **)(_shost)->hostdata) 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_cistatic inline struct domain_device * 38762306a36Sopenharmony_cistarget_to_domain_dev(struct scsi_target *starget) { 38862306a36Sopenharmony_ci return starget->hostdata; 38962306a36Sopenharmony_ci} 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_cistatic inline struct domain_device * 39262306a36Sopenharmony_cisdev_to_domain_dev(struct scsi_device *sdev) { 39362306a36Sopenharmony_ci return starget_to_domain_dev(sdev->sdev_target); 39462306a36Sopenharmony_ci} 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_cistatic inline struct ata_device *sas_to_ata_dev(struct domain_device *dev) 39762306a36Sopenharmony_ci{ 39862306a36Sopenharmony_ci return &dev->sata_dev.ap->link.device[0]; 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_cistatic inline struct domain_device * 40262306a36Sopenharmony_cicmd_to_domain_dev(struct scsi_cmnd *cmd) 40362306a36Sopenharmony_ci{ 40462306a36Sopenharmony_ci return sdev_to_domain_dev(cmd->device); 40562306a36Sopenharmony_ci} 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_civoid sas_hash_addr(u8 *hashed, const u8 *sas_addr); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci/* Before calling a notify event, LLDD should use this function 41062306a36Sopenharmony_ci * when the link is severed (possibly from its tasklet). 41162306a36Sopenharmony_ci * The idea is that the Class only reads those, while the LLDD, 41262306a36Sopenharmony_ci * can R/W these (thus avoiding a race). 41362306a36Sopenharmony_ci */ 41462306a36Sopenharmony_cistatic inline void sas_phy_disconnected(struct asd_sas_phy *phy) 41562306a36Sopenharmony_ci{ 41662306a36Sopenharmony_ci phy->oob_mode = OOB_NOT_CONNECTED; 41762306a36Sopenharmony_ci phy->linkrate = SAS_LINK_RATE_UNKNOWN; 41862306a36Sopenharmony_ci} 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_cistatic inline unsigned int to_sas_gpio_od(int device, int bit) 42162306a36Sopenharmony_ci{ 42262306a36Sopenharmony_ci return 3 * device + bit; 42362306a36Sopenharmony_ci} 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_cistatic inline void sas_put_local_phy(struct sas_phy *phy) 42662306a36Sopenharmony_ci{ 42762306a36Sopenharmony_ci put_device(&phy->dev); 42862306a36Sopenharmony_ci} 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci#ifdef CONFIG_SCSI_SAS_HOST_SMP 43162306a36Sopenharmony_ciint try_test_sas_gpio_gp_bit(unsigned int od, u8 *data, u8 index, u8 count); 43262306a36Sopenharmony_ci#else 43362306a36Sopenharmony_cistatic inline int try_test_sas_gpio_gp_bit(unsigned int od, u8 *data, u8 index, u8 count) 43462306a36Sopenharmony_ci{ 43562306a36Sopenharmony_ci return -1; 43662306a36Sopenharmony_ci} 43762306a36Sopenharmony_ci#endif 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci/* ---------- Tasks ---------- */ 44062306a36Sopenharmony_ci/* 44162306a36Sopenharmony_ci service_response | SAS_TASK_COMPLETE | SAS_TASK_UNDELIVERED | 44262306a36Sopenharmony_ci exec_status | | | 44362306a36Sopenharmony_ci ---------------------+---------------------+-----------------------+ 44462306a36Sopenharmony_ci SAM_... | X | | 44562306a36Sopenharmony_ci DEV_NO_RESPONSE | X | X | 44662306a36Sopenharmony_ci INTERRUPTED | X | | 44762306a36Sopenharmony_ci QUEUE_FULL | | X | 44862306a36Sopenharmony_ci DEVICE_UNKNOWN | | X | 44962306a36Sopenharmony_ci SG_ERR | | X | 45062306a36Sopenharmony_ci ---------------------+---------------------+-----------------------+ 45162306a36Sopenharmony_ci */ 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_cienum service_response { 45462306a36Sopenharmony_ci SAS_TASK_COMPLETE, 45562306a36Sopenharmony_ci SAS_TASK_UNDELIVERED = -1, 45662306a36Sopenharmony_ci}; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_cienum exec_status { 45962306a36Sopenharmony_ci /* 46062306a36Sopenharmony_ci * Values 0..0x7f are used to return the SAM_STAT_* codes. To avoid 46162306a36Sopenharmony_ci * 'case value not in enumerated type' compiler warnings every value 46262306a36Sopenharmony_ci * returned through the exec_status enum needs an alias with the SAS_ 46362306a36Sopenharmony_ci * prefix here. 46462306a36Sopenharmony_ci */ 46562306a36Sopenharmony_ci SAS_SAM_STAT_GOOD = SAM_STAT_GOOD, 46662306a36Sopenharmony_ci SAS_SAM_STAT_BUSY = SAM_STAT_BUSY, 46762306a36Sopenharmony_ci SAS_SAM_STAT_TASK_ABORTED = SAM_STAT_TASK_ABORTED, 46862306a36Sopenharmony_ci SAS_SAM_STAT_CHECK_CONDITION = SAM_STAT_CHECK_CONDITION, 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci SAS_DEV_NO_RESPONSE = 0x80, 47162306a36Sopenharmony_ci SAS_DATA_UNDERRUN, 47262306a36Sopenharmony_ci SAS_DATA_OVERRUN, 47362306a36Sopenharmony_ci SAS_INTERRUPTED, 47462306a36Sopenharmony_ci SAS_QUEUE_FULL, 47562306a36Sopenharmony_ci SAS_DEVICE_UNKNOWN, 47662306a36Sopenharmony_ci SAS_OPEN_REJECT, 47762306a36Sopenharmony_ci SAS_OPEN_TO, 47862306a36Sopenharmony_ci SAS_PROTO_RESPONSE, 47962306a36Sopenharmony_ci SAS_PHY_DOWN, 48062306a36Sopenharmony_ci SAS_NAK_R_ERR, 48162306a36Sopenharmony_ci SAS_PENDING, 48262306a36Sopenharmony_ci SAS_ABORTED_TASK, 48362306a36Sopenharmony_ci}; 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci/* When a task finishes with a response, the LLDD examines the 48662306a36Sopenharmony_ci * response: 48762306a36Sopenharmony_ci * - For an ATA task task_status_struct::stat is set to 48862306a36Sopenharmony_ci * SAS_PROTO_RESPONSE, and the task_status_struct::buf is set to the 48962306a36Sopenharmony_ci * contents of struct ata_task_resp. 49062306a36Sopenharmony_ci * - For SSP tasks, if no data is present or status/TMF response 49162306a36Sopenharmony_ci * is valid, task_status_struct::stat is set. If data is present 49262306a36Sopenharmony_ci * (SENSE data), the LLDD copies up to SAS_STATUS_BUF_SIZE, sets 49362306a36Sopenharmony_ci * task_status_struct::buf_valid_size, and task_status_struct::stat is 49462306a36Sopenharmony_ci * set to SAM_CHECK_COND. 49562306a36Sopenharmony_ci * 49662306a36Sopenharmony_ci * "buf" has format SCSI Sense for SSP task, or struct ata_task_resp 49762306a36Sopenharmony_ci * for ATA task. 49862306a36Sopenharmony_ci * 49962306a36Sopenharmony_ci * "frame_len" is the total frame length, which could be more or less 50062306a36Sopenharmony_ci * than actually copied. 50162306a36Sopenharmony_ci * 50262306a36Sopenharmony_ci * Tasks ending with response, always set the residual field. 50362306a36Sopenharmony_ci */ 50462306a36Sopenharmony_cistruct ata_task_resp { 50562306a36Sopenharmony_ci u16 frame_len; 50662306a36Sopenharmony_ci u8 ending_fis[ATA_RESP_FIS_SIZE]; /* dev to host or data-in */ 50762306a36Sopenharmony_ci}; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci#define SAS_STATUS_BUF_SIZE 96 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_cistruct task_status_struct { 51262306a36Sopenharmony_ci enum service_response resp; 51362306a36Sopenharmony_ci enum exec_status stat; 51462306a36Sopenharmony_ci int buf_valid_size; 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci u8 buf[SAS_STATUS_BUF_SIZE]; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci u32 residual; 51962306a36Sopenharmony_ci enum sas_open_rej_reason open_rej_reason; 52062306a36Sopenharmony_ci}; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci/* ATA and ATAPI task queuable to a SAS LLDD. 52362306a36Sopenharmony_ci */ 52462306a36Sopenharmony_cistruct sas_ata_task { 52562306a36Sopenharmony_ci struct host_to_dev_fis fis; 52662306a36Sopenharmony_ci u8 atapi_packet[16]; /* 0 if not ATAPI task */ 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci u8 dma_xfer:1; /* PIO:0 or DMA:1 */ 52962306a36Sopenharmony_ci u8 use_ncq:1; 53062306a36Sopenharmony_ci u8 return_fis_on_success:1; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci u8 device_control_reg_update:1; 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci bool force_phy; 53562306a36Sopenharmony_ci int force_phy_id; 53662306a36Sopenharmony_ci}; 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_ci/* LLDDs rely on these values */ 53962306a36Sopenharmony_cienum sas_internal_abort { 54062306a36Sopenharmony_ci SAS_INTERNAL_ABORT_SINGLE = 0, 54162306a36Sopenharmony_ci SAS_INTERNAL_ABORT_DEV = 1, 54262306a36Sopenharmony_ci}; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_cistruct sas_internal_abort_task { 54562306a36Sopenharmony_ci enum sas_internal_abort type; 54662306a36Sopenharmony_ci unsigned int qid; 54762306a36Sopenharmony_ci u16 tag; 54862306a36Sopenharmony_ci}; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_cistruct sas_smp_task { 55162306a36Sopenharmony_ci struct scatterlist smp_req; 55262306a36Sopenharmony_ci struct scatterlist smp_resp; 55362306a36Sopenharmony_ci}; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_cienum task_attribute { 55662306a36Sopenharmony_ci TASK_ATTR_SIMPLE = 0, 55762306a36Sopenharmony_ci TASK_ATTR_HOQ = 1, 55862306a36Sopenharmony_ci TASK_ATTR_ORDERED= 2, 55962306a36Sopenharmony_ci TASK_ATTR_ACA = 4, 56062306a36Sopenharmony_ci}; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_cistruct sas_ssp_task { 56362306a36Sopenharmony_ci u8 LUN[8]; 56462306a36Sopenharmony_ci enum task_attribute task_attr; 56562306a36Sopenharmony_ci struct scsi_cmnd *cmd; 56662306a36Sopenharmony_ci}; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_cistruct sas_tmf_task { 56962306a36Sopenharmony_ci u8 tmf; 57062306a36Sopenharmony_ci u16 tag_of_task_to_be_managed; 57162306a36Sopenharmony_ci}; 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_cistruct sas_task { 57462306a36Sopenharmony_ci struct domain_device *dev; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci spinlock_t task_state_lock; 57762306a36Sopenharmony_ci unsigned task_state_flags; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci enum sas_protocol task_proto; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci union { 58262306a36Sopenharmony_ci struct sas_ata_task ata_task; 58362306a36Sopenharmony_ci struct sas_smp_task smp_task; 58462306a36Sopenharmony_ci struct sas_ssp_task ssp_task; 58562306a36Sopenharmony_ci struct sas_internal_abort_task abort_task; 58662306a36Sopenharmony_ci }; 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci struct scatterlist *scatter; 58962306a36Sopenharmony_ci int num_scatter; 59062306a36Sopenharmony_ci u32 total_xfer_len; 59162306a36Sopenharmony_ci u8 data_dir:2; /* Use PCI_DMA_... */ 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci struct task_status_struct task_status; 59462306a36Sopenharmony_ci void (*task_done)(struct sas_task *); 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci void *lldd_task; /* for use by LLDDs */ 59762306a36Sopenharmony_ci void *uldd_task; 59862306a36Sopenharmony_ci struct sas_task_slow *slow_task; 59962306a36Sopenharmony_ci struct sas_tmf_task *tmf; 60062306a36Sopenharmony_ci}; 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_cistruct sas_task_slow { 60362306a36Sopenharmony_ci /* standard/extra infrastructure for slow path commands (SMP and 60462306a36Sopenharmony_ci * internal lldd commands 60562306a36Sopenharmony_ci */ 60662306a36Sopenharmony_ci struct timer_list timer; 60762306a36Sopenharmony_ci struct completion completion; 60862306a36Sopenharmony_ci struct sas_task *task; 60962306a36Sopenharmony_ci}; 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci#define SAS_TASK_STATE_PENDING 1 61262306a36Sopenharmony_ci#define SAS_TASK_STATE_DONE 2 61362306a36Sopenharmony_ci#define SAS_TASK_STATE_ABORTED 4 61462306a36Sopenharmony_ci#define SAS_TASK_NEED_DEV_RESET 8 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_cistatic inline bool sas_is_internal_abort(struct sas_task *task) 61762306a36Sopenharmony_ci{ 61862306a36Sopenharmony_ci return task->task_proto == SAS_PROTOCOL_INTERNAL_ABORT; 61962306a36Sopenharmony_ci} 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_cistatic inline struct request *sas_task_find_rq(struct sas_task *task) 62262306a36Sopenharmony_ci{ 62362306a36Sopenharmony_ci struct scsi_cmnd *scmd; 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci if (task->task_proto & SAS_PROTOCOL_STP_ALL) { 62662306a36Sopenharmony_ci struct ata_queued_cmd *qc = task->uldd_task; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci scmd = qc ? qc->scsicmd : NULL; 62962306a36Sopenharmony_ci } else { 63062306a36Sopenharmony_ci scmd = task->uldd_task; 63162306a36Sopenharmony_ci } 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci if (!scmd) 63462306a36Sopenharmony_ci return NULL; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci return scsi_cmd_to_rq(scmd); 63762306a36Sopenharmony_ci} 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_cistruct sas_domain_function_template { 64062306a36Sopenharmony_ci /* The class calls these to notify the LLDD of an event. */ 64162306a36Sopenharmony_ci void (*lldd_port_formed)(struct asd_sas_phy *); 64262306a36Sopenharmony_ci void (*lldd_port_deformed)(struct asd_sas_phy *); 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci /* The class calls these when a device is found or gone. */ 64562306a36Sopenharmony_ci int (*lldd_dev_found)(struct domain_device *); 64662306a36Sopenharmony_ci void (*lldd_dev_gone)(struct domain_device *); 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci int (*lldd_execute_task)(struct sas_task *, gfp_t gfp_flags); 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci /* Task Management Functions. Must be called from process context. */ 65162306a36Sopenharmony_ci int (*lldd_abort_task)(struct sas_task *); 65262306a36Sopenharmony_ci int (*lldd_abort_task_set)(struct domain_device *, u8 *lun); 65362306a36Sopenharmony_ci int (*lldd_clear_task_set)(struct domain_device *, u8 *lun); 65462306a36Sopenharmony_ci int (*lldd_I_T_nexus_reset)(struct domain_device *); 65562306a36Sopenharmony_ci int (*lldd_ata_check_ready)(struct domain_device *); 65662306a36Sopenharmony_ci void (*lldd_ata_set_dmamode)(struct domain_device *); 65762306a36Sopenharmony_ci int (*lldd_lu_reset)(struct domain_device *, u8 *lun); 65862306a36Sopenharmony_ci int (*lldd_query_task)(struct sas_task *); 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci /* Special TMF callbacks */ 66162306a36Sopenharmony_ci void (*lldd_tmf_exec_complete)(struct domain_device *dev); 66262306a36Sopenharmony_ci void (*lldd_tmf_aborted)(struct sas_task *task); 66362306a36Sopenharmony_ci bool (*lldd_abort_timeout)(struct sas_task *task, void *data); 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci /* Port and Adapter management */ 66662306a36Sopenharmony_ci int (*lldd_clear_nexus_port)(struct asd_sas_port *); 66762306a36Sopenharmony_ci int (*lldd_clear_nexus_ha)(struct sas_ha_struct *); 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci /* Phy management */ 67062306a36Sopenharmony_ci int (*lldd_control_phy)(struct asd_sas_phy *, enum phy_func, void *); 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci /* GPIO support */ 67362306a36Sopenharmony_ci int (*lldd_write_gpio)(struct sas_ha_struct *, u8 reg_type, 67462306a36Sopenharmony_ci u8 reg_index, u8 reg_count, u8 *write_data); 67562306a36Sopenharmony_ci}; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ciextern int sas_register_ha(struct sas_ha_struct *); 67862306a36Sopenharmony_ciextern int sas_unregister_ha(struct sas_ha_struct *); 67962306a36Sopenharmony_ciextern void sas_prep_resume_ha(struct sas_ha_struct *sas_ha); 68062306a36Sopenharmony_ciextern void sas_resume_ha(struct sas_ha_struct *sas_ha); 68162306a36Sopenharmony_ciextern void sas_resume_ha_no_sync(struct sas_ha_struct *sas_ha); 68262306a36Sopenharmony_ciextern void sas_suspend_ha(struct sas_ha_struct *sas_ha); 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ciint sas_set_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates); 68562306a36Sopenharmony_ciint sas_phy_reset(struct sas_phy *phy, int hard_reset); 68662306a36Sopenharmony_ciint sas_phy_enable(struct sas_phy *phy, int enable); 68762306a36Sopenharmony_ciextern int sas_queuecommand(struct Scsi_Host *, struct scsi_cmnd *); 68862306a36Sopenharmony_ciextern int sas_target_alloc(struct scsi_target *); 68962306a36Sopenharmony_ciextern int sas_slave_configure(struct scsi_device *); 69062306a36Sopenharmony_ciextern int sas_change_queue_depth(struct scsi_device *, int new_depth); 69162306a36Sopenharmony_ciextern int sas_bios_param(struct scsi_device *, struct block_device *, 69262306a36Sopenharmony_ci sector_t capacity, int *hsc); 69362306a36Sopenharmony_ciint sas_execute_internal_abort_single(struct domain_device *device, 69462306a36Sopenharmony_ci u16 tag, unsigned int qid, 69562306a36Sopenharmony_ci void *data); 69662306a36Sopenharmony_ciint sas_execute_internal_abort_dev(struct domain_device *device, 69762306a36Sopenharmony_ci unsigned int qid, void *data); 69862306a36Sopenharmony_ciextern struct scsi_transport_template * 69962306a36Sopenharmony_cisas_domain_attach_transport(struct sas_domain_function_template *); 70062306a36Sopenharmony_ciextern struct device_attribute dev_attr_phy_event_threshold; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ciint sas_discover_root_expander(struct domain_device *); 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ciint sas_ex_revalidate_domain(struct domain_device *); 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_civoid sas_unregister_domain_devices(struct asd_sas_port *port, int gone); 70762306a36Sopenharmony_civoid sas_init_disc(struct sas_discovery *disc, struct asd_sas_port *); 70862306a36Sopenharmony_civoid sas_discover_event(struct asd_sas_port *, enum discover_event ev); 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ciint sas_discover_end_dev(struct domain_device *); 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_civoid sas_unregister_dev(struct asd_sas_port *port, struct domain_device *); 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_civoid sas_init_dev(struct domain_device *); 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_civoid sas_task_abort(struct sas_task *); 71762306a36Sopenharmony_ciint sas_eh_abort_handler(struct scsi_cmnd *cmd); 71862306a36Sopenharmony_ciint sas_eh_device_reset_handler(struct scsi_cmnd *cmd); 71962306a36Sopenharmony_ciint sas_eh_target_reset_handler(struct scsi_cmnd *cmd); 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ciextern void sas_target_destroy(struct scsi_target *); 72262306a36Sopenharmony_ciextern int sas_slave_alloc(struct scsi_device *); 72362306a36Sopenharmony_ciextern int sas_ioctl(struct scsi_device *sdev, unsigned int cmd, 72462306a36Sopenharmony_ci void __user *arg); 72562306a36Sopenharmony_ciextern int sas_drain_work(struct sas_ha_struct *ha); 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ciextern void sas_ssp_task_response(struct device *dev, struct sas_task *task, 72862306a36Sopenharmony_ci struct ssp_response_iu *iu); 72962306a36Sopenharmony_cistruct sas_phy *sas_get_local_phy(struct domain_device *dev); 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ciint sas_request_addr(struct Scsi_Host *shost, u8 *addr); 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ciint sas_abort_task_set(struct domain_device *dev, u8 *lun); 73462306a36Sopenharmony_ciint sas_clear_task_set(struct domain_device *dev, u8 *lun); 73562306a36Sopenharmony_ciint sas_lu_reset(struct domain_device *dev, u8 *lun); 73662306a36Sopenharmony_ciint sas_query_task(struct sas_task *task, u16 tag); 73762306a36Sopenharmony_ciint sas_abort_task(struct sas_task *task, u16 tag); 73862306a36Sopenharmony_ciint sas_find_attached_phy_id(struct expander_device *ex_dev, 73962306a36Sopenharmony_ci struct domain_device *dev); 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_civoid sas_notify_port_event(struct asd_sas_phy *phy, enum port_event event, 74262306a36Sopenharmony_ci gfp_t gfp_flags); 74362306a36Sopenharmony_civoid sas_notify_phy_event(struct asd_sas_phy *phy, enum phy_event event, 74462306a36Sopenharmony_ci gfp_t gfp_flags); 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci#endif /* _SASLIB_H_ */ 747