18c2ecf20Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci=========
48c2ecf20Sopenharmony_ciSAS Layer
58c2ecf20Sopenharmony_ci=========
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ciThe SAS Layer is a management infrastructure which manages
88c2ecf20Sopenharmony_ciSAS LLDDs.  It sits between SCSI Core and SAS LLDDs.  The
98c2ecf20Sopenharmony_cilayout is as follows: while SCSI Core is concerned with
108c2ecf20Sopenharmony_ciSAM/SPC issues, and a SAS LLDD+sequencer is concerned with
118c2ecf20Sopenharmony_ciphy/OOB/link management, the SAS layer is concerned with:
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci      * SAS Phy/Port/HA event management (LLDD generates,
148c2ecf20Sopenharmony_ci        SAS Layer processes),
158c2ecf20Sopenharmony_ci      * SAS Port management (creation/destruction),
168c2ecf20Sopenharmony_ci      * SAS Domain discovery and revalidation,
178c2ecf20Sopenharmony_ci      * SAS Domain device management,
188c2ecf20Sopenharmony_ci      * SCSI Host registration/unregistration,
198c2ecf20Sopenharmony_ci      * Device registration with SCSI Core (SAS) or libata
208c2ecf20Sopenharmony_ci        (SATA), and
218c2ecf20Sopenharmony_ci      * Expander management and exporting expander control
228c2ecf20Sopenharmony_ci        to user space.
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ciA SAS LLDD is a PCI device driver.  It is concerned with
258c2ecf20Sopenharmony_ciphy/OOB management, and vendor specific tasks and generates
268c2ecf20Sopenharmony_cievents to the SAS layer.
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ciThe SAS Layer does most SAS tasks as outlined in the SAS 1.1
298c2ecf20Sopenharmony_cispec.
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ciThe sas_ha_struct describes the SAS LLDD to the SAS layer.
328c2ecf20Sopenharmony_ciMost of it is used by the SAS Layer but a few fields need to
338c2ecf20Sopenharmony_cibe initialized by the LLDDs.
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ciAfter initializing your hardware, from the probe() function
368c2ecf20Sopenharmony_ciyou call sas_register_ha(). It will register your LLDD with
378c2ecf20Sopenharmony_cithe SCSI subsystem, creating a SCSI host and it will
388c2ecf20Sopenharmony_ciregister your SAS driver with the sysfs SAS tree it creates.
398c2ecf20Sopenharmony_ciIt will then return.  Then you enable your phys to actually
408c2ecf20Sopenharmony_cistart OOB (at which point your driver will start calling the
418c2ecf20Sopenharmony_cinotify_* event callbacks).
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ciStructure descriptions
448c2ecf20Sopenharmony_ci======================
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci``struct sas_phy``
478c2ecf20Sopenharmony_ci------------------
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ciNormally this is statically embedded to your driver's
508c2ecf20Sopenharmony_ciphy structure::
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci    struct my_phy {
538c2ecf20Sopenharmony_ci	    blah;
548c2ecf20Sopenharmony_ci	    struct sas_phy sas_phy;
558c2ecf20Sopenharmony_ci	    bleh;
568c2ecf20Sopenharmony_ci    };
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ciAnd then all the phys are an array of my_phy in your HA
598c2ecf20Sopenharmony_cistruct (shown below).
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ciThen as you go along and initialize your phys you also
628c2ecf20Sopenharmony_ciinitialize the sas_phy struct, along with your own
638c2ecf20Sopenharmony_ciphy structure.
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ciIn general, the phys are managed by the LLDD and the ports
668c2ecf20Sopenharmony_ciare managed by the SAS layer.  So the phys are initialized
678c2ecf20Sopenharmony_ciand updated by the LLDD and the ports are initialized and
688c2ecf20Sopenharmony_ciupdated by the SAS layer.
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ciThere is a scheme where the LLDD can RW certain fields,
718c2ecf20Sopenharmony_ciand the SAS layer can only read such ones, and vice versa.
728c2ecf20Sopenharmony_ciThe idea is to avoid unnecessary locking.
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cienabled
758c2ecf20Sopenharmony_ci    - must be set (0/1)
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ciid
788c2ecf20Sopenharmony_ci    - must be set [0,MAX_PHYS)]
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ciclass, proto, type, role, oob_mode, linkrate
818c2ecf20Sopenharmony_ci    - must be set
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_cioob_mode
848c2ecf20Sopenharmony_ci    - you set this when OOB has finished and then notify
858c2ecf20Sopenharmony_ci      the SAS Layer.
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_cisas_addr
888c2ecf20Sopenharmony_ci    - this normally points to an array holding the sas
898c2ecf20Sopenharmony_ci      address of the phy, possibly somewhere in your my_phy
908c2ecf20Sopenharmony_ci      struct.
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ciattached_sas_addr
938c2ecf20Sopenharmony_ci    - set this when you (LLDD) receive an
948c2ecf20Sopenharmony_ci      IDENTIFY frame or a FIS frame, _before_ notifying the SAS
958c2ecf20Sopenharmony_ci      layer.  The idea is that sometimes the LLDD may want to fake
968c2ecf20Sopenharmony_ci      or provide a different SAS address on that phy/port and this
978c2ecf20Sopenharmony_ci      allows it to do this.  At best you should copy the sas
988c2ecf20Sopenharmony_ci      address from the IDENTIFY frame or maybe generate a SAS
998c2ecf20Sopenharmony_ci      address for SATA directly attached devices.  The Discover
1008c2ecf20Sopenharmony_ci      process may later change this.
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ciframe_rcvd
1038c2ecf20Sopenharmony_ci    - this is where you copy the IDENTIFY/FIS frame
1048c2ecf20Sopenharmony_ci      when you get it; you lock, copy, set frame_rcvd_size and
1058c2ecf20Sopenharmony_ci      unlock the lock, and then call the event.  It is a pointer
1068c2ecf20Sopenharmony_ci      since there's no way to know your hw frame size _exactly_,
1078c2ecf20Sopenharmony_ci      so you define the actual array in your phy struct and let
1088c2ecf20Sopenharmony_ci      this pointer point to it.  You copy the frame from your
1098c2ecf20Sopenharmony_ci      DMAable memory to that area holding the lock.
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_cisas_prim
1128c2ecf20Sopenharmony_ci    - this is where primitives go when they're
1138c2ecf20Sopenharmony_ci      received.  See sas.h. Grab the lock, set the primitive,
1148c2ecf20Sopenharmony_ci      release the lock, notify.
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ciport
1178c2ecf20Sopenharmony_ci    - this points to the sas_port if the phy belongs
1188c2ecf20Sopenharmony_ci      to a port -- the LLDD only reads this. It points to the
1198c2ecf20Sopenharmony_ci      sas_port this phy is part of.  Set by the SAS Layer.
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ciha
1228c2ecf20Sopenharmony_ci    - may be set; the SAS layer sets it anyway.
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_cilldd_phy
1258c2ecf20Sopenharmony_ci    - you should set this to point to your phy so you
1268c2ecf20Sopenharmony_ci      can find your way around faster when the SAS layer calls one
1278c2ecf20Sopenharmony_ci      of your callbacks and passes you a phy.  If the sas_phy is
1288c2ecf20Sopenharmony_ci      embedded you can also use container_of -- whatever you
1298c2ecf20Sopenharmony_ci      prefer.
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci``struct sas_port``
1338c2ecf20Sopenharmony_ci-------------------
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ciThe LLDD doesn't set any fields of this struct -- it only
1368c2ecf20Sopenharmony_cireads them.  They should be self explanatory.
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ciphy_mask is 32 bit, this should be enough for now, as I
1398c2ecf20Sopenharmony_cihaven't heard of a HA having more than 8 phys.
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cilldd_port
1428c2ecf20Sopenharmony_ci    - I haven't found use for that -- maybe other
1438c2ecf20Sopenharmony_ci      LLDD who wish to have internal port representation can make
1448c2ecf20Sopenharmony_ci      use of this.
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci``struct sas_ha_struct``
1478c2ecf20Sopenharmony_ci------------------------
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ciIt normally is statically declared in your own LLDD
1508c2ecf20Sopenharmony_cistructure describing your adapter::
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci    struct my_sas_ha {
1538c2ecf20Sopenharmony_ci	blah;
1548c2ecf20Sopenharmony_ci	struct sas_ha_struct sas_ha;
1558c2ecf20Sopenharmony_ci	struct my_phy phys[MAX_PHYS];
1568c2ecf20Sopenharmony_ci	struct sas_port sas_ports[MAX_PHYS]; /* (1) */
1578c2ecf20Sopenharmony_ci	bleh;
1588c2ecf20Sopenharmony_ci    };
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci    (1) If your LLDD doesn't have its own port representation.
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ciWhat needs to be initialized (sample function given below).
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_cipcidev
1658c2ecf20Sopenharmony_ci^^^^^^
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_cisas_addr
1688c2ecf20Sopenharmony_ci       - since the SAS layer doesn't want to mess with
1698c2ecf20Sopenharmony_ci	 memory allocation, etc, this points to statically
1708c2ecf20Sopenharmony_ci	 allocated array somewhere (say in your host adapter
1718c2ecf20Sopenharmony_ci	 structure) and holds the SAS address of the host
1728c2ecf20Sopenharmony_ci	 adapter as given by you or the manufacturer, etc.
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_cisas_port
1758c2ecf20Sopenharmony_ci^^^^^^^^
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_cisas_phy
1788c2ecf20Sopenharmony_ci      - an array of pointers to structures. (see
1798c2ecf20Sopenharmony_ci	note above on sas_addr).
1808c2ecf20Sopenharmony_ci	These must be set.  See more notes below.
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_cinum_phys
1838c2ecf20Sopenharmony_ci       - the number of phys present in the sas_phy array,
1848c2ecf20Sopenharmony_ci	 and the number of ports present in the sas_port
1858c2ecf20Sopenharmony_ci	 array.  There can be a maximum num_phys ports (one per
1868c2ecf20Sopenharmony_ci	 port) so we drop the num_ports, and only use
1878c2ecf20Sopenharmony_ci	 num_phys.
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ciThe event interface::
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	/* LLDD calls these to notify the class of an event. */
1928c2ecf20Sopenharmony_ci	void sas_notify_port_event(struct sas_phy *, enum port_event);
1938c2ecf20Sopenharmony_ci	void sas_notify_phy_event(struct sas_phy *, enum phy_event);
1948c2ecf20Sopenharmony_ci	void sas_notify_port_event_gfp(struct sas_phy *, enum port_event, gfp_t);
1958c2ecf20Sopenharmony_ci	void sas_notify_phy_event_gfp(struct sas_phy *, enum phy_event, gfp_t);
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ciThe port notification::
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	/* The class calls these to notify the LLDD of an event. */
2008c2ecf20Sopenharmony_ci	void (*lldd_port_formed)(struct sas_phy *);
2018c2ecf20Sopenharmony_ci	void (*lldd_port_deformed)(struct sas_phy *);
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ciIf the LLDD wants notification when a port has been formed
2048c2ecf20Sopenharmony_cior deformed it sets those to a function satisfying the type.
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ciA SAS LLDD should also implement at least one of the Task
2078c2ecf20Sopenharmony_ciManagement Functions (TMFs) described in SAM::
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	/* Task Management Functions. Must be called from process context. */
2108c2ecf20Sopenharmony_ci	int (*lldd_abort_task)(struct sas_task *);
2118c2ecf20Sopenharmony_ci	int (*lldd_abort_task_set)(struct domain_device *, u8 *lun);
2128c2ecf20Sopenharmony_ci	int (*lldd_clear_aca)(struct domain_device *, u8 *lun);
2138c2ecf20Sopenharmony_ci	int (*lldd_clear_task_set)(struct domain_device *, u8 *lun);
2148c2ecf20Sopenharmony_ci	int (*lldd_I_T_nexus_reset)(struct domain_device *);
2158c2ecf20Sopenharmony_ci	int (*lldd_lu_reset)(struct domain_device *, u8 *lun);
2168c2ecf20Sopenharmony_ci	int (*lldd_query_task)(struct sas_task *);
2178c2ecf20Sopenharmony_ci
2188c2ecf20Sopenharmony_ciFor more information please read SAM from T10.org.
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ciPort and Adapter management::
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	/* Port and Adapter management */
2238c2ecf20Sopenharmony_ci	int (*lldd_clear_nexus_port)(struct sas_port *);
2248c2ecf20Sopenharmony_ci	int (*lldd_clear_nexus_ha)(struct sas_ha_struct *);
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ciA SAS LLDD should implement at least one of those.
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ciPhy management::
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci	/* Phy management */
2318c2ecf20Sopenharmony_ci	int (*lldd_control_phy)(struct sas_phy *, enum phy_func);
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_cilldd_ha
2348c2ecf20Sopenharmony_ci    - set this to point to your HA struct. You can also
2358c2ecf20Sopenharmony_ci      use container_of if you embedded it as shown above.
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ciA sample initialization and registration function
2388c2ecf20Sopenharmony_cican look like this (called last thing from probe())
2398c2ecf20Sopenharmony_ci*but* before you enable the phys to do OOB::
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci    static int register_sas_ha(struct my_sas_ha *my_ha)
2428c2ecf20Sopenharmony_ci    {
2438c2ecf20Sopenharmony_ci	    int i;
2448c2ecf20Sopenharmony_ci	    static struct sas_phy   *sas_phys[MAX_PHYS];
2458c2ecf20Sopenharmony_ci	    static struct sas_port  *sas_ports[MAX_PHYS];
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	    my_ha->sas_ha.sas_addr = &my_ha->sas_addr[0];
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	    for (i = 0; i < MAX_PHYS; i++) {
2508c2ecf20Sopenharmony_ci		    sas_phys[i] = &my_ha->phys[i].sas_phy;
2518c2ecf20Sopenharmony_ci		    sas_ports[i] = &my_ha->sas_ports[i];
2528c2ecf20Sopenharmony_ci	    }
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	    my_ha->sas_ha.sas_phy  = sas_phys;
2558c2ecf20Sopenharmony_ci	    my_ha->sas_ha.sas_port = sas_ports;
2568c2ecf20Sopenharmony_ci	    my_ha->sas_ha.num_phys = MAX_PHYS;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	    my_ha->sas_ha.lldd_port_formed = my_port_formed;
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	    my_ha->sas_ha.lldd_dev_found = my_dev_found;
2618c2ecf20Sopenharmony_ci	    my_ha->sas_ha.lldd_dev_gone = my_dev_gone;
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	    my_ha->sas_ha.lldd_execute_task = my_execute_task;
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_ci	    my_ha->sas_ha.lldd_abort_task     = my_abort_task;
2668c2ecf20Sopenharmony_ci	    my_ha->sas_ha.lldd_abort_task_set = my_abort_task_set;
2678c2ecf20Sopenharmony_ci	    my_ha->sas_ha.lldd_clear_aca      = my_clear_aca;
2688c2ecf20Sopenharmony_ci	    my_ha->sas_ha.lldd_clear_task_set = my_clear_task_set;
2698c2ecf20Sopenharmony_ci	    my_ha->sas_ha.lldd_I_T_nexus_reset= NULL; (2)
2708c2ecf20Sopenharmony_ci	    my_ha->sas_ha.lldd_lu_reset       = my_lu_reset;
2718c2ecf20Sopenharmony_ci	    my_ha->sas_ha.lldd_query_task     = my_query_task;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	    my_ha->sas_ha.lldd_clear_nexus_port = my_clear_nexus_port;
2748c2ecf20Sopenharmony_ci	    my_ha->sas_ha.lldd_clear_nexus_ha = my_clear_nexus_ha;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	    my_ha->sas_ha.lldd_control_phy = my_control_phy;
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	    return sas_register_ha(&my_ha->sas_ha);
2798c2ecf20Sopenharmony_ci    }
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci(2) SAS 1.1 does not define I_T Nexus Reset TMF.
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ciEvents
2848c2ecf20Sopenharmony_ci======
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ciEvents are **the only way** a SAS LLDD notifies the SAS layer
2878c2ecf20Sopenharmony_ciof anything.  There is no other method or way a LLDD to tell
2888c2ecf20Sopenharmony_cithe SAS layer of anything happening internally or in the SAS
2898c2ecf20Sopenharmony_cidomain.
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ciPhy events::
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	PHYE_LOSS_OF_SIGNAL, (C)
2948c2ecf20Sopenharmony_ci	PHYE_OOB_DONE,
2958c2ecf20Sopenharmony_ci	PHYE_OOB_ERROR,      (C)
2968c2ecf20Sopenharmony_ci	PHYE_SPINUP_HOLD.
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ciPort events, passed on a _phy_::
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	PORTE_BYTES_DMAED,      (M)
3018c2ecf20Sopenharmony_ci	PORTE_BROADCAST_RCVD,   (E)
3028c2ecf20Sopenharmony_ci	PORTE_LINK_RESET_ERR,   (C)
3038c2ecf20Sopenharmony_ci	PORTE_TIMER_EVENT,      (C)
3048c2ecf20Sopenharmony_ci	PORTE_HARD_RESET.
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ciHost Adapter event:
3078c2ecf20Sopenharmony_ci	HAE_RESET
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ciA SAS LLDD should be able to generate
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	- at least one event from group C (choice),
3128c2ecf20Sopenharmony_ci	- events marked M (mandatory) are mandatory (only one),
3138c2ecf20Sopenharmony_ci	- events marked E (expander) if it wants the SAS layer
3148c2ecf20Sopenharmony_ci	  to handle domain revalidation (only one such).
3158c2ecf20Sopenharmony_ci	- Unmarked events are optional.
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ciMeaning:
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ciHAE_RESET
3208c2ecf20Sopenharmony_ci    - when your HA got internal error and was reset.
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ciPORTE_BYTES_DMAED
3238c2ecf20Sopenharmony_ci    - on receiving an IDENTIFY/FIS frame
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ciPORTE_BROADCAST_RCVD
3268c2ecf20Sopenharmony_ci    - on receiving a primitive
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ciPORTE_LINK_RESET_ERR
3298c2ecf20Sopenharmony_ci    - timer expired, loss of signal, loss of DWS, etc. [1]_
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ciPORTE_TIMER_EVENT
3328c2ecf20Sopenharmony_ci    - DWS reset timeout timer expired [1]_
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ciPORTE_HARD_RESET
3358c2ecf20Sopenharmony_ci    - Hard Reset primitive received.
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ciPHYE_LOSS_OF_SIGNAL
3388c2ecf20Sopenharmony_ci    - the device is gone [1]_
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ciPHYE_OOB_DONE
3418c2ecf20Sopenharmony_ci    - OOB went fine and oob_mode is valid
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ciPHYE_OOB_ERROR
3448c2ecf20Sopenharmony_ci    - Error while doing OOB, the device probably
3458c2ecf20Sopenharmony_ci      got disconnected. [1]_
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ciPHYE_SPINUP_HOLD
3488c2ecf20Sopenharmony_ci    - SATA is present, COMWAKE not sent.
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci.. [1] should set/clear the appropriate fields in the phy,
3518c2ecf20Sopenharmony_ci       or alternatively call the inlined sas_phy_disconnected()
3528c2ecf20Sopenharmony_ci       which is just a helper, from their tasklet.
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ciThe Execute Command SCSI RPC::
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	int (*lldd_execute_task)(struct sas_task *, gfp_t gfp_flags);
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ciUsed to queue a task to the SAS LLDD.  @task is the task to be executed.
3598c2ecf20Sopenharmony_ci@gfp_mask is the gfp_mask defining the context of the caller.
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ciThis function should implement the Execute Command SCSI RPC,
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ciThat is, when lldd_execute_task() is called, the command
3648c2ecf20Sopenharmony_cigo out on the transport *immediately*.  There is *no*
3658c2ecf20Sopenharmony_ciqueuing of any sort and at any level in a SAS LLDD.
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ciReturns:
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci   * -SAS_QUEUE_FULL, -ENOMEM, nothing was queued;
3708c2ecf20Sopenharmony_ci   * 0, the task(s) were queued.
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci::
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci    struct sas_task {
3758c2ecf20Sopenharmony_ci	    dev -- the device this task is destined to
3768c2ecf20Sopenharmony_ci	    task_proto -- _one_ of enum sas_proto
3778c2ecf20Sopenharmony_ci	    scatter -- pointer to scatter gather list array
3788c2ecf20Sopenharmony_ci	    num_scatter -- number of elements in scatter
3798c2ecf20Sopenharmony_ci	    total_xfer_len -- total number of bytes expected to be transferred
3808c2ecf20Sopenharmony_ci	    data_dir -- PCI_DMA_...
3818c2ecf20Sopenharmony_ci	    task_done -- callback when the task has finished execution
3828c2ecf20Sopenharmony_ci    };
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ciDiscovery
3858c2ecf20Sopenharmony_ci=========
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ciThe sysfs tree has the following purposes:
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci    a) It shows you the physical layout of the SAS domain at
3908c2ecf20Sopenharmony_ci       the current time, i.e. how the domain looks in the
3918c2ecf20Sopenharmony_ci       physical world right now.
3928c2ecf20Sopenharmony_ci    b) Shows some device parameters _at_discovery_time_.
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ciThis is a link to the tree(1) program, very useful in
3958c2ecf20Sopenharmony_civiewing the SAS domain:
3968c2ecf20Sopenharmony_ciftp://mama.indstate.edu/linux/tree/
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ciI expect user space applications to actually create a
3998c2ecf20Sopenharmony_cigraphical interface of this.
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ciThat is, the sysfs domain tree doesn't show or keep state if
4028c2ecf20Sopenharmony_ciyou e.g., change the meaning of the READY LED MEANING
4038c2ecf20Sopenharmony_cisetting, but it does show you the current connection status
4048c2ecf20Sopenharmony_ciof the domain device.
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ciKeeping internal device state changes is responsibility of
4078c2ecf20Sopenharmony_ciupper layers (Command set drivers) and user space.
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ciWhen a device or devices are unplugged from the domain, this
4108c2ecf20Sopenharmony_ciis reflected in the sysfs tree immediately, and the device(s)
4118c2ecf20Sopenharmony_ciremoved from the system.
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ciThe structure domain_device describes any device in the SAS
4148c2ecf20Sopenharmony_cidomain.  It is completely managed by the SAS layer.  A task
4158c2ecf20Sopenharmony_cipoints to a domain device, this is how the SAS LLDD knows
4168c2ecf20Sopenharmony_ciwhere to send the task(s) to.  A SAS LLDD only reads the
4178c2ecf20Sopenharmony_cicontents of the domain_device structure, but it never creates
4188c2ecf20Sopenharmony_cior destroys one.
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ciExpander management from User Space
4218c2ecf20Sopenharmony_ci===================================
4228c2ecf20Sopenharmony_ci
4238c2ecf20Sopenharmony_ciIn each expander directory in sysfs, there is a file called
4248c2ecf20Sopenharmony_ci"smp_portal".  It is a binary sysfs attribute file, which
4258c2ecf20Sopenharmony_ciimplements an SMP portal (Note: this is *NOT* an SMP port),
4268c2ecf20Sopenharmony_cito which user space applications can send SMP requests and
4278c2ecf20Sopenharmony_cireceive SMP responses.
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ciFunctionality is deceptively simple:
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci1. Build the SMP frame you want to send. The format and layout
4328c2ecf20Sopenharmony_ci   is described in the SAS spec.  Leave the CRC field equal 0.
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ciopen(2)
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci2. Open the expander's SMP portal sysfs file in RW mode.
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ciwrite(2)
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci3. Write the frame you built in 1.
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ciread(2)
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci4. Read the amount of data you expect to receive for the frame you built.
4458c2ecf20Sopenharmony_ci   If you receive different amount of data you expected to receive,
4468c2ecf20Sopenharmony_ci   then there was some kind of error.
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ciclose(2)
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ciAll this process is shown in detail in the function do_smp_func()
4518c2ecf20Sopenharmony_ciand its callers, in the file "expander_conf.c".
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ciThe kernel functionality is implemented in the file
4548c2ecf20Sopenharmony_ci"sas_expander.c".
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ciThe program "expander_conf.c" implements this. It takes one
4578c2ecf20Sopenharmony_ciargument, the sysfs file name of the SMP portal to the
4588c2ecf20Sopenharmony_ciexpander, and gives expander information, including routing
4598c2ecf20Sopenharmony_citables.
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ciThe SMP portal gives you complete control of the expander,
4628c2ecf20Sopenharmony_ciso please be careful.
463