1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 * 21 * 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 #ifndef _PMCS_DEF_H 26 #define _PMCS_DEF_H 27 #ifdef __cplusplus 28 extern "C" { 29 #endif 30 31 typedef enum { 32 NOTHING, /* nothing connected here */ 33 SATA, /* SATA connection */ 34 SAS, /* direct or indirect SAS connection */ 35 EXPANDER, /* connection to an expander */ 36 NEW /* Brand new device (pending state) */ 37 } pmcs_dtype_t; 38 39 /* 40 * This structure defines a PHY device that represents what we 41 * are connected to. 42 * 43 * The eight real physical PHYs that are in the PMC8X6G are represented 44 * as an array of eight of these structures which define what these 45 * real PHYs are connected to. 46 * 47 * Depending upon what is actually connected to each PHY, the 48 * type set will define what we're connected to. If it is 49 * a direct SATA connection, the phy will describe a SATA endpoint 50 * If it is a direct SAS connection, it will describe a SAS 51 * endpoint. 52 * 53 * If it is an EXPANDER, this will describe the edge of an expander. 54 * As we perform discovery on what is in an EXPANDER we define an 55 * additional list of phys that represent what the Expander is connected to. 56 */ 57 #define PMCS_HW_MIN_LINK_RATE SAS_LINK_RATE_1_5GBIT 58 #define PMCS_HW_MAX_LINK_RATE SAS_LINK_RATE_6GBIT 59 60 #define PMCS_INVALID_DEVICE_ID 0xffffffff 61 #define PMCS_PHY_INVALID_PORT_ID 0xf 62 63 #define PMCS_PM_MAX_NAMELEN 16 64 65 struct pmcs_phy { 66 pmcs_phy_t *sibling; /* sibling phy */ 67 pmcs_phy_t *parent; /* parent phy */ 68 pmcs_phy_t *children; /* head of list of children */ 69 pmcs_phy_t *dead_next; /* dead PHY list link */ 70 list_node_t list_node; /* list element */ 71 uint32_t device_id; /* PMC8X6G device handle */ 72 uint32_t 73 ncphy : 8, /* # of contained phys for expander */ 74 hw_event_ack : 24; /* XXX: first level phy event acked */ 75 uint8_t phynum; /* phy number on parent expander */ 76 uint8_t width; /* how many phys wide */ 77 uint8_t ds_recovery_retries; /* # error retry attempts */ 78 uint8_t ds_prev_good_recoveries; /* # successful recoveries */ 79 clock_t prev_recovery; /* previous successful recovery */ 80 clock_t last_good_recovery; /* oldest successful recovery */ 81 /* within PMCS_MAX_DS_RECOVERY_TIME time frame */ 82 pmcs_dtype_t dtype; /* current dtype of the phy */ 83 pmcs_dtype_t pend_dtype; /* new dtype (pending change) */ 84 uint32_t 85 level : 8, /* level in expander tree */ 86 tolerates_sas2 : 1, /* tolerates SAS2 SMP */ 87 spinup_hold : 1, /* spinup hold needs releasing */ 88 atdt : 3, /* attached device type */ 89 portid : 4, /* PMC8X6G port context */ 90 link_rate : 4, /* current supported speeds */ 91 valid_device_id : 1, /* device id is valid */ 92 abort_sent : 1, /* we've sent an abort */ 93 abort_pending : 1, /* we have an abort pending */ 94 need_rl_ext : 1, /* need SATA RL_EXT recocvery */ 95 subsidiary : 1, /* this is part of a wide phy */ 96 configured : 1, /* is configured */ 97 dead : 1, /* dead */ 98 changed : 1, /* this phy is changing */ 99 deregister_wait : 1; /* phy waiting to get deregistered */ 100 clock_t config_stop; /* When config attempts will stop */ 101 hrtime_t abort_all_start; 102 kcondvar_t abort_all_cv; /* Wait for ABORT_ALL completion */ 103 kmutex_t phy_lock; 104 volatile uint32_t ref_count; /* Targets & work on this PHY */ 105 uint8_t sas_address[8]; /* SAS address for this PHY */ 106 struct { 107 uint32_t 108 prog_min_rate :4, 109 hw_min_rate :4, 110 prog_max_rate :4, 111 hw_max_rate :4, 112 reserved :16; 113 } state; 114 char path[32]; /* path name for this phy */ 115 pmcs_hw_t *pwp; /* back ptr to hba struct */ 116 pmcs_iport_t *iport; /* back ptr to the iport handle */ 117 pmcs_iport_t *last_iport; /* last iport this PHY was on */ 118 pmcs_xscsi_t *target; /* back ptr to current target */ 119 kstat_t *phy_stats; /* kstats for this phy */ 120 /* 121 * Attached port phy mask and target port phymask. With 16 bytes 122 * we can represent a phymask for anything with up to 64 ports 123 */ 124 uint64_t att_port_pm; /* att port pm for this PHY */ 125 uint64_t att_port_pm_tmp; /* Temp area for wide-ports */ 126 char att_port_pm_str[PMCS_PM_MAX_NAMELEN + 1]; 127 uint64_t tgt_port_pm; /* tgt port pm for this PHY */ 128 uint64_t tgt_port_pm_tmp; /* Temp area for wide-ports */ 129 char tgt_port_pm_str[PMCS_PM_MAX_NAMELEN + 1]; 130 }; 131 132 /* maximum number of ds recovery retries (ds_recovery_retries) */ 133 #define PMCS_MAX_DS_RECOVERY_RETRIES 10 134 135 /* max time allowed for successful recovery */ 136 #define PMCS_MAX_DS_RECOVERY_TIME (60 * 1000000) /* 60 seconds */ 137 138 /* ds recovery on same same phy is not allowed within this interval */ 139 #define PMCS_DS_RECOVERY_INTERVAL (1000000) /* 1 second */ 140 141 142 /* 143 * Inbound and Outbound Queue Related Definitions. 144 * 145 * The PMC8X6G has a programmable number of inbound and outbound circular 146 * queues for use in message passing between the host and the PMC8X6G 147 * (up to 64 queues for the Rev C Chip). This driver does not use all 148 * possible queues. 149 * 150 * Each Queue is given 4K of consistent memory and we set a 64 byte size for 151 * the queue entry size (this gives us 256 queue entries per queue). 152 * 153 * This allocation then continues up a further PMCS_SCRATCH_SIZE bytes 154 * that the driver uses as a temporary scratch area for things like 155 * SMP discovery. 156 * 157 * This control area looks like this: 158 * 159 * Offset What 160 * ------------------------------------------------ 161 * 0 IQ 0 Consumer Index 162 * 4 IQ 1 Consumer Index 163 * 8..255 ... 164 * 252..255 IQ 63 Consumer Index 165 * 256 OQ 0 Producer Index 166 * 260 OQ 1 Producer Index 167 * 264..259 .... 168 * 508..511 OQ 63 Producer Index 169 * 512..512+PMCS_SCRATCH_SIZE-1 Scratch area. 170 */ 171 #define IQCI_BASE_OFFSET 0 172 #define IQ_OFFSET(qnum) (IQCI_BASE_OFFSET + (qnum << 2)) 173 #define OQPI_BASE_OFFSET 256 174 #define OQ_OFFSET(qnum) (OQPI_BASE_OFFSET + (qnum << 2)) 175 176 /* 177 * Work related structures. Each one of these structures is paired 178 * with *any* command that is fed to the PMC8X6G via one of the 179 * Inbound Queues. The work structure has a tag to compare with 180 * the message that comes back out of an Outbound Queue. The 181 * work structure also points to the phy which this command is 182 * tied to. It also has a pointer a callback function (if defined). 183 * See that TAG Architecture below for the various kinds of 184 * dispositions of a work structure. 185 */ 186 187 /* 188 * Work Structure States 189 * 190 * NIL -> READY 191 * READY -> NIL 192 * READY -> ONCHIP 193 * ONCHIP -> INTR 194 * INTR -> READY 195 * INTR -> NIL 196 * INTR -> ABORTED 197 * INTR -> TIMED_OUT 198 * ABORTED -> NIL 199 * TIMED_OUT -> NIL 200 */ 201 typedef enum { 202 PMCS_WORK_STATE_NIL = 0, 203 PMCS_WORK_STATE_READY, 204 PMCS_WORK_STATE_ONCHIP, 205 PMCS_WORK_STATE_INTR, 206 PMCS_WORK_STATE_IOCOMPQ, 207 PMCS_WORK_STATE_ABORTED, 208 PMCS_WORK_STATE_TIMED_OUT 209 } pmcs_work_state_t; 210 211 struct pmcwork { 212 STAILQ_ENTRY(pmcwork) next; 213 kmutex_t lock; 214 kcondvar_t sleep_cv; 215 void *ptr; /* linkage or callback function */ 216 void *arg; /* command specific data */ 217 pmcs_phy_t *phy; /* phy who owns this command */ 218 pmcs_xscsi_t *xp; /* Back pointer to xscsi struct */ 219 volatile uint32_t htag; /* tag for this structure */ 220 uint32_t abt_htag; /* Tag of command to be aborted */ 221 uint32_t 222 timer : 27, 223 onwire : 1, 224 dead : 1, 225 state : 3; 226 hrtime_t start; /* timestamp start */ 227 uint32_t ssp_event; /* ssp event */ 228 pmcs_dtype_t dtype; /* stash, incase phy gets cleared */ 229 230 void *last_ptr; 231 void *last_arg; 232 pmcs_phy_t *last_phy; 233 pmcs_xscsi_t *last_xp; 234 uint32_t last_htag; 235 pmcs_work_state_t last_state; 236 hrtime_t finish; 237 }; 238 239 #define PMCS_REC_EVENT 0xffffffff /* event recovery */ 240 241 /* 242 * This structure defines a PMC-Sierra defined firmware header. 243 */ 244 #pragma pack(4) 245 typedef struct { 246 char vendor_id[8]; 247 uint8_t product_id; 248 uint8_t hwrev; 249 uint8_t destination_partition; 250 uint8_t reserved0; 251 uint8_t fwrev[4]; 252 uint32_t firmware_length; 253 uint32_t crc; 254 uint32_t start_address; 255 uint8_t data[]; 256 } pmcs_fw_hdr_t; 257 #pragma pack() 258 259 /* 260 * Offlevel work as a bit pattern. 261 */ 262 #define PMCS_WORK_DISCOVER 0 263 #define PMCS_WORK_ABORT_HANDLE 3 264 #define PMCS_WORK_SPINUP_RELEASE 4 265 #define PMCS_WORK_SAS_HW_ACK 5 266 #define PMCS_WORK_SATA_RUN 6 267 #define PMCS_WORK_RUN_QUEUES 7 268 #define PMCS_WORK_ADD_DMA_CHUNKS 8 269 #define PMCS_WORK_DS_ERR_RECOVERY 9 270 #define PMCS_WORK_SSP_EVT_RECOVERY 10 271 #define PMCS_WORK_DEREGISTER_DEV 11 272 273 /* 274 * The actual values as they appear in work_flags 275 */ 276 #define PMCS_WORK_FLAG_DISCOVER (1 << 0) 277 #define PMCS_WORK_FLAG_ABORT_HANDLE (1 << 3) 278 #define PMCS_WORK_FLAG_SPINUP_RELEASE (1 << 4) 279 #define PMCS_WORK_FLAG_SAS_HW_ACK (1 << 5) 280 #define PMCS_WORK_FLAG_SATA_RUN (1 << 6) 281 #define PMCS_WORK_FLAG_RUN_QUEUES (1 << 7) 282 #define PMCS_WORK_FLAG_ADD_DMA_CHUNKS (1 << 8) 283 #define PMCS_WORK_FLAG_DS_ERR_RECOVERY (1 << 9) 284 #define PMCS_WORK_FLAG_SSP_EVT_RECOVERY (1 << 10) 285 #define PMCS_WORK_FLAG_DEREGISTER_DEV (1 << 11) 286 287 /* 288 * This structure is used by this function to test MPI (and interrupts) 289 * after MPI has been started to make sure it's working reliably. 290 */ 291 typedef struct { 292 uint32_t signature; 293 uint32_t count; 294 uint32_t *ptr; 295 } echo_test_t; 296 #define ECHO_SIGNATURE 0xbebebeef 297 298 /* 299 * Tag Architecture. The PMC has 32 bit tags for MPI messages. 300 * We use this tag this way. 301 * 302 * bits what 303 * ------------------------ 304 * 31 done bit 305 * 30..28 tag type 306 * 27..12 rolling serial number 307 * 11..0 index into work area to get pmcwork structure 308 * 309 * A tag type of NONE means that nobody is waiting on any results, 310 * so the interrupt code frees the work structure that has this 311 * tag. 312 * 313 * A tag type of CBACK means that the the interrupt handler 314 * takes the tag 'arg' in the work structure to be a callback 315 * function pointer (see pmcs_cb_t). The callee is responsible 316 * for freeing the work structure that has this tag. 317 * 318 * A tag type of WAIT means that the issuer of the work needs 319 * be woken up from interrupt level when the command completes 320 * (or times out). If work structure tag 'arg' is non-null, 321 * up to 2*PMCS_QENTRY_SIZE bits of data from the Outbound Queue 322 * entry may be copied to the area pointed to by 'arg'. This 323 * allows issuers to get directly at the results of the command 324 * they issed. The synchronization point for the issuer and the 325 * interrupt code for command done notification is the setting 326 * of the 'DONE' bit in the tag as stored in the work structure. 327 */ 328 #define PMCS_TAG_TYPE_FREE 0 329 #define PMCS_TAG_TYPE_NONE 1 330 #define PMCS_TAG_TYPE_CBACK 2 331 #define PMCS_TAG_TYPE_WAIT 3 332 #define PMCS_TAG_TYPE_SHIFT 28 333 #define PMCS_TAG_SERNO_SHIFT 12 334 #define PMCS_TAG_INDEX_SHIFT 0 335 #define PMCS_TAG_TYPE_MASK 0x70000000 336 #define PMCS_TAG_DONE 0x80000000 337 #define PMCS_TAG_SERNO_MASK 0x0ffff000 338 #define PMCS_TAG_INDEX_MASK 0x00000fff 339 #define PMCS_TAG_TYPE(x) \ 340 (((x) & PMCS_TAG_TYPE_MASK) >> PMCS_TAG_TYPE_SHIFT) 341 #define PMCS_TAG_SERNO(x) \ 342 (((x) & PMCS_TAG_SERNO_MASK) >> PMCS_TAG_SERNO_SHIFT) 343 #define PMCS_TAG_INDEX(x) \ 344 (((x) & PMCS_TAG_INDEX_MASK) >> PMCS_TAG_INDEX_SHIFT) 345 #define PMCS_TAG_FREE 0 346 #define PMCS_COMMAND_DONE(x) \ 347 (((x)->htag == PMCS_TAG_FREE) || (((x)->htag & PMCS_TAG_DONE) != 0)) 348 #define PMCS_COMMAND_ACTIVE(x) \ 349 ((x)->htag != PMCS_TAG_FREE && (x)->state == PMCS_WORK_STATE_ONCHIP) 350 351 /* 352 * Miscellaneous Definitions 353 */ 354 #define CLEAN_MESSAGE(m, x) { \ 355 int _j = x; \ 356 while (_j < PMCS_MSG_SIZE) { \ 357 m[_j++] = 0; \ 358 } \ 359 } 360 361 #define COPY_MESSAGE(t, f, a) { \ 362 int _j; \ 363 for (_j = 0; _j < a; _j++) { \ 364 t[_j] = f[_j]; \ 365 } \ 366 while (_j < PMCS_MSG_SIZE) { \ 367 t[_j++] = 0; \ 368 } \ 369 } 370 371 #define PMCS_PHY_ADDRESSABLE(pp) \ 372 ((pp)->level == 0 && (pp)->dtype == SATA && \ 373 ((pp)->sas_address[0] >> 4) != 5) 374 375 #define RESTART_DISCOVERY(pwp) \ 376 ASSERT(!mutex_owned(&pwp->config_lock)); \ 377 mutex_enter(&pwp->config_lock); \ 378 pwp->config_changed = B_TRUE; \ 379 mutex_exit(&pwp->config_lock); \ 380 SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER); 381 382 #define RESTART_DISCOVERY_LOCKED(pwp) \ 383 ASSERT(mutex_owned(&pwp->config_lock)); \ 384 pwp->config_changed = B_TRUE; \ 385 SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER); 386 387 #define PHY_CHANGED(pwp, p) \ 388 pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, p, NULL, "%s changed in " \ 389 "%s line %d", p->path, __func__, __LINE__); \ 390 p->changed = 1 391 392 #define PHY_CHANGED_AT_LOCATION(pwp, p, func, line) \ 393 pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, p, NULL, "%s changed in " \ 394 "%s line %d", p->path, func, line); \ 395 p->changed = 1 396 397 #define PHY_TYPE(pptr) \ 398 (((pptr)->dtype == NOTHING)? "NOTHING" : \ 399 (((pptr)->dtype == SATA)? "SATA" : \ 400 (((pptr)->dtype == SAS)? "SAS" : "EXPANDER"))) 401 402 #define IS_ROOT_PHY(pptr) (pptr->parent == NULL) 403 404 #define PMCS_HIPRI(pwp, oq, c) \ 405 (pwp->hipri_queue & (1 << PMCS_IQ_OTHER)) ? \ 406 (PMCS_IOMB_HIPRI | PMCS_IOMB_IN_SAS(oq, c)) : \ 407 (PMCS_IOMB_IN_SAS(oq, c)) 408 409 #define SCHEDULE_WORK(hwp, wrk) \ 410 (void) atomic_set_long_excl(&hwp->work_flags, wrk) 411 412 /* 413 * Check to see if the requested work bit is set. Either way, the bit will 414 * be cleared upon return. 415 */ 416 #define WORK_SCHEDULED(hwp, wrk) \ 417 (atomic_clear_long_excl(&hwp->work_flags, wrk) == 0) 418 419 /* 420 * Check to see if the requested work bit is set. The value will not be 421 * changed in this case. The atomic_xx_nv operations can be quite expensive 422 * so this should not be used in non-DEBUG code. 423 */ 424 #define WORK_IS_SCHEDULED(hwp, wrk) \ 425 ((atomic_and_ulong_nv(&hwp->work_flags, (ulong_t)-1) & (1 << wrk)) != 0) 426 427 #define WAIT_FOR(p, t, r) \ 428 r = 0; \ 429 while (!PMCS_COMMAND_DONE(p)) { \ 430 clock_t tmp = cv_timedwait(&p->sleep_cv, \ 431 &p->lock, ddi_get_lbolt() + \ 432 drv_usectohz(t * 1000)); \ 433 if (!PMCS_COMMAND_DONE(p) && tmp < 0) { \ 434 r = 1; \ 435 break; \ 436 } \ 437 } 438 439 /* 440 * Signal the next I/O completion thread to start running. 441 */ 442 443 #define PMCS_CQ_RUN_LOCKED(hwp) \ 444 if (!STAILQ_EMPTY(&hwp->cq) || hwp->iocomp_cb_head) { \ 445 pmcs_cq_thr_info_t *cqti; \ 446 cqti = &hwp->cq_info.cq_thr_info \ 447 [hwp->cq_info.cq_next_disp_thr]; \ 448 hwp->cq_info.cq_next_disp_thr++; \ 449 if (hwp->cq_info.cq_next_disp_thr == \ 450 hwp->cq_info.cq_threads) { \ 451 hwp->cq_info.cq_next_disp_thr = 0; \ 452 } \ 453 mutex_enter(&cqti->cq_thr_lock); \ 454 cv_signal(&cqti->cq_cv); \ 455 mutex_exit(&cqti->cq_thr_lock); \ 456 } \ 457 458 #define PMCS_CQ_RUN(hwp) \ 459 mutex_enter(&hwp->cq_lock); \ 460 PMCS_CQ_RUN_LOCKED(hwp); \ 461 mutex_exit(&hwp->cq_lock); 462 463 464 /* 465 * Watchdog/SCSA timer definitions 466 */ 467 /* usecs to SCSA watchdog ticks */ 468 #define US2WT(x) (x)/10 469 470 /* 471 * More misc 472 */ 473 #define BYTE0(x) (((x) >> 0) & 0xff) 474 #define BYTE1(x) (((x) >> 8) & 0xff) 475 #define BYTE2(x) (((x) >> 16) & 0xff) 476 #define BYTE3(x) (((x) >> 24) & 0xff) 477 #define BYTE4(x) (((x) >> 32) & 0xff) 478 #define BYTE5(x) (((x) >> 40) & 0xff) 479 #define BYTE6(x) (((x) >> 48) & 0xff) 480 #define BYTE7(x) (((x) >> 56) & 0xff) 481 #define WORD0(x) (((x) >> 0) & 0xffff) 482 #define WORD1(x) (((x) >> 16) & 0xffff) 483 #define WORD2(x) (((x) >> 32) & 0xffff) 484 #define WORD3(x) (((x) >> 48) & 0xffff) 485 #define DWORD0(x) ((uint32_t)(x)) 486 #define DWORD1(x) ((uint32_t)(((uint64_t)x) >> 32)) 487 488 #define SAS_ADDR_FMT "0x%02x%02x%02x%02x%02x%02x%02x%02x" 489 #define SAS_ADDR_PRT(x) x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7] 490 491 #define PMCS_VALID_LINK_RATE(r) \ 492 ((r == SAS_LINK_RATE_1_5GBIT) || (r == SAS_LINK_RATE_3GBIT) || \ 493 (r == SAS_LINK_RATE_6GBIT)) 494 495 /* 496 * This is here to avoid inclusion of <sys/ctype.h> which is not lint clean. 497 */ 498 #define HEXDIGIT(x) (((x) >= '0' && (x) <= '9') || \ 499 ((x) >= 'a' && (x) <= 'f') || ((x) >= 'A' && (x) <= 'F')) 500 501 502 typedef void (*pmcs_cb_t) (pmcs_hw_t *, pmcwork_t *, uint32_t *); 503 504 /* 505 * Defines and structure used for tracing/logging information 506 */ 507 508 #define PMCS_TBUF_ELEM_SIZE 120 509 510 #ifdef DEBUG 511 #define PMCS_TBUF_NUM_ELEMS_DEF 100000 512 #else 513 #define PMCS_TBUF_NUM_ELEMS_DEF 15000 514 #endif 515 516 #define PMCS_TBUF_UA_MAX_SIZE 32 517 typedef struct { 518 /* Target-specific data */ 519 uint16_t target_num; 520 char target_ua[PMCS_TBUF_UA_MAX_SIZE]; 521 /* PHY-specific data */ 522 uint8_t phy_sas_address[8]; 523 char phy_path[32]; 524 pmcs_dtype_t phy_dtype; 525 /* Log data */ 526 timespec_t timestamp; 527 char buf[PMCS_TBUF_ELEM_SIZE]; 528 } pmcs_tbuf_t; 529 530 /* 531 * Firmware event log header format 532 */ 533 534 typedef struct pmcs_fw_event_hdr_s { 535 uint32_t fw_el_signature; 536 uint32_t fw_el_entry_start_offset; 537 uint32_t fw_el_rsvd1; 538 uint32_t fw_el_buf_size; 539 uint32_t fw_el_rsvd2; 540 uint32_t fw_el_oldest_idx; 541 uint32_t fw_el_latest_idx; 542 uint32_t fw_el_entry_size; 543 } pmcs_fw_event_hdr_t; 544 545 #ifdef __cplusplus 546 } 547 #endif 548 #endif /* _PMCS_DEF_H */ 549