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