1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 2010, LSI Corp. 5 * All rights reserved. 6 * Author : Manjunath Ranganathaiah 7 * Support: freebsdraid@lsi.com 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 3. Neither the name of the <ORGANIZATION> nor the names of its 20 * contributors may be used to endorse or promote products derived 21 * from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 27 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 31 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 33 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 #include <dev/tws/tws.h> 38 #include <dev/tws/tws_hdm.h> 39 #include <dev/tws/tws_services.h> 40 #include <sys/time.h> 41 42 void tws_q_insert_tail(struct tws_softc *sc, struct tws_request *req, 43 u_int8_t q_type ); 44 struct tws_request * tws_q_remove_request(struct tws_softc *sc, 45 struct tws_request *req, u_int8_t q_type ); 46 struct tws_request *tws_q_remove_head(struct tws_softc *sc, u_int8_t q_type ); 47 void tws_q_insert_head(struct tws_softc *sc, struct tws_request *req, 48 u_int8_t q_type ); 49 struct tws_request * tws_q_remove_tail(struct tws_softc *sc, u_int8_t q_type ); 50 void tws_print_stats(void *arg); 51 52 struct tws_sense *tws_find_sense_from_mfa(struct tws_softc *sc, u_int64_t mfa); 53 54 static struct error_desc array[] = { 55 { "Cannot add sysctl tree node", 0x2000, ERROR, 56 "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" }, 57 { "Register window not available", 0x2001, ERROR, 58 "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" }, 59 { "Can't allocate register window", 0x2002, ERROR, 60 "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" }, 61 { "Can't allocate interrupt", 0x2003, ERROR, 62 "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" }, 63 { "Can't set up interrupt", 0x2004, ERROR, 64 "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" }, 65 { "Couldn't intialize CAM", 0x2007, ERROR, 66 "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" }, 67 { "Couldn't create SIM device queue", 0x2100, ENOMEM, 68 "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" }, 69 { "Unable to create SIM entry", 0x2101, ENOMEM, 70 "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" }, 71 { "Unable to register the bus", 0x2102, ENXIO, 72 "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" }, 73 { "Unable to create the path", 0x2103, ENXIO, 74 "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" }, 75 { "Bus scan request to CAM failed", 0x2104, ENXIO, 76 "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" }, 77 { "Unable to intialize the driver", 0x2008, ENXIO, 78 "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" }, 79 { "Unable to intialize the controller", 0x2009, ENXIO, 80 "%s: (0x%02X: 0x%04X): %s:\n", "ERROR" }, 81 }; 82 83 void 84 tws_trace(const char *file, const char *fun, int linenum, 85 struct tws_softc *sc, char *desc, u_int64_t val1, u_int64_t val2) 86 { 87 88 struct tws_trace_rec *rec = (struct tws_trace_rec *)sc->trace_q.q; 89 volatile u_int16_t head, tail; 90 char fmt[256]; 91 92 head = sc->trace_q.head; 93 tail = sc->trace_q.tail; 94 /* 95 getnanotime(&rec[tail].ts); 96 */ 97 strncpy(rec[tail].fname, file, TWS_TRACE_FNAME_LEN); 98 strncpy(rec[tail].func, fun, TWS_TRACE_FUNC_LEN); 99 rec[tail].linenum = linenum; 100 strncpy(rec[tail].desc, desc, TWS_TRACE_DESC_LEN); 101 rec[tail].val1 = val1; 102 rec[tail].val2 = val2; 103 104 tail = (tail+1) % sc->trace_q.depth; 105 106 if ( head == tail ) { 107 sc->trace_q.overflow = 1; 108 sc->trace_q.head = (head+1) % sc->trace_q.depth; 109 } 110 sc->trace_q.tail = tail; 111 112 /* 113 tws_circular_q_insert(sc, &sc->trace_q, 114 &rec, sizeof(struct tws_trace_rec)); 115 */ 116 if ( sc->is64bit ) 117 strcpy(fmt, "%05d:%s::%s :%s: 0x%016lx : 0x%016lx \n"); 118 else 119 strcpy(fmt, "%05d:%s::%s :%s: 0x%016llx : 0x%016llx \n"); 120 121 /* 122 printf("%05d:%s::%s :%s: 0x%016llx : 0x%016llx \n", 123 linenum, file, fun, desc, val1, val2); 124 */ 125 printf(fmt, linenum, file, fun, desc, val1, val2); 126 } 127 128 void 129 tws_log(struct tws_softc *sc, int index) 130 { 131 device_printf((sc)->tws_dev, array[index].fmt, 132 array[index].error_str, 133 array[index].error_code, 134 array[index].severity_level, 135 array[index].desc ); 136 } 137 138 /* ----------- swap functions ----------- */ 139 140 u_int16_t 141 tws_swap16(u_int16_t val) 142 { 143 return((val << 8) | (val >> 8)); 144 } 145 146 u_int32_t 147 tws_swap32(u_int32_t val) 148 { 149 return(((val << 24) | ((val << 8) & (0xFF0000)) | 150 ((val >> 8) & (0xFF00)) | (val >> 24))); 151 } 152 153 u_int64_t 154 tws_swap64(u_int64_t val) 155 { 156 return((((u_int64_t)(tws_swap32(((u_int32_t *)(&(val)))[1]))) << 32) | 157 ((u_int32_t)(tws_swap32(((u_int32_t *)(&(val)))[0])))); 158 } 159 160 /* ----------- reg access ----------- */ 161 162 void 163 tws_write_reg(struct tws_softc *sc, int offset, 164 u_int32_t value, int size) 165 { 166 bus_space_tag_t bus_tag = sc->bus_tag; 167 bus_space_handle_t bus_handle = sc->bus_handle; 168 169 if (size == 4) 170 bus_space_write_4(bus_tag, bus_handle, offset, value); 171 else 172 if (size == 2) 173 bus_space_write_2(bus_tag, bus_handle, offset, 174 (u_int16_t)value); 175 else 176 bus_space_write_1(bus_tag, bus_handle, offset, (u_int8_t)value); 177 } 178 179 u_int32_t 180 tws_read_reg(struct tws_softc *sc, int offset, int size) 181 { 182 bus_space_tag_t bus_tag = sc->bus_tag; 183 bus_space_handle_t bus_handle = sc->bus_handle; 184 185 if (size == 4) 186 return((u_int32_t)bus_space_read_4(bus_tag, bus_handle, offset)); 187 else if (size == 2) 188 return((u_int32_t)bus_space_read_2(bus_tag, bus_handle, offset)); 189 else 190 return((u_int32_t)bus_space_read_1(bus_tag, bus_handle, offset)); 191 } 192 193 /* --------------------- Q service --------------------- */ 194 195 /* 196 * intialize q pointers with null. 197 */ 198 void 199 tws_init_qs(struct tws_softc *sc) 200 { 201 202 mtx_lock(&sc->q_lock); 203 for(int i=0;i<TWS_MAX_QS;i++) { 204 sc->q_head[i] = NULL; 205 sc->q_tail[i] = NULL; 206 } 207 mtx_unlock(&sc->q_lock); 208 209 } 210 211 /* called with lock held */ 212 static void 213 tws_insert2_empty_q(struct tws_softc *sc, struct tws_request *req, 214 u_int8_t q_type ) 215 { 216 217 mtx_assert(&sc->q_lock, MA_OWNED); 218 req->next = req->prev = NULL; 219 sc->q_head[q_type] = sc->q_tail[q_type] = req; 220 221 } 222 223 /* called with lock held */ 224 void 225 tws_q_insert_head(struct tws_softc *sc, struct tws_request *req, 226 u_int8_t q_type ) 227 { 228 229 mtx_assert(&sc->q_lock, MA_OWNED); 230 if ( sc->q_head[q_type] == NULL ) { 231 tws_insert2_empty_q(sc, req, q_type); 232 } else { 233 req->next = sc->q_head[q_type]; 234 req->prev = NULL; 235 sc->q_head[q_type]->prev = req; 236 sc->q_head[q_type] = req; 237 } 238 239 } 240 241 /* called with lock held */ 242 void 243 tws_q_insert_tail(struct tws_softc *sc, struct tws_request *req, 244 u_int8_t q_type ) 245 { 246 247 mtx_assert(&sc->q_lock, MA_OWNED); 248 if ( sc->q_tail[q_type] == NULL ) { 249 tws_insert2_empty_q(sc, req, q_type); 250 } else { 251 req->prev = sc->q_tail[q_type]; 252 req->next = NULL; 253 sc->q_tail[q_type]->next = req; 254 sc->q_tail[q_type] = req; 255 } 256 257 } 258 259 /* called with lock held */ 260 struct tws_request * 261 tws_q_remove_head(struct tws_softc *sc, u_int8_t q_type ) 262 { 263 264 struct tws_request *r; 265 266 mtx_assert(&sc->q_lock, MA_OWNED); 267 r = sc->q_head[q_type]; 268 if ( !r ) 269 return(NULL); 270 if ( r->next == NULL && r->prev == NULL ) { 271 /* last element */ 272 sc->q_head[q_type] = sc->q_tail[q_type] = NULL; 273 } else { 274 sc->q_head[q_type] = r->next; 275 r->next->prev = NULL; 276 r->next = NULL; 277 r->prev = NULL; 278 } 279 return(r); 280 } 281 282 /* called with lock held */ 283 struct tws_request * 284 tws_q_remove_tail(struct tws_softc *sc, u_int8_t q_type ) 285 { 286 287 struct tws_request *r; 288 289 mtx_assert(&sc->q_lock, MA_OWNED); 290 r = sc->q_tail[q_type]; 291 if ( !r ) 292 return(NULL); 293 if ( r->next == NULL && r->prev == NULL ) { 294 /* last element */ 295 sc->q_head[q_type] = sc->q_tail[q_type] = NULL; 296 } else { 297 sc->q_tail[q_type] = r->prev; 298 r->prev->next = NULL; 299 r->next = NULL; 300 r->prev = NULL; 301 } 302 return(r); 303 } 304 305 /* returns removed request if successful. return NULL otherwise */ 306 /* called with lock held */ 307 struct tws_request * 308 tws_q_remove_request(struct tws_softc *sc, struct tws_request *req, 309 u_int8_t q_type ) 310 { 311 312 struct tws_request *r; 313 314 mtx_assert(&sc->q_lock, MA_OWNED); 315 if ( req == NULL ) { 316 TWS_TRACE_DEBUG(sc, "null req", 0, q_type); 317 return(NULL); 318 } 319 320 if ( req == sc->q_head[q_type] ) 321 return(tws_q_remove_head(sc, q_type)); 322 if ( req == sc->q_tail[q_type] ) 323 return(tws_q_remove_tail(sc, q_type)); 324 325 /* The given node is not at head or tail. 326 * It's in the middle and there are more than 327 * 2 elements on the q. 328 */ 329 330 if ( req->next == NULL || req->prev == NULL ) { 331 TWS_TRACE_DEBUG(sc, "invalid req", 0, q_type); 332 return(NULL); 333 } 334 335 /* debug only */ 336 r = sc->q_head[q_type]; 337 while ( r ) { 338 if ( req == r ) 339 break; 340 r = r->next; 341 } 342 343 if ( !r ) { 344 TWS_TRACE_DEBUG(sc, "req not in q", 0, req->request_id); 345 return(NULL); 346 } 347 /* debug end */ 348 349 req->prev->next = r->next; 350 req->next->prev = r->prev; 351 req->next = NULL; 352 req->prev = NULL; 353 return(req); 354 } 355 356 struct tws_sense * 357 tws_find_sense_from_mfa(struct tws_softc *sc, u_int64_t mfa) 358 { 359 struct tws_sense *s; 360 int i; 361 TWS_TRACE_DEBUG(sc, "entry",sc,mfa); 362 363 i = (mfa - sc->dma_mem_phys) / sizeof(struct tws_command_packet); 364 if ( i>= 0 && i<tws_queue_depth) { 365 s = &sc->sense_bufs[i]; 366 if ( mfa == s->hdr_pkt_phy ) 367 return(s); 368 } 369 370 TWS_TRACE_DEBUG(sc, "return null",0,mfa); 371 return(NULL); 372 373 } 374 375 /* --------------------- Q service end --------------------- */ 376 /* --------------------- misc service start --------------------- */ 377 378 void 379 tws_print_stats(void *arg) 380 { 381 382 struct tws_softc *sc = (struct tws_softc *)arg; 383 384 TWS_TRACE(sc, "reqs(in, out)", sc->stats.reqs_in, sc->stats.reqs_out); 385 TWS_TRACE(sc, "reqs(err, intrs)", sc->stats.reqs_errored 386 , sc->stats.num_intrs); 387 TWS_TRACE(sc, "reqs(ioctls, scsi)", sc->stats.ioctls 388 , sc->stats.scsi_ios); 389 callout_reset(&sc->stats_timer, 300 * hz, tws_print_stats, sc); 390 } 391 /* --------------------- misc service end --------------------- */ 392