1*4882a593Smuzhiyun.. SPDX-License-Identifier: GPL-2.0 2*4882a593Smuzhiyun 3*4882a593Smuzhiyun========= 4*4882a593SmuzhiyunSAS Layer 5*4882a593Smuzhiyun========= 6*4882a593Smuzhiyun 7*4882a593SmuzhiyunThe SAS Layer is a management infrastructure which manages 8*4882a593SmuzhiyunSAS LLDDs. It sits between SCSI Core and SAS LLDDs. The 9*4882a593Smuzhiyunlayout is as follows: while SCSI Core is concerned with 10*4882a593SmuzhiyunSAM/SPC issues, and a SAS LLDD+sequencer is concerned with 11*4882a593Smuzhiyunphy/OOB/link management, the SAS layer is concerned with: 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun * SAS Phy/Port/HA event management (LLDD generates, 14*4882a593Smuzhiyun SAS Layer processes), 15*4882a593Smuzhiyun * SAS Port management (creation/destruction), 16*4882a593Smuzhiyun * SAS Domain discovery and revalidation, 17*4882a593Smuzhiyun * SAS Domain device management, 18*4882a593Smuzhiyun * SCSI Host registration/unregistration, 19*4882a593Smuzhiyun * Device registration with SCSI Core (SAS) or libata 20*4882a593Smuzhiyun (SATA), and 21*4882a593Smuzhiyun * Expander management and exporting expander control 22*4882a593Smuzhiyun to user space. 23*4882a593Smuzhiyun 24*4882a593SmuzhiyunA SAS LLDD is a PCI device driver. It is concerned with 25*4882a593Smuzhiyunphy/OOB management, and vendor specific tasks and generates 26*4882a593Smuzhiyunevents to the SAS layer. 27*4882a593Smuzhiyun 28*4882a593SmuzhiyunThe SAS Layer does most SAS tasks as outlined in the SAS 1.1 29*4882a593Smuzhiyunspec. 30*4882a593Smuzhiyun 31*4882a593SmuzhiyunThe sas_ha_struct describes the SAS LLDD to the SAS layer. 32*4882a593SmuzhiyunMost of it is used by the SAS Layer but a few fields need to 33*4882a593Smuzhiyunbe initialized by the LLDDs. 34*4882a593Smuzhiyun 35*4882a593SmuzhiyunAfter initializing your hardware, from the probe() function 36*4882a593Smuzhiyunyou call sas_register_ha(). It will register your LLDD with 37*4882a593Smuzhiyunthe SCSI subsystem, creating a SCSI host and it will 38*4882a593Smuzhiyunregister your SAS driver with the sysfs SAS tree it creates. 39*4882a593SmuzhiyunIt will then return. Then you enable your phys to actually 40*4882a593Smuzhiyunstart OOB (at which point your driver will start calling the 41*4882a593Smuzhiyunnotify_* event callbacks). 42*4882a593Smuzhiyun 43*4882a593SmuzhiyunStructure descriptions 44*4882a593Smuzhiyun====================== 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun``struct sas_phy`` 47*4882a593Smuzhiyun------------------ 48*4882a593Smuzhiyun 49*4882a593SmuzhiyunNormally this is statically embedded to your driver's 50*4882a593Smuzhiyunphy structure:: 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun struct my_phy { 53*4882a593Smuzhiyun blah; 54*4882a593Smuzhiyun struct sas_phy sas_phy; 55*4882a593Smuzhiyun bleh; 56*4882a593Smuzhiyun }; 57*4882a593Smuzhiyun 58*4882a593SmuzhiyunAnd then all the phys are an array of my_phy in your HA 59*4882a593Smuzhiyunstruct (shown below). 60*4882a593Smuzhiyun 61*4882a593SmuzhiyunThen as you go along and initialize your phys you also 62*4882a593Smuzhiyuninitialize the sas_phy struct, along with your own 63*4882a593Smuzhiyunphy structure. 64*4882a593Smuzhiyun 65*4882a593SmuzhiyunIn general, the phys are managed by the LLDD and the ports 66*4882a593Smuzhiyunare managed by the SAS layer. So the phys are initialized 67*4882a593Smuzhiyunand updated by the LLDD and the ports are initialized and 68*4882a593Smuzhiyunupdated by the SAS layer. 69*4882a593Smuzhiyun 70*4882a593SmuzhiyunThere is a scheme where the LLDD can RW certain fields, 71*4882a593Smuzhiyunand the SAS layer can only read such ones, and vice versa. 72*4882a593SmuzhiyunThe idea is to avoid unnecessary locking. 73*4882a593Smuzhiyun 74*4882a593Smuzhiyunenabled 75*4882a593Smuzhiyun - must be set (0/1) 76*4882a593Smuzhiyun 77*4882a593Smuzhiyunid 78*4882a593Smuzhiyun - must be set [0,MAX_PHYS)] 79*4882a593Smuzhiyun 80*4882a593Smuzhiyunclass, proto, type, role, oob_mode, linkrate 81*4882a593Smuzhiyun - must be set 82*4882a593Smuzhiyun 83*4882a593Smuzhiyunoob_mode 84*4882a593Smuzhiyun - you set this when OOB has finished and then notify 85*4882a593Smuzhiyun the SAS Layer. 86*4882a593Smuzhiyun 87*4882a593Smuzhiyunsas_addr 88*4882a593Smuzhiyun - this normally points to an array holding the sas 89*4882a593Smuzhiyun address of the phy, possibly somewhere in your my_phy 90*4882a593Smuzhiyun struct. 91*4882a593Smuzhiyun 92*4882a593Smuzhiyunattached_sas_addr 93*4882a593Smuzhiyun - set this when you (LLDD) receive an 94*4882a593Smuzhiyun IDENTIFY frame or a FIS frame, _before_ notifying the SAS 95*4882a593Smuzhiyun layer. The idea is that sometimes the LLDD may want to fake 96*4882a593Smuzhiyun or provide a different SAS address on that phy/port and this 97*4882a593Smuzhiyun allows it to do this. At best you should copy the sas 98*4882a593Smuzhiyun address from the IDENTIFY frame or maybe generate a SAS 99*4882a593Smuzhiyun address for SATA directly attached devices. The Discover 100*4882a593Smuzhiyun process may later change this. 101*4882a593Smuzhiyun 102*4882a593Smuzhiyunframe_rcvd 103*4882a593Smuzhiyun - this is where you copy the IDENTIFY/FIS frame 104*4882a593Smuzhiyun when you get it; you lock, copy, set frame_rcvd_size and 105*4882a593Smuzhiyun unlock the lock, and then call the event. It is a pointer 106*4882a593Smuzhiyun since there's no way to know your hw frame size _exactly_, 107*4882a593Smuzhiyun so you define the actual array in your phy struct and let 108*4882a593Smuzhiyun this pointer point to it. You copy the frame from your 109*4882a593Smuzhiyun DMAable memory to that area holding the lock. 110*4882a593Smuzhiyun 111*4882a593Smuzhiyunsas_prim 112*4882a593Smuzhiyun - this is where primitives go when they're 113*4882a593Smuzhiyun received. See sas.h. Grab the lock, set the primitive, 114*4882a593Smuzhiyun release the lock, notify. 115*4882a593Smuzhiyun 116*4882a593Smuzhiyunport 117*4882a593Smuzhiyun - this points to the sas_port if the phy belongs 118*4882a593Smuzhiyun to a port -- the LLDD only reads this. It points to the 119*4882a593Smuzhiyun sas_port this phy is part of. Set by the SAS Layer. 120*4882a593Smuzhiyun 121*4882a593Smuzhiyunha 122*4882a593Smuzhiyun - may be set; the SAS layer sets it anyway. 123*4882a593Smuzhiyun 124*4882a593Smuzhiyunlldd_phy 125*4882a593Smuzhiyun - you should set this to point to your phy so you 126*4882a593Smuzhiyun can find your way around faster when the SAS layer calls one 127*4882a593Smuzhiyun of your callbacks and passes you a phy. If the sas_phy is 128*4882a593Smuzhiyun embedded you can also use container_of -- whatever you 129*4882a593Smuzhiyun prefer. 130*4882a593Smuzhiyun 131*4882a593Smuzhiyun 132*4882a593Smuzhiyun``struct sas_port`` 133*4882a593Smuzhiyun------------------- 134*4882a593Smuzhiyun 135*4882a593SmuzhiyunThe LLDD doesn't set any fields of this struct -- it only 136*4882a593Smuzhiyunreads them. They should be self explanatory. 137*4882a593Smuzhiyun 138*4882a593Smuzhiyunphy_mask is 32 bit, this should be enough for now, as I 139*4882a593Smuzhiyunhaven't heard of a HA having more than 8 phys. 140*4882a593Smuzhiyun 141*4882a593Smuzhiyunlldd_port 142*4882a593Smuzhiyun - I haven't found use for that -- maybe other 143*4882a593Smuzhiyun LLDD who wish to have internal port representation can make 144*4882a593Smuzhiyun use of this. 145*4882a593Smuzhiyun 146*4882a593Smuzhiyun``struct sas_ha_struct`` 147*4882a593Smuzhiyun------------------------ 148*4882a593Smuzhiyun 149*4882a593SmuzhiyunIt normally is statically declared in your own LLDD 150*4882a593Smuzhiyunstructure describing your adapter:: 151*4882a593Smuzhiyun 152*4882a593Smuzhiyun struct my_sas_ha { 153*4882a593Smuzhiyun blah; 154*4882a593Smuzhiyun struct sas_ha_struct sas_ha; 155*4882a593Smuzhiyun struct my_phy phys[MAX_PHYS]; 156*4882a593Smuzhiyun struct sas_port sas_ports[MAX_PHYS]; /* (1) */ 157*4882a593Smuzhiyun bleh; 158*4882a593Smuzhiyun }; 159*4882a593Smuzhiyun 160*4882a593Smuzhiyun (1) If your LLDD doesn't have its own port representation. 161*4882a593Smuzhiyun 162*4882a593SmuzhiyunWhat needs to be initialized (sample function given below). 163*4882a593Smuzhiyun 164*4882a593Smuzhiyunpcidev 165*4882a593Smuzhiyun^^^^^^ 166*4882a593Smuzhiyun 167*4882a593Smuzhiyunsas_addr 168*4882a593Smuzhiyun - since the SAS layer doesn't want to mess with 169*4882a593Smuzhiyun memory allocation, etc, this points to statically 170*4882a593Smuzhiyun allocated array somewhere (say in your host adapter 171*4882a593Smuzhiyun structure) and holds the SAS address of the host 172*4882a593Smuzhiyun adapter as given by you or the manufacturer, etc. 173*4882a593Smuzhiyun 174*4882a593Smuzhiyunsas_port 175*4882a593Smuzhiyun^^^^^^^^ 176*4882a593Smuzhiyun 177*4882a593Smuzhiyunsas_phy 178*4882a593Smuzhiyun - an array of pointers to structures. (see 179*4882a593Smuzhiyun note above on sas_addr). 180*4882a593Smuzhiyun These must be set. See more notes below. 181*4882a593Smuzhiyun 182*4882a593Smuzhiyunnum_phys 183*4882a593Smuzhiyun - the number of phys present in the sas_phy array, 184*4882a593Smuzhiyun and the number of ports present in the sas_port 185*4882a593Smuzhiyun array. There can be a maximum num_phys ports (one per 186*4882a593Smuzhiyun port) so we drop the num_ports, and only use 187*4882a593Smuzhiyun num_phys. 188*4882a593Smuzhiyun 189*4882a593SmuzhiyunThe event interface:: 190*4882a593Smuzhiyun 191*4882a593Smuzhiyun /* LLDD calls these to notify the class of an event. */ 192*4882a593Smuzhiyun void sas_notify_port_event(struct sas_phy *, enum port_event); 193*4882a593Smuzhiyun void sas_notify_phy_event(struct sas_phy *, enum phy_event); 194*4882a593Smuzhiyun void sas_notify_port_event_gfp(struct sas_phy *, enum port_event, gfp_t); 195*4882a593Smuzhiyun void sas_notify_phy_event_gfp(struct sas_phy *, enum phy_event, gfp_t); 196*4882a593Smuzhiyun 197*4882a593SmuzhiyunThe port notification:: 198*4882a593Smuzhiyun 199*4882a593Smuzhiyun /* The class calls these to notify the LLDD of an event. */ 200*4882a593Smuzhiyun void (*lldd_port_formed)(struct sas_phy *); 201*4882a593Smuzhiyun void (*lldd_port_deformed)(struct sas_phy *); 202*4882a593Smuzhiyun 203*4882a593SmuzhiyunIf the LLDD wants notification when a port has been formed 204*4882a593Smuzhiyunor deformed it sets those to a function satisfying the type. 205*4882a593Smuzhiyun 206*4882a593SmuzhiyunA SAS LLDD should also implement at least one of the Task 207*4882a593SmuzhiyunManagement Functions (TMFs) described in SAM:: 208*4882a593Smuzhiyun 209*4882a593Smuzhiyun /* Task Management Functions. Must be called from process context. */ 210*4882a593Smuzhiyun int (*lldd_abort_task)(struct sas_task *); 211*4882a593Smuzhiyun int (*lldd_abort_task_set)(struct domain_device *, u8 *lun); 212*4882a593Smuzhiyun int (*lldd_clear_aca)(struct domain_device *, u8 *lun); 213*4882a593Smuzhiyun int (*lldd_clear_task_set)(struct domain_device *, u8 *lun); 214*4882a593Smuzhiyun int (*lldd_I_T_nexus_reset)(struct domain_device *); 215*4882a593Smuzhiyun int (*lldd_lu_reset)(struct domain_device *, u8 *lun); 216*4882a593Smuzhiyun int (*lldd_query_task)(struct sas_task *); 217*4882a593Smuzhiyun 218*4882a593SmuzhiyunFor more information please read SAM from T10.org. 219*4882a593Smuzhiyun 220*4882a593SmuzhiyunPort and Adapter management:: 221*4882a593Smuzhiyun 222*4882a593Smuzhiyun /* Port and Adapter management */ 223*4882a593Smuzhiyun int (*lldd_clear_nexus_port)(struct sas_port *); 224*4882a593Smuzhiyun int (*lldd_clear_nexus_ha)(struct sas_ha_struct *); 225*4882a593Smuzhiyun 226*4882a593SmuzhiyunA SAS LLDD should implement at least one of those. 227*4882a593Smuzhiyun 228*4882a593SmuzhiyunPhy management:: 229*4882a593Smuzhiyun 230*4882a593Smuzhiyun /* Phy management */ 231*4882a593Smuzhiyun int (*lldd_control_phy)(struct sas_phy *, enum phy_func); 232*4882a593Smuzhiyun 233*4882a593Smuzhiyunlldd_ha 234*4882a593Smuzhiyun - set this to point to your HA struct. You can also 235*4882a593Smuzhiyun use container_of if you embedded it as shown above. 236*4882a593Smuzhiyun 237*4882a593SmuzhiyunA sample initialization and registration function 238*4882a593Smuzhiyuncan look like this (called last thing from probe()) 239*4882a593Smuzhiyun*but* before you enable the phys to do OOB:: 240*4882a593Smuzhiyun 241*4882a593Smuzhiyun static int register_sas_ha(struct my_sas_ha *my_ha) 242*4882a593Smuzhiyun { 243*4882a593Smuzhiyun int i; 244*4882a593Smuzhiyun static struct sas_phy *sas_phys[MAX_PHYS]; 245*4882a593Smuzhiyun static struct sas_port *sas_ports[MAX_PHYS]; 246*4882a593Smuzhiyun 247*4882a593Smuzhiyun my_ha->sas_ha.sas_addr = &my_ha->sas_addr[0]; 248*4882a593Smuzhiyun 249*4882a593Smuzhiyun for (i = 0; i < MAX_PHYS; i++) { 250*4882a593Smuzhiyun sas_phys[i] = &my_ha->phys[i].sas_phy; 251*4882a593Smuzhiyun sas_ports[i] = &my_ha->sas_ports[i]; 252*4882a593Smuzhiyun } 253*4882a593Smuzhiyun 254*4882a593Smuzhiyun my_ha->sas_ha.sas_phy = sas_phys; 255*4882a593Smuzhiyun my_ha->sas_ha.sas_port = sas_ports; 256*4882a593Smuzhiyun my_ha->sas_ha.num_phys = MAX_PHYS; 257*4882a593Smuzhiyun 258*4882a593Smuzhiyun my_ha->sas_ha.lldd_port_formed = my_port_formed; 259*4882a593Smuzhiyun 260*4882a593Smuzhiyun my_ha->sas_ha.lldd_dev_found = my_dev_found; 261*4882a593Smuzhiyun my_ha->sas_ha.lldd_dev_gone = my_dev_gone; 262*4882a593Smuzhiyun 263*4882a593Smuzhiyun my_ha->sas_ha.lldd_execute_task = my_execute_task; 264*4882a593Smuzhiyun 265*4882a593Smuzhiyun my_ha->sas_ha.lldd_abort_task = my_abort_task; 266*4882a593Smuzhiyun my_ha->sas_ha.lldd_abort_task_set = my_abort_task_set; 267*4882a593Smuzhiyun my_ha->sas_ha.lldd_clear_aca = my_clear_aca; 268*4882a593Smuzhiyun my_ha->sas_ha.lldd_clear_task_set = my_clear_task_set; 269*4882a593Smuzhiyun my_ha->sas_ha.lldd_I_T_nexus_reset= NULL; (2) 270*4882a593Smuzhiyun my_ha->sas_ha.lldd_lu_reset = my_lu_reset; 271*4882a593Smuzhiyun my_ha->sas_ha.lldd_query_task = my_query_task; 272*4882a593Smuzhiyun 273*4882a593Smuzhiyun my_ha->sas_ha.lldd_clear_nexus_port = my_clear_nexus_port; 274*4882a593Smuzhiyun my_ha->sas_ha.lldd_clear_nexus_ha = my_clear_nexus_ha; 275*4882a593Smuzhiyun 276*4882a593Smuzhiyun my_ha->sas_ha.lldd_control_phy = my_control_phy; 277*4882a593Smuzhiyun 278*4882a593Smuzhiyun return sas_register_ha(&my_ha->sas_ha); 279*4882a593Smuzhiyun } 280*4882a593Smuzhiyun 281*4882a593Smuzhiyun(2) SAS 1.1 does not define I_T Nexus Reset TMF. 282*4882a593Smuzhiyun 283*4882a593SmuzhiyunEvents 284*4882a593Smuzhiyun====== 285*4882a593Smuzhiyun 286*4882a593SmuzhiyunEvents are **the only way** a SAS LLDD notifies the SAS layer 287*4882a593Smuzhiyunof anything. There is no other method or way a LLDD to tell 288*4882a593Smuzhiyunthe SAS layer of anything happening internally or in the SAS 289*4882a593Smuzhiyundomain. 290*4882a593Smuzhiyun 291*4882a593SmuzhiyunPhy events:: 292*4882a593Smuzhiyun 293*4882a593Smuzhiyun PHYE_LOSS_OF_SIGNAL, (C) 294*4882a593Smuzhiyun PHYE_OOB_DONE, 295*4882a593Smuzhiyun PHYE_OOB_ERROR, (C) 296*4882a593Smuzhiyun PHYE_SPINUP_HOLD. 297*4882a593Smuzhiyun 298*4882a593SmuzhiyunPort events, passed on a _phy_:: 299*4882a593Smuzhiyun 300*4882a593Smuzhiyun PORTE_BYTES_DMAED, (M) 301*4882a593Smuzhiyun PORTE_BROADCAST_RCVD, (E) 302*4882a593Smuzhiyun PORTE_LINK_RESET_ERR, (C) 303*4882a593Smuzhiyun PORTE_TIMER_EVENT, (C) 304*4882a593Smuzhiyun PORTE_HARD_RESET. 305*4882a593Smuzhiyun 306*4882a593SmuzhiyunHost Adapter event: 307*4882a593Smuzhiyun HAE_RESET 308*4882a593Smuzhiyun 309*4882a593SmuzhiyunA SAS LLDD should be able to generate 310*4882a593Smuzhiyun 311*4882a593Smuzhiyun - at least one event from group C (choice), 312*4882a593Smuzhiyun - events marked M (mandatory) are mandatory (only one), 313*4882a593Smuzhiyun - events marked E (expander) if it wants the SAS layer 314*4882a593Smuzhiyun to handle domain revalidation (only one such). 315*4882a593Smuzhiyun - Unmarked events are optional. 316*4882a593Smuzhiyun 317*4882a593SmuzhiyunMeaning: 318*4882a593Smuzhiyun 319*4882a593SmuzhiyunHAE_RESET 320*4882a593Smuzhiyun - when your HA got internal error and was reset. 321*4882a593Smuzhiyun 322*4882a593SmuzhiyunPORTE_BYTES_DMAED 323*4882a593Smuzhiyun - on receiving an IDENTIFY/FIS frame 324*4882a593Smuzhiyun 325*4882a593SmuzhiyunPORTE_BROADCAST_RCVD 326*4882a593Smuzhiyun - on receiving a primitive 327*4882a593Smuzhiyun 328*4882a593SmuzhiyunPORTE_LINK_RESET_ERR 329*4882a593Smuzhiyun - timer expired, loss of signal, loss of DWS, etc. [1]_ 330*4882a593Smuzhiyun 331*4882a593SmuzhiyunPORTE_TIMER_EVENT 332*4882a593Smuzhiyun - DWS reset timeout timer expired [1]_ 333*4882a593Smuzhiyun 334*4882a593SmuzhiyunPORTE_HARD_RESET 335*4882a593Smuzhiyun - Hard Reset primitive received. 336*4882a593Smuzhiyun 337*4882a593SmuzhiyunPHYE_LOSS_OF_SIGNAL 338*4882a593Smuzhiyun - the device is gone [1]_ 339*4882a593Smuzhiyun 340*4882a593SmuzhiyunPHYE_OOB_DONE 341*4882a593Smuzhiyun - OOB went fine and oob_mode is valid 342*4882a593Smuzhiyun 343*4882a593SmuzhiyunPHYE_OOB_ERROR 344*4882a593Smuzhiyun - Error while doing OOB, the device probably 345*4882a593Smuzhiyun got disconnected. [1]_ 346*4882a593Smuzhiyun 347*4882a593SmuzhiyunPHYE_SPINUP_HOLD 348*4882a593Smuzhiyun - SATA is present, COMWAKE not sent. 349*4882a593Smuzhiyun 350*4882a593Smuzhiyun.. [1] should set/clear the appropriate fields in the phy, 351*4882a593Smuzhiyun or alternatively call the inlined sas_phy_disconnected() 352*4882a593Smuzhiyun which is just a helper, from their tasklet. 353*4882a593Smuzhiyun 354*4882a593SmuzhiyunThe Execute Command SCSI RPC:: 355*4882a593Smuzhiyun 356*4882a593Smuzhiyun int (*lldd_execute_task)(struct sas_task *, gfp_t gfp_flags); 357*4882a593Smuzhiyun 358*4882a593SmuzhiyunUsed to queue a task to the SAS LLDD. @task is the task to be executed. 359*4882a593Smuzhiyun@gfp_mask is the gfp_mask defining the context of the caller. 360*4882a593Smuzhiyun 361*4882a593SmuzhiyunThis function should implement the Execute Command SCSI RPC, 362*4882a593Smuzhiyun 363*4882a593SmuzhiyunThat is, when lldd_execute_task() is called, the command 364*4882a593Smuzhiyungo out on the transport *immediately*. There is *no* 365*4882a593Smuzhiyunqueuing of any sort and at any level in a SAS LLDD. 366*4882a593Smuzhiyun 367*4882a593SmuzhiyunReturns: 368*4882a593Smuzhiyun 369*4882a593Smuzhiyun * -SAS_QUEUE_FULL, -ENOMEM, nothing was queued; 370*4882a593Smuzhiyun * 0, the task(s) were queued. 371*4882a593Smuzhiyun 372*4882a593Smuzhiyun:: 373*4882a593Smuzhiyun 374*4882a593Smuzhiyun struct sas_task { 375*4882a593Smuzhiyun dev -- the device this task is destined to 376*4882a593Smuzhiyun task_proto -- _one_ of enum sas_proto 377*4882a593Smuzhiyun scatter -- pointer to scatter gather list array 378*4882a593Smuzhiyun num_scatter -- number of elements in scatter 379*4882a593Smuzhiyun total_xfer_len -- total number of bytes expected to be transferred 380*4882a593Smuzhiyun data_dir -- PCI_DMA_... 381*4882a593Smuzhiyun task_done -- callback when the task has finished execution 382*4882a593Smuzhiyun }; 383*4882a593Smuzhiyun 384*4882a593SmuzhiyunDiscovery 385*4882a593Smuzhiyun========= 386*4882a593Smuzhiyun 387*4882a593SmuzhiyunThe sysfs tree has the following purposes: 388*4882a593Smuzhiyun 389*4882a593Smuzhiyun a) It shows you the physical layout of the SAS domain at 390*4882a593Smuzhiyun the current time, i.e. how the domain looks in the 391*4882a593Smuzhiyun physical world right now. 392*4882a593Smuzhiyun b) Shows some device parameters _at_discovery_time_. 393*4882a593Smuzhiyun 394*4882a593SmuzhiyunThis is a link to the tree(1) program, very useful in 395*4882a593Smuzhiyunviewing the SAS domain: 396*4882a593Smuzhiyunftp://mama.indstate.edu/linux/tree/ 397*4882a593Smuzhiyun 398*4882a593SmuzhiyunI expect user space applications to actually create a 399*4882a593Smuzhiyungraphical interface of this. 400*4882a593Smuzhiyun 401*4882a593SmuzhiyunThat is, the sysfs domain tree doesn't show or keep state if 402*4882a593Smuzhiyunyou e.g., change the meaning of the READY LED MEANING 403*4882a593Smuzhiyunsetting, but it does show you the current connection status 404*4882a593Smuzhiyunof the domain device. 405*4882a593Smuzhiyun 406*4882a593SmuzhiyunKeeping internal device state changes is responsibility of 407*4882a593Smuzhiyunupper layers (Command set drivers) and user space. 408*4882a593Smuzhiyun 409*4882a593SmuzhiyunWhen a device or devices are unplugged from the domain, this 410*4882a593Smuzhiyunis reflected in the sysfs tree immediately, and the device(s) 411*4882a593Smuzhiyunremoved from the system. 412*4882a593Smuzhiyun 413*4882a593SmuzhiyunThe structure domain_device describes any device in the SAS 414*4882a593Smuzhiyundomain. It is completely managed by the SAS layer. A task 415*4882a593Smuzhiyunpoints to a domain device, this is how the SAS LLDD knows 416*4882a593Smuzhiyunwhere to send the task(s) to. A SAS LLDD only reads the 417*4882a593Smuzhiyuncontents of the domain_device structure, but it never creates 418*4882a593Smuzhiyunor destroys one. 419*4882a593Smuzhiyun 420*4882a593SmuzhiyunExpander management from User Space 421*4882a593Smuzhiyun=================================== 422*4882a593Smuzhiyun 423*4882a593SmuzhiyunIn each expander directory in sysfs, there is a file called 424*4882a593Smuzhiyun"smp_portal". It is a binary sysfs attribute file, which 425*4882a593Smuzhiyunimplements an SMP portal (Note: this is *NOT* an SMP port), 426*4882a593Smuzhiyunto which user space applications can send SMP requests and 427*4882a593Smuzhiyunreceive SMP responses. 428*4882a593Smuzhiyun 429*4882a593SmuzhiyunFunctionality is deceptively simple: 430*4882a593Smuzhiyun 431*4882a593Smuzhiyun1. Build the SMP frame you want to send. The format and layout 432*4882a593Smuzhiyun is described in the SAS spec. Leave the CRC field equal 0. 433*4882a593Smuzhiyun 434*4882a593Smuzhiyunopen(2) 435*4882a593Smuzhiyun 436*4882a593Smuzhiyun2. Open the expander's SMP portal sysfs file in RW mode. 437*4882a593Smuzhiyun 438*4882a593Smuzhiyunwrite(2) 439*4882a593Smuzhiyun 440*4882a593Smuzhiyun3. Write the frame you built in 1. 441*4882a593Smuzhiyun 442*4882a593Smuzhiyunread(2) 443*4882a593Smuzhiyun 444*4882a593Smuzhiyun4. Read the amount of data you expect to receive for the frame you built. 445*4882a593Smuzhiyun If you receive different amount of data you expected to receive, 446*4882a593Smuzhiyun then there was some kind of error. 447*4882a593Smuzhiyun 448*4882a593Smuzhiyunclose(2) 449*4882a593Smuzhiyun 450*4882a593SmuzhiyunAll this process is shown in detail in the function do_smp_func() 451*4882a593Smuzhiyunand its callers, in the file "expander_conf.c". 452*4882a593Smuzhiyun 453*4882a593SmuzhiyunThe kernel functionality is implemented in the file 454*4882a593Smuzhiyun"sas_expander.c". 455*4882a593Smuzhiyun 456*4882a593SmuzhiyunThe program "expander_conf.c" implements this. It takes one 457*4882a593Smuzhiyunargument, the sysfs file name of the SMP portal to the 458*4882a593Smuzhiyunexpander, and gives expander information, including routing 459*4882a593Smuzhiyuntables. 460*4882a593Smuzhiyun 461*4882a593SmuzhiyunThe SMP portal gives you complete control of the expander, 462*4882a593Smuzhiyunso please be careful. 463