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