123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- .. SPDX-License-Identifier: GPL-2.0
- =========
- SAS Layer
- =========
- The SAS Layer is a management infrastructure which manages
- SAS LLDDs. It sits between SCSI Core and SAS LLDDs. The
- layout is as follows: while SCSI Core is concerned with
- SAM/SPC issues, and a SAS LLDD+sequencer is concerned with
- phy/OOB/link management, the SAS layer is concerned with:
- * SAS Phy/Port/HA event management (LLDD generates,
- SAS Layer processes),
- * SAS Port management (creation/destruction),
- * SAS Domain discovery and revalidation,
- * SAS Domain device management,
- * SCSI Host registration/unregistration,
- * Device registration with SCSI Core (SAS) or libata
- (SATA), and
- * Expander management and exporting expander control
- to user space.
- A SAS LLDD is a PCI device driver. It is concerned with
- phy/OOB management, and vendor specific tasks and generates
- events to the SAS layer.
- The SAS Layer does most SAS tasks as outlined in the SAS 1.1
- spec.
- The sas_ha_struct describes the SAS LLDD to the SAS layer.
- Most of it is used by the SAS Layer but a few fields need to
- be initialized by the LLDDs.
- After initializing your hardware, from the probe() function
- you call sas_register_ha(). It will register your LLDD with
- the SCSI subsystem, creating a SCSI host and it will
- register your SAS driver with the sysfs SAS tree it creates.
- It will then return. Then you enable your phys to actually
- start OOB (at which point your driver will start calling the
- notify_* event callbacks).
- Structure descriptions
- ======================
- ``struct sas_phy``
- Normally this is statically embedded to your driver's
- phy structure::
- struct my_phy {
- blah;
- struct sas_phy sas_phy;
- bleh;
- };
- And then all the phys are an array of my_phy in your HA
- struct (shown below).
- Then as you go along and initialize your phys you also
- initialize the sas_phy struct, along with your own
- phy structure.
- In general, the phys are managed by the LLDD and the ports
- are managed by the SAS layer. So the phys are initialized
- and updated by the LLDD and the ports are initialized and
- updated by the SAS layer.
- There is a scheme where the LLDD can RW certain fields,
- and the SAS layer can only read such ones, and vice versa.
- The idea is to avoid unnecessary locking.
- enabled
- - must be set (0/1)
- id
- - must be set [0,MAX_PHYS)]
- class, proto, type, role, oob_mode, linkrate
- - must be set
- oob_mode
- - you set this when OOB has finished and then notify
- the SAS Layer.
- sas_addr
- - this normally points to an array holding the sas
- address of the phy, possibly somewhere in your my_phy
- struct.
- attached_sas_addr
- - set this when you (LLDD) receive an
- IDENTIFY frame or a FIS frame, _before_ notifying the SAS
- layer. The idea is that sometimes the LLDD may want to fake
- or provide a different SAS address on that phy/port and this
- allows it to do this. At best you should copy the sas
- address from the IDENTIFY frame or maybe generate a SAS
- address for SATA directly attached devices. The Discover
- process may later change this.
- frame_rcvd
- - this is where you copy the IDENTIFY/FIS frame
- when you get it; you lock, copy, set frame_rcvd_size and
- unlock the lock, and then call the event. It is a pointer
- since there's no way to know your hw frame size _exactly_,
- so you define the actual array in your phy struct and let
- this pointer point to it. You copy the frame from your
- DMAable memory to that area holding the lock.
- sas_prim
- - this is where primitives go when they're
- received. See sas.h. Grab the lock, set the primitive,
- release the lock, notify.
- port
- - this points to the sas_port if the phy belongs
- to a port
- sas_port this phy is part of. Set by the SAS Layer.
- ha
- - may be set; the SAS layer sets it anyway.
- lldd_phy
- - you should set this to point to your phy so you
- can find your way around faster when the SAS layer calls one
- of your callbacks and passes you a phy. If the sas_phy is
- embedded you can also use container_of
- prefer.
- ``struct sas_port``
- The LLDD doesn't set any fields of this struct
- reads them. They should be self explanatory.
- phy_mask is 32 bit, this should be enough for now, as I
- haven't heard of a HA having more than 8 phys.
- lldd_port
- - I haven't found use for that
- LLDD who wish to have internal port representation can make
- use of this.
- ``struct sas_ha_struct``
- It normally is statically declared in your own LLDD
- structure describing your adapter::
- struct my_sas_ha {
- blah;
- struct sas_ha_struct sas_ha;
- struct my_phy phys[MAX_PHYS];
- struct sas_port sas_ports[MAX_PHYS]; /* (1) */
- bleh;
- };
- (1) If your LLDD doesn't have its own port representation.
- What needs to be initialized (sample function given below).
- pcidev
- ^^^^^^
- sas_addr
- - since the SAS layer doesn't want to mess with
- memory allocation, etc, this points to statically
- allocated array somewhere (say in your host adapter
- structure) and holds the SAS address of the host
- adapter as given by you or the manufacturer, etc.
- sas_port
- ^^^^^^^^
- sas_phy
- - an array of pointers to structures. (see
- note above on sas_addr).
- These must be set. See more notes below.
- num_phys
- - the number of phys present in the sas_phy array,
- and the number of ports present in the sas_port
- array. There can be a maximum num_phys ports (one per
- port) so we drop the num_ports, and only use
- num_phys.
- The event interface::
- /* LLDD calls these to notify the class of an event. */
- void sas_notify_port_event(struct sas_phy *, enum port_event, gfp_t);
- void sas_notify_phy_event(struct sas_phy *, enum phy_event, gfp_t);
- The port notification::
- /* The class calls these to notify the LLDD of an event. */
- void ;
- void ;
- If the LLDD wants notification when a port has been formed
- or deformed it sets those to a function satisfying the type.
- A SAS LLDD should also implement at least one of the Task
- Management Functions (TMFs) described in SAM::
- /* Task Management Functions. Must be called from process context. */
- int ;
- int
|