The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/twa/tw_cl_intr.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2004-07 Applied Micro Circuits Corporation.
    5  * Copyright (c) 2004-05 Vinod Kashyap
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   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 the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  *      $FreeBSD$
   30  */
   31 
   32 /*
   33  * AMCC'S 3ware driver for 9000 series storage controllers.
   34  *
   35  * Author: Vinod Kashyap
   36  * Modifications by: Adam Radford
   37  * Modifications by: Manjunath Ranganathaiah
   38  */
   39 
   40 /*
   41  * Common Layer interrupt handling functions.
   42  */
   43 
   44 #include "tw_osl_share.h"
   45 #include "tw_cl_share.h"
   46 #include "tw_cl_fwif.h"
   47 #include "tw_cl_ioctl.h"
   48 #include "tw_cl.h"
   49 #include "tw_cl_externs.h"
   50 #include "tw_osl_ioctl.h"
   51 
   52 /*
   53  * Function name:       twa_interrupt
   54  * Description:         Interrupt handler.  Determines the kind of interrupt,
   55  *                      and returns TW_CL_TRUE if it recognizes the interrupt.
   56  *
   57  * Input:               ctlr_handle     -- controller handle
   58  * Output:              None
   59  * Return value:        TW_CL_TRUE -- interrupt recognized
   60  *                      TW_CL_FALSE-- interrupt not recognized
   61  */
   62 TW_INT32
   63 tw_cl_interrupt(struct tw_cl_ctlr_handle *ctlr_handle)
   64 {
   65         struct tw_cli_ctlr_context      *ctlr =
   66                 (struct tw_cli_ctlr_context *)(ctlr_handle->cl_ctlr_ctxt);
   67         TW_UINT32                       status_reg;
   68         TW_INT32                        rc = TW_CL_FALSE;
   69 
   70         tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(), "entered");
   71 
   72         /* If we don't have controller context, bail */
   73         if (ctlr == NULL)
   74                 goto out;
   75 
   76         /*
   77          * Bail If we get an interrupt while resetting, or shutting down.
   78          */
   79         if (ctlr->reset_in_progress || !(ctlr->active))
   80                 goto out;
   81 
   82         /* Read the status register to determine the type of interrupt. */
   83         status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr_handle);
   84         if (tw_cli_check_ctlr_state(ctlr, status_reg))
   85                 goto out;
   86 
   87         /* Clear the interrupt. */
   88         if (status_reg & TWA_STATUS_HOST_INTERRUPT) {
   89                 tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
   90                         "Host interrupt");
   91                 TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
   92                         TWA_CONTROL_CLEAR_HOST_INTERRUPT);
   93         }
   94         if (status_reg & TWA_STATUS_ATTENTION_INTERRUPT) {
   95                 tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
   96                         "Attention interrupt");
   97                 rc |= TW_CL_TRUE; /* request for a deferred isr call */
   98                 tw_cli_process_attn_intr(ctlr);
   99                 TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
  100                         TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT);
  101         }
  102         if (status_reg & TWA_STATUS_COMMAND_INTERRUPT) {
  103                 tw_cli_dbg_printf(6, ctlr_handle, tw_osl_cur_func(),
  104                         "Command interrupt");
  105                 rc |= TW_CL_TRUE; /* request for a deferred isr call */
  106                 tw_cli_process_cmd_intr(ctlr);
  107                 if ((TW_CL_Q_FIRST_ITEM(&(ctlr->req_q_head[TW_CLI_PENDING_Q]))) == TW_CL_NULL)
  108                         TW_CLI_WRITE_CONTROL_REGISTER(ctlr_handle,
  109                                 TWA_CONTROL_MASK_COMMAND_INTERRUPT);
  110         }
  111         if (status_reg & TWA_STATUS_RESPONSE_INTERRUPT) {
  112                 tw_cli_dbg_printf(10, ctlr_handle, tw_osl_cur_func(),
  113                         "Response interrupt");
  114                 rc |= TW_CL_TRUE; /* request for a deferred isr call */
  115                 tw_cli_process_resp_intr(ctlr);
  116         }
  117 out:
  118         return(rc);
  119 }
  120 
  121 /*
  122  * Function name:       tw_cli_process_host_intr
  123  * Description:         This function gets called if we triggered an interrupt.
  124  *                      We don't use it as of now.
  125  *
  126  * Input:               ctlr    -- ptr to CL internal ctlr context
  127  * Output:              None
  128  * Return value:        None
  129  */
  130 TW_VOID
  131 tw_cli_process_host_intr(struct tw_cli_ctlr_context *ctlr)
  132 {
  133         tw_cli_dbg_printf(6, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  134 }
  135 
  136 /*
  137  * Function name:       tw_cli_process_attn_intr
  138  * Description:         This function gets called if the fw posted an AEN
  139  *                      (Asynchronous Event Notification).  It fetches
  140  *                      all the AEN's that the fw might have posted.
  141  *
  142  * Input:               ctlr    -- ptr to CL internal ctlr context
  143  * Output:              None
  144  * Return value:        None
  145  */
  146 TW_VOID
  147 tw_cli_process_attn_intr(struct tw_cli_ctlr_context *ctlr)
  148 {
  149         TW_INT32        error;
  150 
  151         tw_cli_dbg_printf(6, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  152 
  153         if ((error = tw_cli_get_aen(ctlr))) {
  154                 /*
  155                  * If the driver is already in the process of retrieveing AEN's,
  156                  * we will be returned TW_OSL_EBUSY.  In this case,
  157                  * tw_cli_param_callback or tw_cli_aen_callback will eventually
  158                  * retrieve the AEN this attention interrupt is for.  So, we
  159                  * don't need to print the failure.
  160                  */ 
  161                 if (error != TW_OSL_EBUSY)
  162                         tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
  163                                 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
  164                                 0x1200, 0x1, TW_CL_SEVERITY_ERROR_STRING,
  165                                 "Failed to fetch AEN",
  166                                 "error = %d", error);
  167         }
  168 }
  169 
  170 /*
  171  * Function name:       tw_cli_process_cmd_intr
  172  * Description:         This function gets called if we hit a queue full
  173  *                      condition earlier, and the fw is now ready for
  174  *                      new cmds.  Submits any pending requests.
  175  *
  176  * Input:               ctlr    -- ptr to CL internal ctlr context
  177  * Output:              None
  178  * Return value:        None
  179  */
  180 TW_VOID
  181 tw_cli_process_cmd_intr(struct tw_cli_ctlr_context *ctlr)
  182 {
  183         tw_cli_dbg_printf(6, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  184 
  185         /* Start any requests that might be in the pending queue. */
  186         tw_cli_submit_pending_queue(ctlr);
  187 
  188         /*
  189          * If tw_cli_submit_pending_queue was unsuccessful due to a "cmd queue
  190          * full" condition, cmd_intr will already have been unmasked by
  191          * tw_cli_submit_cmd.  We don't need to do it again... simply return.
  192          */
  193 }
  194 
  195 /*
  196  * Function name:       tw_cli_process_resp_intr
  197  * Description:         Looks for cmd completions from fw; queues cmds completed
  198  *                      by fw into complete queue.
  199  *
  200  * Input:               ctlr    -- ptr to CL internal ctlr context
  201  * Output:              None
  202  * Return value:        0       -- no ctlr error
  203  *                      non-zero-- ctlr error
  204  */
  205 TW_INT32
  206 tw_cli_process_resp_intr(struct tw_cli_ctlr_context *ctlr)
  207 {
  208         TW_UINT32                       resp;
  209         struct tw_cli_req_context       *req;
  210         TW_INT32                        error;
  211         TW_UINT32                       status_reg;
  212     
  213         tw_cli_dbg_printf(10, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  214 
  215         for (;;) {
  216                 status_reg = TW_CLI_READ_STATUS_REGISTER(ctlr->ctlr_handle);
  217                 if ((error = tw_cli_check_ctlr_state(ctlr, status_reg)))
  218                         break;
  219                 if (status_reg & TWA_STATUS_RESPONSE_QUEUE_EMPTY) {
  220                         tw_cli_dbg_printf(7, ctlr->ctlr_handle,
  221                                 tw_osl_cur_func(), "Response queue empty");
  222                         break;
  223                 }
  224 
  225                 /* Response queue is not empty. */
  226                 resp = TW_CLI_READ_RESPONSE_QUEUE(ctlr->ctlr_handle);
  227                 {
  228                         req = &(ctlr->req_ctxt_buf[GET_RESP_ID(resp)]);
  229                 }
  230 
  231                 if (req->state != TW_CLI_REQ_STATE_BUSY) {
  232                         tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
  233                                 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
  234                                 0x1201, 0x1, TW_CL_SEVERITY_ERROR_STRING,
  235                                 "Unposted command completed!!",
  236                                 "request = %p, status = %d",
  237                                 req, req->state);
  238 #ifdef TW_OSL_DEBUG
  239                         tw_cl_print_ctlr_stats(ctlr->ctlr_handle);
  240 #endif /* TW_OSL_DEBUG */
  241                         continue;
  242                 }
  243 
  244                 /*
  245                  * Remove the request from the busy queue, mark it as complete,
  246                  * and enqueue it in the complete queue.
  247                  */
  248                 tw_cli_req_q_remove_item(req, TW_CLI_BUSY_Q);
  249                 req->state = TW_CLI_REQ_STATE_COMPLETE;
  250                 tw_cli_req_q_insert_tail(req, TW_CLI_COMPLETE_Q);
  251         }
  252 
  253         /* Complete this, and other requests in the complete queue. */
  254         tw_cli_process_complete_queue(ctlr);
  255 
  256         return(error);
  257 }
  258 
  259 /*
  260  * Function name:       tw_cli_submit_pending_queue
  261  * Description:         Kick starts any requests in the pending queue.
  262  *
  263  * Input:               ctlr    -- ptr to CL internal ctlr context
  264  * Output:              None
  265  * Return value:        0       -- all pending requests submitted successfully
  266  *                      non-zero-- otherwise
  267  */
  268 TW_INT32
  269 tw_cli_submit_pending_queue(struct tw_cli_ctlr_context *ctlr)
  270 {
  271         struct tw_cli_req_context       *req;
  272         TW_INT32                        error = TW_OSL_ESUCCESS;
  273     
  274         tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  275 
  276         /*
  277          * Pull requests off the pending queue, and submit them.
  278          */
  279         while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_PENDING_Q)) !=
  280                 TW_CL_NULL) {
  281                 if ((error = tw_cli_submit_cmd(req))) {
  282                         if (error == TW_OSL_EBUSY) {
  283                                 tw_cli_dbg_printf(2, ctlr->ctlr_handle,
  284                                         tw_osl_cur_func(),
  285                                         "Requeueing pending request");
  286                                 req->state = TW_CLI_REQ_STATE_PENDING;
  287                                 /*
  288                                  * Queue the request at the head of the pending
  289                                  * queue, and break away, so we don't try to
  290                                  * submit any more requests.
  291                                  */
  292                                 tw_cli_req_q_insert_head(req, TW_CLI_PENDING_Q);
  293                                 break;
  294                         } else {
  295                                 tw_cl_create_event(ctlr->ctlr_handle,
  296                                         TW_CL_FALSE,
  297                                         TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
  298                                         0x1202, 0x1,
  299                                         TW_CL_SEVERITY_ERROR_STRING,
  300                                         "Could not start request "
  301                                         "in pending queue",
  302                                         "request = %p, opcode = 0x%x, "
  303                                         "error = %d", req,
  304                                         GET_OPCODE(req->cmd_pkt->
  305                                                 command.cmd_pkt_9k.res__opcode),
  306                                         error);
  307                                 /*
  308                                  * Set the appropriate error and call the CL
  309                                  * internal callback if there's one.  If the
  310                                  * request originator is polling for completion,
  311                                  * he should be checking req->error to
  312                                  * determine that the request did not go
  313                                  * through.  The request originators are
  314                                  * responsible for the clean-up.
  315                                  */
  316                                 req->error_code = error;
  317                                 req->state = TW_CLI_REQ_STATE_COMPLETE;
  318                                 if (req->tw_cli_callback)
  319                                         req->tw_cli_callback(req);
  320                                 error = TW_OSL_ESUCCESS;
  321                         }
  322                 }
  323         }
  324         return(error);
  325 }
  326 
  327 /*
  328  * Function name:       tw_cli_process_complete_queue
  329  * Description:         Calls the CL internal callback routine, if any, for
  330  *                      each request in the complete queue.
  331  *
  332  * Input:               ctlr    -- ptr to CL internal ctlr context
  333  * Output:              None
  334  * Return value:        None
  335  */
  336 TW_VOID
  337 tw_cli_process_complete_queue(struct tw_cli_ctlr_context *ctlr)
  338 {
  339         struct tw_cli_req_context       *req;
  340     
  341         tw_cli_dbg_printf(10, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  342 
  343         /*
  344          * Pull commands off the completed list, dispatch them appropriately.
  345          */
  346         while ((req = tw_cli_req_q_remove_head(ctlr, TW_CLI_COMPLETE_Q)) !=
  347                 TW_CL_NULL) {
  348                 /* Call the CL internal callback, if there's one. */
  349                 if (req->tw_cli_callback)
  350                         req->tw_cli_callback(req);
  351         }
  352 }
  353 
  354 /*
  355  * Function name:       tw_cli_complete_io
  356  * Description:         CL internal callback for SCSI/fw passthru requests.
  357  *
  358  * Input:               req     -- ptr to CL internal request context
  359  * Output:              None
  360  * Return value:        None
  361  */
  362 TW_VOID
  363 tw_cli_complete_io(struct tw_cli_req_context *req)
  364 {
  365         struct tw_cli_ctlr_context      *ctlr = req->ctlr;
  366         struct tw_cl_req_packet         *req_pkt =
  367                 (struct tw_cl_req_packet *)(req->orig_req);
  368 
  369         tw_cli_dbg_printf(8, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  370 
  371         req_pkt->status = TW_CL_ERR_REQ_SUCCESS;
  372         if (req->error_code) {
  373                 req_pkt->status = TW_CL_ERR_REQ_UNABLE_TO_SUBMIT_COMMAND;
  374                 goto out;
  375         }
  376 
  377         if (req->state != TW_CLI_REQ_STATE_COMPLETE) {
  378                 tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
  379                         TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
  380                         0x1203, 0x1, TW_CL_SEVERITY_ERROR_STRING,
  381                         "I/O completion on incomplete command!!",
  382                         "request = %p, status = %d",
  383                         req, req->state);
  384 #ifdef TW_OSL_DEBUG
  385                 tw_cl_print_ctlr_stats(ctlr->ctlr_handle);
  386 #endif /* TW_OSL_DEBUG */
  387                 return;
  388         }
  389 
  390         if (req->flags & TW_CLI_REQ_FLAGS_PASSTHRU) {
  391                 /* Copy the command packet back into OSL's space. */
  392                 tw_osl_memcpy(req_pkt->gen_req_pkt.pt_req.cmd_pkt, req->cmd_pkt,
  393                         sizeof(struct tw_cl_command_packet));
  394         } else
  395                 tw_cli_scsi_complete(req);
  396 
  397 out:
  398         req_pkt->tw_osl_callback(req->req_handle);
  399         tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
  400 }
  401 
  402 /*
  403  * Function name:       tw_cli_scsi_complete
  404  * Description:         Completion routine for SCSI requests.
  405  *
  406  * Input:               req     -- ptr to CL internal request context
  407  * Output:              None
  408  * Return value:        None
  409  */
  410 TW_VOID
  411 tw_cli_scsi_complete(struct tw_cli_req_context *req)
  412 {
  413         struct tw_cl_req_packet         *req_pkt =
  414                 (struct tw_cl_req_packet *)(req->orig_req);
  415         struct tw_cl_scsi_req_packet    *scsi_req =
  416                 &(req_pkt->gen_req_pkt.scsi_req);
  417         struct tw_cl_command_9k         *cmd =
  418                 &(req->cmd_pkt->command.cmd_pkt_9k);
  419         struct tw_cl_command_header     *cmd_hdr;
  420         TW_UINT16                       error;
  421         TW_UINT8                        *cdb;
  422 
  423         tw_cli_dbg_printf(8, req->ctlr->ctlr_handle, tw_osl_cur_func(),
  424                 "entered");
  425 
  426         scsi_req->scsi_status = cmd->status;
  427         if (! cmd->status)
  428                 return;
  429 
  430         tw_cli_dbg_printf(1, req->ctlr->ctlr_handle, tw_osl_cur_func(),
  431                 "req_id = 0x%x, status = 0x%x",
  432                 GET_REQ_ID(cmd->lun_l4__req_id), cmd->status);
  433 
  434         cmd_hdr = &(req->cmd_pkt->cmd_hdr);
  435         error = cmd_hdr->status_block.error;
  436         if ((error == TWA_ERROR_LOGICAL_UNIT_NOT_SUPPORTED) ||
  437                         (error == TWA_ERROR_UNIT_OFFLINE)) {
  438                 if (GET_LUN_L4(cmd->lun_l4__req_id))
  439                         req_pkt->status |= TW_CL_ERR_REQ_INVALID_LUN;
  440                 else
  441                         req_pkt->status |= TW_CL_ERR_REQ_INVALID_TARGET;
  442         } else {
  443                 tw_cli_dbg_printf(2, req->ctlr->ctlr_handle,
  444                         tw_osl_cur_func(),
  445                         "cmd = %x %x %x %x %x %x %x",
  446                         GET_OPCODE(cmd->res__opcode),
  447                         GET_SGL_OFF(cmd->res__opcode),
  448                         cmd->unit,
  449                         cmd->lun_l4__req_id,
  450                         cmd->status,
  451                         cmd->sgl_offset,
  452                         cmd->lun_h4__sgl_entries);
  453 
  454                 cdb = (TW_UINT8 *)(cmd->cdb);
  455                 tw_cli_dbg_printf(2, req->ctlr->ctlr_handle,
  456                         tw_osl_cur_func(),
  457                         "cdb = %x %x %x %x %x %x %x %x "
  458                         "%x %x %x %x %x %x %x %x",
  459                         cdb[0], cdb[1], cdb[2], cdb[3],
  460                         cdb[4], cdb[5], cdb[6], cdb[7],
  461                         cdb[8], cdb[9], cdb[10], cdb[11],
  462                         cdb[12], cdb[13], cdb[14], cdb[15]);
  463 
  464 #if       0
  465                 /* 
  466                  * Print the error. Firmware doesn't yet support
  467                  * the 'Mode Sense' cmd.  Don't print if the cmd
  468                  * is 'Mode Sense', and the error is 'Invalid field
  469                  * in CDB'.
  470                  */
  471                 if (! ((cdb[0] == 0x1A) && (error == 0x10D)))
  472                         tw_cli_create_ctlr_event(req->ctlr,
  473                                 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
  474                                 cmd_hdr);
  475 #endif // 0
  476         }
  477 
  478         if (scsi_req->sense_data) {
  479                 tw_osl_memcpy(scsi_req->sense_data, cmd_hdr->sense_data,
  480                         TWA_SENSE_DATA_LENGTH);
  481                 scsi_req->sense_len = TWA_SENSE_DATA_LENGTH;
  482                 req_pkt->status |= TW_CL_ERR_REQ_AUTO_SENSE_VALID;
  483         }
  484         req_pkt->status |= TW_CL_ERR_REQ_SCSI_ERROR;
  485 }
  486 
  487 /*
  488  * Function name:       tw_cli_param_callback
  489  * Description:         Callback for get/set_param requests.
  490  *
  491  * Input:               req     -- ptr to completed request pkt
  492  * Output:              None
  493  * Return value:        None
  494  */
  495 TW_VOID
  496 tw_cli_param_callback(struct tw_cli_req_context *req)
  497 {
  498         struct tw_cli_ctlr_context      *ctlr = req->ctlr;
  499         union tw_cl_command_7k          *cmd =
  500                 &(req->cmd_pkt->command.cmd_pkt_7k);
  501         TW_INT32                        error;
  502 
  503         tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  504 
  505         /*
  506          * If the request was never submitted to the controller, the function
  507          * that sets req->error is responsible for calling tw_cl_create_event.
  508          */
  509         if (! req->error_code)
  510                 if (cmd->param.status) {
  511 #if       0
  512                         tw_cli_create_ctlr_event(ctlr,
  513                                 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
  514                                 &(req->cmd_pkt->cmd_hdr));
  515 #endif // 0
  516                         tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
  517                                 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
  518                                 0x1204, 0x1, TW_CL_SEVERITY_ERROR_STRING,
  519                                 "get/set_param failed",
  520                                 "status = %d", cmd->param.status);
  521                 }
  522 
  523         ctlr->internal_req_busy = TW_CL_FALSE;
  524         tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
  525 
  526         if ((ctlr->get_more_aens) && (!(ctlr->reset_in_progress))) {
  527                 ctlr->get_more_aens = TW_CL_FALSE;
  528                 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
  529                         "Fetching more AEN's");
  530                 if ((error = tw_cli_get_aen(ctlr)))
  531                         tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
  532                                 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
  533                                 0x1205, 0x1, TW_CL_SEVERITY_ERROR_STRING,
  534                                 "Failed to fetch all AEN's from param_callback",
  535                                 "error = %d", error);
  536         }
  537 }
  538 
  539 /*
  540  * Function name:       tw_cli_aen_callback
  541  * Description:         Callback for requests to fetch AEN's.
  542  *
  543  * Input:               req     -- ptr to completed request pkt
  544  * Output:              None
  545  * Return value:        None
  546  */
  547 TW_VOID
  548 tw_cli_aen_callback(struct tw_cli_req_context *req)
  549 {
  550         struct tw_cli_ctlr_context      *ctlr = req->ctlr;
  551         struct tw_cl_command_header     *cmd_hdr;
  552         struct tw_cl_command_9k         *cmd =
  553                 &(req->cmd_pkt->command.cmd_pkt_9k);
  554         TW_UINT16                       aen_code = TWA_AEN_QUEUE_EMPTY;
  555         TW_INT32                        error;
  556 
  557         tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  558 
  559         tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
  560                 "req_id = 0x%x, req error = %d, status = 0x%x",
  561                 GET_REQ_ID(cmd->lun_l4__req_id), req->error_code, cmd->status);
  562 
  563         /*
  564          * If the request was never submitted to the controller, the function
  565          * that sets error is responsible for calling tw_cl_create_event.
  566          */
  567         if (!(error = req->error_code))
  568                 if ((error = cmd->status)) {
  569                         cmd_hdr = (struct tw_cl_command_header *)
  570                                 (&(req->cmd_pkt->cmd_hdr));
  571 #if       0
  572                         tw_cli_create_ctlr_event(ctlr,
  573                                 TW_CL_MESSAGE_SOURCE_CONTROLLER_ERROR,
  574                                 cmd_hdr);
  575 #endif // 0
  576                         tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
  577                                 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
  578                                 0x1206, 0x1, TW_CL_SEVERITY_ERROR_STRING,
  579                                 "Request Sense failed",
  580                                 "opcode = 0x%x, status = %d",
  581                                 GET_OPCODE(cmd->res__opcode), cmd->status);
  582                 }
  583 
  584         if (error) {
  585                 ctlr->internal_req_busy = TW_CL_FALSE;
  586                 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
  587                 return;
  588         }
  589 
  590         tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
  591                 "Request Sense command succeeded");
  592 
  593         aen_code = tw_cli_manage_aen(ctlr, req);
  594 
  595         if (aen_code != TWA_AEN_SYNC_TIME_WITH_HOST) {
  596                 ctlr->internal_req_busy = TW_CL_FALSE;
  597                 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
  598                 if (aen_code != TWA_AEN_QUEUE_EMPTY)
  599                         if ((error = tw_cli_get_aen(ctlr)))
  600                                 tw_cl_create_event(ctlr->ctlr_handle,
  601                                         TW_CL_FALSE,
  602                                         TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
  603                                         0x1207, 0x1,
  604                                         TW_CL_SEVERITY_ERROR_STRING,
  605                                         "Failed to fetch all AEN's",
  606                                         "error = %d", error);
  607         }
  608 }
  609 
  610 /*
  611  * Function name:       tw_cli_manage_aen
  612  * Description:         Handles AEN's.
  613  *
  614  * Input:               ctlr    -- ptr to CL internal ctlr context
  615  *                      req     -- ptr to CL internal request context
  616  * Output:              None
  617  * Return value:        None
  618  */
  619 TW_UINT16
  620 tw_cli_manage_aen(struct tw_cli_ctlr_context *ctlr,
  621         struct tw_cli_req_context *req)
  622 {
  623         struct tw_cl_command_header     *cmd_hdr;
  624         TW_UINT16                       aen_code;
  625         TW_TIME                         local_time;
  626         TW_TIME                         sync_time;
  627         TW_UINT32                       error;
  628 
  629         tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  630 
  631         cmd_hdr = (struct tw_cl_command_header *)(req->data);
  632         aen_code = cmd_hdr->status_block.error;
  633 
  634         switch (aen_code) {
  635         case TWA_AEN_SYNC_TIME_WITH_HOST:
  636                 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
  637                         "Received AEN_SYNC_TIME");
  638                 /*
  639                  * Free the internal req pkt right here, since
  640                  * tw_cli_set_param will need it.
  641                  */
  642                 ctlr->internal_req_busy = TW_CL_FALSE;
  643                 tw_cli_req_q_insert_tail(req, TW_CLI_FREE_Q);
  644 
  645                 /*
  646                  * We will use a callback in tw_cli_set_param only when
  647                  * interrupts are enabled and we can expect our callback
  648                  * to get called.  Setting the get_more_aens
  649                  * flag will make the callback continue to try to retrieve
  650                  * more AEN's.
  651                  */
  652                 if (ctlr->interrupts_enabled)
  653                         ctlr->get_more_aens = TW_CL_TRUE;
  654                 /* Calculate time (in seconds) since last Sunday 12.00 AM. */
  655                 local_time = tw_osl_get_local_time();
  656                 sync_time = (local_time - (3 * 86400)) % 604800;
  657                 if ((error = tw_cli_set_param(ctlr, TWA_PARAM_TIME_TABLE,
  658                                 TWA_PARAM_TIME_SCHED_TIME, 4,
  659                                 &sync_time,
  660                                 (ctlr->interrupts_enabled)
  661                                 ? tw_cli_param_callback : TW_CL_NULL)))
  662                         tw_cl_create_event(ctlr->ctlr_handle, TW_CL_FALSE,
  663                                 TW_CL_MESSAGE_SOURCE_COMMON_LAYER_ERROR,
  664                                 0x1208, 0x1, TW_CL_SEVERITY_ERROR_STRING,
  665                                 "Unable to sync time with ctlr",
  666                                 "error = %d", error);
  667 
  668                 break;
  669 
  670         case TWA_AEN_QUEUE_EMPTY:
  671                 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
  672                         "AEN queue empty");
  673                 break;
  674 
  675         default:
  676                 /* Queue the event. */
  677 
  678                 tw_cli_dbg_printf(4, ctlr->ctlr_handle, tw_osl_cur_func(),
  679                         "Queueing AEN");
  680                 tw_cli_create_ctlr_event(ctlr,
  681                         TW_CL_MESSAGE_SOURCE_CONTROLLER_EVENT,
  682                         cmd_hdr);
  683                 break;
  684         } /* switch */
  685         return(aen_code);
  686 }
  687 
  688 /*
  689  * Function name:       tw_cli_enable_interrupts
  690  * Description:         Enables interrupts on the controller
  691  *
  692  * Input:               ctlr    -- ptr to CL internal ctlr context
  693  * Output:              None
  694  * Return value:        None
  695  */
  696 TW_VOID
  697 tw_cli_enable_interrupts(struct tw_cli_ctlr_context *ctlr)
  698 {
  699         tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  700 
  701         ctlr->interrupts_enabled = TW_CL_TRUE;
  702         TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
  703                 TWA_CONTROL_CLEAR_ATTENTION_INTERRUPT |
  704                 TWA_CONTROL_UNMASK_RESPONSE_INTERRUPT |
  705                 TWA_CONTROL_ENABLE_INTERRUPTS);
  706 }
  707 
  708 /*
  709  * Function name:       twa_setup
  710  * Description:         Disables interrupts on the controller
  711  *
  712  * Input:               ctlr    -- ptr to CL internal ctlr context
  713  * Output:              None
  714  * Return value:        None
  715  */
  716 TW_VOID
  717 tw_cli_disable_interrupts(struct tw_cli_ctlr_context *ctlr)
  718 {
  719         tw_cli_dbg_printf(3, ctlr->ctlr_handle, tw_osl_cur_func(), "entered");
  720 
  721         TW_CLI_WRITE_CONTROL_REGISTER(ctlr->ctlr_handle,
  722                 TWA_CONTROL_DISABLE_INTERRUPTS);
  723         ctlr->interrupts_enabled = TW_CL_FALSE;
  724 }

Cache object: 6deee3ea2f419dc97a715571e04ad8d8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.