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/smartpqi/smartpqi_cam.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  * Copyright 2016-2021 Microchip Technology, Inc. and/or its subsidiaries.
    3  *
    4  * Redistribution and use in source and binary forms, with or without
    5  * modification, are permitted provided that the following conditions
    6  * are met:
    7  * 1. Redistributions of source code must retain the above copyright
    8  *    notice, this list of conditions and the following disclaimer.
    9  * 2. Redistributions in binary form must reproduce the above copyright
   10  *    notice, this list of conditions and the following disclaimer in the
   11  *    documentation and/or other materials provided with the distribution.
   12  *
   13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   23  * SUCH DAMAGE.
   24  */
   25 
   26 /* $FreeBSD$ */
   27 /*
   28  * CAM interface for smartpqi driver
   29  */
   30 
   31 #include "smartpqi_includes.h"
   32 
   33 /*
   34  * Set cam sim properties of the smartpqi adapter.
   35  */
   36 static void
   37 update_sim_properties(struct cam_sim *sim, struct ccb_pathinq *cpi)
   38 {
   39 
   40         pqisrc_softstate_t *softs = (struct pqisrc_softstate *)
   41                                         cam_sim_softc(sim);
   42 
   43         device_t dev = softs->os_specific.pqi_dev;
   44 
   45         DBG_FUNC("IN\n");
   46 
   47         cpi->version_num = 1;
   48         cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16;
   49         cpi->target_sprt = 0;
   50         cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED;
   51         cpi->hba_eng_cnt = 0;
   52         cpi->max_lun = PQI_MAX_MULTILUN;
   53         cpi->max_target = 1088;
   54         cpi->maxio = (softs->pqi_cap.max_sg_elem - 1) * PAGE_SIZE;
   55         cpi->initiator_id = 255;
   56         strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
   57         strlcpy(cpi->hba_vid, "Microsemi", HBA_IDLEN);
   58         strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
   59         cpi->unit_number = cam_sim_unit(sim);
   60         cpi->bus_id = cam_sim_bus(sim);
   61         cpi->base_transfer_speed = 1200000; /* Base bus speed in KB/sec */
   62         cpi->protocol = PROTO_SCSI;
   63         cpi->protocol_version = SCSI_REV_SPC4;
   64         cpi->transport = XPORT_SPI;
   65         cpi->transport_version = 2;
   66         cpi->ccb_h.status = CAM_REQ_CMP;
   67         cpi->hba_vendor = pci_get_vendor(dev);
   68         cpi->hba_device = pci_get_device(dev);
   69         cpi->hba_subvendor = pci_get_subvendor(dev);
   70         cpi->hba_subdevice = pci_get_subdevice(dev);
   71 
   72 
   73         DBG_FUNC("OUT\n");
   74 }
   75 
   76 /*
   77  * Get transport settings of the smartpqi adapter 
   78  */
   79 static void
   80 get_transport_settings(struct pqisrc_softstate *softs,
   81                 struct ccb_trans_settings *cts)
   82 {
   83         struct ccb_trans_settings_scsi  *scsi = &cts->proto_specific.scsi;
   84         struct ccb_trans_settings_sas   *sas = &cts->xport_specific.sas;
   85         struct ccb_trans_settings_spi   *spi = &cts->xport_specific.spi;
   86 
   87         DBG_FUNC("IN\n");
   88         
   89         cts->protocol = PROTO_SCSI;
   90         cts->protocol_version = SCSI_REV_SPC4;
   91         cts->transport = XPORT_SPI;
   92         cts->transport_version = 2;
   93         spi->valid = CTS_SPI_VALID_DISC;
   94         spi->flags = CTS_SPI_FLAGS_DISC_ENB;
   95         scsi->valid = CTS_SCSI_VALID_TQ;
   96         scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
   97         sas->valid = CTS_SAS_VALID_SPEED;
   98         cts->ccb_h.status = CAM_REQ_CMP;
   99 
  100         DBG_FUNC("OUT\n");
  101 }
  102 
  103 /*
  104  *  Add the target to CAM layer and rescan, when a new device is found
  105  */
  106 void
  107 os_add_device(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
  108 {
  109         union ccb *ccb;
  110 
  111         DBG_FUNC("IN\n");
  112 
  113         if(softs->os_specific.sim_registered) { 
  114                 if ((ccb = xpt_alloc_ccb_nowait()) == NULL) {
  115                         DBG_ERR("rescan failed (can't allocate CCB)\n");
  116                         return;
  117                 }
  118 
  119                 if (xpt_create_path(&ccb->ccb_h.path, NULL,
  120                         cam_sim_path(softs->os_specific.sim),
  121                         device->target, device->lun) != CAM_REQ_CMP) {
  122                         DBG_ERR("rescan failed (can't create path)\n");
  123                         xpt_free_ccb(ccb);
  124                         return;
  125                 }
  126                 xpt_rescan(ccb);
  127         }
  128 
  129         DBG_FUNC("OUT\n");
  130 }
  131 
  132 /*
  133  * Remove the device from CAM layer when deleted or hot removed
  134  */
  135 void
  136 os_remove_device(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
  137 {
  138         struct cam_path *tmppath;
  139 
  140         DBG_FUNC("IN\n");
  141         
  142         if(softs->os_specific.sim_registered) {
  143                 if (xpt_create_path(&tmppath, NULL, 
  144                         cam_sim_path(softs->os_specific.sim),
  145                         device->target, device->lun) != CAM_REQ_CMP) {
  146                         DBG_ERR("unable to create path for async event");
  147                         return;
  148                 }
  149                 xpt_async(AC_LOST_DEVICE, tmppath, NULL);
  150                 xpt_free_path(tmppath);
  151                 softs->device_list[device->target][device->lun] = NULL;
  152                 pqisrc_free_device(softs, device);
  153         }
  154 
  155         DBG_FUNC("OUT\n");
  156 
  157 }
  158 
  159 /*
  160  * Function to release the frozen simq
  161  */
  162 static void
  163 pqi_release_camq(rcb_t *rcb)
  164 {
  165         pqisrc_softstate_t *softs;
  166         struct ccb_scsiio *csio;
  167 
  168         csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
  169         softs = rcb->softs;
  170 
  171         DBG_FUNC("IN\n");
  172 
  173         if (softs->os_specific.pqi_flags & PQI_FLAG_BUSY) {
  174                 softs->os_specific.pqi_flags &= ~PQI_FLAG_BUSY;
  175                 if (csio->ccb_h.status & CAM_RELEASE_SIMQ)
  176                         xpt_release_simq(xpt_path_sim(csio->ccb_h.path), 0);
  177                 else
  178                         csio->ccb_h.status |= CAM_RELEASE_SIMQ;
  179         }
  180 
  181         DBG_FUNC("OUT\n");
  182 }
  183 
  184 static void
  185 pqi_synch_request(rcb_t *rcb)
  186 {
  187         pqisrc_softstate_t *softs = rcb->softs;
  188 
  189         DBG_IO("IN rcb = %p\n", rcb);
  190 
  191         if (!(rcb->cm_flags & PQI_CMD_MAPPED))
  192                 return;
  193 
  194         if (rcb->bcount != 0 ) {
  195                 if (rcb->data_dir == SOP_DATA_DIR_FROM_DEVICE)
  196                         bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
  197                                         rcb->cm_datamap,
  198                                         BUS_DMASYNC_POSTREAD);
  199                 if (rcb->data_dir == SOP_DATA_DIR_TO_DEVICE)
  200                         bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
  201                                         rcb->cm_datamap,
  202                                         BUS_DMASYNC_POSTWRITE);
  203                 bus_dmamap_unload(softs->os_specific.pqi_buffer_dmat,
  204                                         rcb->cm_datamap);
  205         }
  206         rcb->cm_flags &= ~PQI_CMD_MAPPED;
  207 
  208         if(rcb->sgt && rcb->nseg)
  209                 os_mem_free(rcb->softs, (void*)rcb->sgt,
  210                                 rcb->nseg*sizeof(sgt_t));
  211 
  212         DBG_IO("OUT\n");
  213 }
  214 
  215 /*
  216  * Function to dma-unmap the completed request
  217  */
  218 static inline void
  219 pqi_unmap_request(rcb_t *rcb)
  220 {
  221         DBG_IO("IN rcb = %p\n", rcb);
  222 
  223         pqi_synch_request(rcb);
  224         pqisrc_put_tag(&rcb->softs->taglist, rcb->tag);
  225 
  226         DBG_IO("OUT\n");
  227 }
  228 
  229 /*
  230  * Construct meaningful LD name for volume here.
  231  */
  232 static void
  233 smartpqi_fix_ld_inquiry(pqisrc_softstate_t *softs, struct ccb_scsiio *csio)
  234 {
  235         struct scsi_inquiry_data *inq = NULL;
  236         uint8_t *cdb = NULL;
  237         pqi_scsi_dev_t *device = NULL;
  238 
  239         DBG_FUNC("IN\n");
  240 
  241         if (pqisrc_ctrl_offline(softs))
  242                 return;
  243 
  244         cdb = (csio->ccb_h.flags & CAM_CDB_POINTER) ?
  245                 (uint8_t *)csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes;
  246         if(cdb[0] == INQUIRY &&
  247                 (cdb[1] & SI_EVPD) == 0 &&
  248                 (csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN &&
  249                 csio->dxfer_len >= SHORT_INQUIRY_LENGTH) {
  250 
  251                 inq = (struct scsi_inquiry_data *)csio->data_ptr;
  252 
  253                 device = softs->device_list[csio->ccb_h.target_id][csio->ccb_h.target_lun];
  254 
  255                 /* Let the disks be probed and dealt with via CAM. Only for LD
  256                   let it fall through and inquiry be tweaked */
  257                 if (!device || !pqisrc_is_logical_device(device) ||
  258                                 (device->devtype != DISK_DEVICE) ||
  259                                 pqisrc_is_external_raid_device(device)) {
  260                         return;
  261                 }
  262 
  263                 strncpy(inq->vendor, device->vendor,
  264                                 SID_VENDOR_SIZE);
  265                 strncpy(inq->product,
  266                                 pqisrc_raidlevel_to_string(device->raid_level),
  267                                 SID_PRODUCT_SIZE);
  268                 strncpy(inq->revision, device->volume_offline?"OFF":"OK",
  269                                 SID_REVISION_SIZE);
  270         }
  271 
  272         DBG_FUNC("OUT\n");
  273 }
  274 
  275 static void
  276 pqi_complete_scsi_io(struct ccb_scsiio *csio, rcb_t *rcb)
  277 {
  278         uint32_t release_tag;
  279         pqisrc_softstate_t *softs = rcb->softs;
  280 
  281         DBG_IO("IN scsi io = %p\n", csio);
  282 
  283         pqi_synch_request(rcb);
  284         smartpqi_fix_ld_inquiry(rcb->softs, csio);
  285         pqi_release_camq(rcb);
  286         release_tag = rcb->tag;
  287         os_reset_rcb(rcb);
  288         pqisrc_put_tag(&softs->taglist, release_tag);
  289         xpt_done((union ccb *)csio);
  290 
  291         DBG_FUNC("OUT\n");
  292 }
  293 
  294 /*
  295  * Handle completion of a command - pass results back through the CCB
  296  */
  297 void
  298 os_io_response_success(rcb_t *rcb)
  299 {
  300         struct ccb_scsiio *csio;
  301 
  302         DBG_IO("IN rcb = %p\n", rcb);
  303 
  304         if (rcb == NULL)
  305                 panic("rcb is null");
  306 
  307         csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
  308 
  309         if (csio == NULL)
  310                 panic("csio is null");
  311 
  312         rcb->status = REQUEST_SUCCESS;
  313         csio->ccb_h.status = CAM_REQ_CMP;
  314 
  315         pqi_complete_scsi_io(csio, rcb);
  316 
  317         DBG_IO("OUT\n");
  318 }
  319 
  320 static void
  321 copy_sense_data_to_csio(struct ccb_scsiio *csio,
  322                 uint8_t *sense_data, uint16_t sense_data_len)
  323 {
  324         DBG_IO("IN csio = %p\n", csio);
  325 
  326         memset(&csio->sense_data, 0, csio->sense_len);
  327 
  328         sense_data_len = (sense_data_len > csio->sense_len) ?
  329                 csio->sense_len : sense_data_len;
  330 
  331         if (sense_data)
  332                 memcpy(&csio->sense_data, sense_data, sense_data_len);
  333 
  334         if (csio->sense_len > sense_data_len)
  335                 csio->sense_resid = csio->sense_len - sense_data_len;
  336         else
  337                 csio->sense_resid = 0;
  338 
  339         DBG_IO("OUT\n");
  340 }
  341 
  342 /*
  343  * Error response handling for raid IO
  344  */
  345 void
  346 os_raid_response_error(rcb_t *rcb, raid_path_error_info_elem_t *err_info)
  347 {
  348         struct ccb_scsiio *csio;
  349         pqisrc_softstate_t *softs;
  350 
  351         DBG_IO("IN\n");
  352 
  353         csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
  354 
  355         if (csio == NULL)
  356                 panic("csio is null");
  357 
  358         softs = rcb->softs;
  359 
  360         csio->ccb_h.status = CAM_REQ_CMP_ERR;
  361 
  362         if (!err_info || !rcb->dvp) {
  363                 DBG_ERR("couldn't be accessed! error info = %p, rcb->dvp = %p\n",
  364                                 err_info, rcb->dvp);
  365                 goto error_out;
  366         }
  367 
  368         csio->scsi_status = err_info->status;
  369 
  370         if (csio->ccb_h.func_code == XPT_SCSI_IO) {
  371                 /*
  372                  * Handle specific SCSI status values.
  373                  */
  374                 switch(csio->scsi_status) {
  375                         case PQI_RAID_STATUS_QUEUE_FULL:
  376                                 csio->ccb_h.status = CAM_REQ_CMP;
  377                                 DBG_ERR("Queue Full error\n");
  378                                 break;
  379                                 /* check condition, sense data included */
  380                         case PQI_RAID_STATUS_CHECK_CONDITION:
  381                                 {
  382                                         uint16_t sense_data_len =
  383                                                 LE_16(err_info->sense_data_len);
  384                                         uint8_t *sense_data = NULL;
  385                                         if (sense_data_len)
  386                                                 sense_data = err_info->data;
  387                                         copy_sense_data_to_csio(csio, sense_data, sense_data_len);
  388                                         csio->ccb_h.status = CAM_SCSI_STATUS_ERROR
  389                                                         | CAM_AUTOSNS_VALID
  390                                                         | CAM_REQ_CMP_ERR;
  391 
  392                                 }
  393                                 break;
  394 
  395                         case PQI_RAID_DATA_IN_OUT_UNDERFLOW:
  396                                 {
  397                                         uint32_t resid = 0;
  398                                         resid = rcb->bcount-err_info->data_out_transferred;
  399                                         csio->resid  = resid;
  400                                         csio->ccb_h.status = CAM_REQ_CMP;
  401                                 }
  402                                 break;
  403                         default:
  404                                 csio->ccb_h.status = CAM_REQ_CMP;
  405                                 break;
  406                 }
  407         }
  408 
  409 error_out:
  410         pqi_complete_scsi_io(csio, rcb);
  411 
  412         DBG_IO("OUT\n");
  413 }
  414 
  415 /*
  416  * Error response handling for aio.
  417  */
  418 void
  419 os_aio_response_error(rcb_t *rcb, aio_path_error_info_elem_t *err_info)
  420 {
  421         struct ccb_scsiio *csio;
  422         pqisrc_softstate_t *softs;
  423 
  424         DBG_IO("IN\n");
  425 
  426         if (rcb == NULL)
  427                 panic("rcb is null");
  428 
  429         rcb->status = REQUEST_SUCCESS;
  430         csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio;
  431         if (csio == NULL)
  432                 panic("csio is null");
  433 
  434         softs = rcb->softs;
  435 
  436         if (!err_info || !rcb->dvp) {
  437                 csio->ccb_h.status = CAM_REQ_CMP_ERR;
  438                 DBG_ERR("couldn't be accessed! error info = %p, rcb->dvp = %p\n",
  439                                 err_info, rcb->dvp);
  440                 goto error_out;
  441         }
  442 
  443         switch (err_info->service_resp) {
  444                 case PQI_AIO_SERV_RESPONSE_COMPLETE:
  445                         csio->ccb_h.status = err_info->status;
  446                         break;
  447                 case PQI_AIO_SERV_RESPONSE_FAILURE:
  448                         switch(err_info->status) {
  449                                 case PQI_AIO_STATUS_IO_ABORTED:
  450                                         csio->ccb_h.status = CAM_REQ_ABORTED;
  451                                         DBG_WARN_BTL(rcb->dvp, "IO aborted\n");
  452                                         break;
  453                                 case PQI_AIO_STATUS_UNDERRUN:
  454                                         csio->ccb_h.status = CAM_REQ_CMP;
  455                                         csio->resid =
  456                                                 LE_32(err_info->resd_count);
  457                                         break;
  458                                 case PQI_AIO_STATUS_OVERRUN:
  459                                         csio->ccb_h.status = CAM_REQ_CMP;
  460                                         break;
  461                                 case PQI_AIO_STATUS_AIO_PATH_DISABLED:
  462                                         DBG_WARN_BTL(rcb->dvp,"AIO Path Disabled\n");
  463                                         /* Timed out TMF response comes here */
  464                                         if (rcb->tm_req) {
  465                                                 rcb->req_pending = false;
  466                                                 rcb->status = REQUEST_SUCCESS;
  467                                                 DBG_ERR("AIO Disabled for TMF\n");
  468                                                 return;
  469                                         }
  470                                         rcb->dvp->aio_enabled = false;
  471                                         rcb->dvp->offload_enabled = false;
  472                                         csio->ccb_h.status |= CAM_REQUEUE_REQ;
  473                                         break;
  474                                 case PQI_AIO_STATUS_IO_ERROR:
  475                                 case PQI_AIO_STATUS_IO_NO_DEVICE:
  476                                 case PQI_AIO_STATUS_INVALID_DEVICE:
  477                                 default:
  478                                         DBG_WARN_BTL(rcb->dvp,"IO Error/Invalid/No device\n");
  479                                         csio->ccb_h.status |=
  480                                                 CAM_SCSI_STATUS_ERROR;
  481                                         break;
  482                         }
  483                         break;
  484                 case PQI_AIO_SERV_RESPONSE_TMF_COMPLETE:
  485                 case PQI_AIO_SERV_RESPONSE_TMF_SUCCEEDED:
  486                         DBG_ERR("PQI_AIO_SERV_RESPONSE_TMF %s\n",
  487                                 (err_info->service_resp == PQI_AIO_SERV_RESPONSE_TMF_COMPLETE) ? "COMPLETE" : "SUCCEEDED");
  488                         rcb->status = REQUEST_SUCCESS;
  489                         rcb->req_pending = false;
  490                         return;
  491                 case PQI_AIO_SERV_RESPONSE_TMF_REJECTED:
  492                 case PQI_AIO_SERV_RESPONSE_TMF_INCORRECT_LUN:
  493                         DBG_ERR("PQI_AIO_SERV_RESPONSE_TMF %s\n",
  494                                 (err_info->service_resp == PQI_AIO_SERV_RESPONSE_TMF_REJECTED) ? "REJECTED" : "INCORRECT LUN");
  495                         rcb->status = REQUEST_FAILED;
  496                         rcb->req_pending = false;
  497                         return;
  498                 default:
  499                         DBG_WARN_BTL(rcb->dvp,"Scsi Status Error\n");
  500                         csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR;
  501                         break;
  502         }
  503 
  504         if(err_info->data_pres == DATA_PRESENT_SENSE_DATA ) {
  505                 csio->scsi_status = PQI_AIO_STATUS_CHECK_CONDITION;
  506                 uint8_t *sense_data = NULL;
  507                 unsigned sense_data_len = LE_16(err_info->data_len);
  508                 if (sense_data_len)
  509                         sense_data = err_info->data;
  510                 DBG_INFO("SCSI_STATUS_CHECK_COND  sense size %u\n",
  511                         sense_data_len);
  512                 copy_sense_data_to_csio(csio, sense_data, sense_data_len);
  513                 csio->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID;
  514         }
  515 
  516 error_out:
  517         pqi_complete_scsi_io(csio, rcb);
  518         DBG_IO("OUT\n");
  519 }
  520 
  521 static void
  522 pqi_freeze_ccb(union ccb *ccb)
  523 {
  524         if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
  525                 ccb->ccb_h.status |= CAM_DEV_QFRZN;
  526                 xpt_freeze_devq(ccb->ccb_h.path, 1);
  527         }
  528 }
  529 
  530 /*
  531  * Command-mapping helper function - populate this command's s/g table.
  532  */
  533 static void
  534 pqi_request_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
  535 {
  536         rcb_t *rcb = (rcb_t *)arg;
  537         pqisrc_softstate_t *softs = rcb->softs;
  538         union ccb *ccb;
  539 
  540         if (error || nseg > softs->pqi_cap.max_sg_elem) {
  541                 DBG_ERR_BTL(rcb->dvp, "map failed err = %d or nseg(%d) > sgelem(%d)\n",
  542                         error, nseg, softs->pqi_cap.max_sg_elem);
  543                 goto error_io;
  544         }
  545 
  546         rcb->sgt = os_mem_alloc(softs, nseg * sizeof(sgt_t));
  547 
  548         if (!rcb->sgt) {
  549                 DBG_ERR_BTL(rcb->dvp, "os_mem_alloc() failed; nseg = %d\n", nseg);
  550                 goto error_io;
  551         }
  552 
  553         rcb->nseg = nseg;
  554         for (int i = 0; i < nseg; i++) {
  555                 rcb->sgt[i].addr = segs[i].ds_addr;
  556                 rcb->sgt[i].len = segs[i].ds_len;
  557                 rcb->sgt[i].flags = 0;
  558         }
  559 
  560         if (rcb->data_dir == SOP_DATA_DIR_FROM_DEVICE)
  561                 bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
  562                         rcb->cm_datamap, BUS_DMASYNC_PREREAD);
  563         if (rcb->data_dir == SOP_DATA_DIR_TO_DEVICE)
  564                 bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat,
  565                         rcb->cm_datamap, BUS_DMASYNC_PREWRITE);
  566 
  567         /* Call IO functions depending on pd or ld */
  568         rcb->status = REQUEST_PENDING;
  569 
  570         error = pqisrc_build_send_io(softs, rcb);
  571 
  572         if (error) {
  573                 rcb->req_pending = false;
  574                 DBG_ERR_BTL(rcb->dvp, "Build IO failed, error = %d\n", error);
  575         } else {
  576                 /* Successfully IO was submitted to the device. */
  577                 return;
  578         }
  579 
  580 error_io:
  581         ccb = rcb->cm_ccb;
  582         ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
  583         pqi_freeze_ccb(ccb);
  584         pqi_unmap_request(rcb);
  585         xpt_done(ccb);
  586         return;
  587 }
  588 
  589 /*
  590  * Function to dma-map the request buffer
  591  */
  592 static int
  593 pqi_map_request(rcb_t *rcb)
  594 {
  595         pqisrc_softstate_t *softs = rcb->softs;
  596         int bsd_status = BSD_SUCCESS;
  597         union ccb *ccb = rcb->cm_ccb;
  598 
  599         DBG_FUNC("IN\n");
  600 
  601         /* check that mapping is necessary */
  602         if (rcb->cm_flags & PQI_CMD_MAPPED)
  603                 return BSD_SUCCESS;
  604 
  605         rcb->cm_flags |= PQI_CMD_MAPPED;
  606 
  607         if (rcb->bcount) {
  608                 bsd_status = bus_dmamap_load_ccb(softs->os_specific.pqi_buffer_dmat,
  609                         rcb->cm_datamap, ccb, pqi_request_map_helper, rcb, 0);
  610                 if (bsd_status != BSD_SUCCESS && bsd_status != EINPROGRESS) {
  611                         DBG_ERR_BTL(rcb->dvp, "bus_dmamap_load_ccb failed, return status = %d transfer length = %d\n",
  612                                         bsd_status, rcb->bcount);
  613                         return bsd_status;
  614                 }
  615         } else {
  616                 /*
  617                  * Set up the command to go to the controller.  If there are no
  618                  * data buffers associated with the command then it can bypass
  619                  * busdma.
  620                  */
  621                 /* Call IO functions depending on pd or ld */
  622                 rcb->status = REQUEST_PENDING;
  623 
  624                 if (pqisrc_build_send_io(softs, rcb) != PQI_STATUS_SUCCESS) {
  625                         bsd_status = EIO;
  626                 }
  627         }
  628 
  629         DBG_FUNC("OUT error = %d\n", bsd_status);
  630 
  631         return bsd_status;
  632 }
  633 
  634 /*
  635  * Function to clear the request control block
  636  */
  637 void
  638 os_reset_rcb(rcb_t *rcb)
  639 {
  640         rcb->error_info = NULL;
  641         rcb->req = NULL;
  642         rcb->status = -1;
  643         rcb->tag = INVALID_ELEM;
  644         rcb->dvp = NULL;
  645         rcb->cdbp = NULL;
  646         rcb->softs = NULL;
  647         rcb->cm_flags = 0;
  648         rcb->cm_data = NULL;
  649         rcb->bcount = 0;
  650         rcb->nseg = 0;
  651         rcb->sgt = NULL;
  652         rcb->cm_ccb = NULL;
  653         rcb->encrypt_enable = false;
  654         rcb->ioaccel_handle = 0;
  655         rcb->resp_qid = 0;
  656         rcb->req_pending = false;
  657         rcb->tm_req = false;
  658 }
  659 
  660 /*
  661  * Callback function for the lun rescan
  662  */
  663 static void
  664 smartpqi_lunrescan_cb(struct cam_periph *periph, union ccb *ccb)
  665 {
  666         xpt_free_path(ccb->ccb_h.path);
  667         xpt_free_ccb(ccb);
  668 }
  669 
  670 
  671 /*
  672  * Function to rescan the lun
  673  */
  674 static void
  675 smartpqi_lun_rescan(struct pqisrc_softstate *softs, int target,
  676                         int lun)
  677 {
  678         union ccb *ccb = NULL;
  679         cam_status status = 0;
  680         struct cam_path *path = NULL;
  681 
  682         DBG_FUNC("IN\n");
  683 
  684         ccb = xpt_alloc_ccb_nowait();
  685         if (ccb == NULL) {
  686                 DBG_ERR("Unable to alloc ccb for lun rescan\n");
  687                 return;
  688         }
  689 
  690         status = xpt_create_path(&path, NULL,
  691                                 cam_sim_path(softs->os_specific.sim), target, lun);
  692         if (status != CAM_REQ_CMP) {
  693                 DBG_ERR("xpt_create_path status(%d) != CAM_REQ_CMP \n",
  694                                  status);
  695                 xpt_free_ccb(ccb);
  696                 return;
  697         }
  698 
  699         bzero(ccb, sizeof(union ccb));
  700         xpt_setup_ccb(&ccb->ccb_h, path, 5);
  701         ccb->ccb_h.func_code = XPT_SCAN_LUN;
  702         ccb->ccb_h.cbfcnp = smartpqi_lunrescan_cb;
  703         ccb->crcn.flags = CAM_FLAG_NONE;
  704 
  705         xpt_action(ccb);
  706 
  707         DBG_FUNC("OUT\n");
  708 }
  709 
  710 /*
  711  * Function to rescan the lun under each target
  712  */
  713 void
  714 smartpqi_target_rescan(struct pqisrc_softstate *softs)
  715 {
  716         int target = 0, lun = 0;
  717 
  718         DBG_FUNC("IN\n");
  719 
  720         for(target = 0; target < PQI_MAX_DEVICES; target++){
  721                 for(lun = 0; lun < PQI_MAX_MULTILUN; lun++){
  722                         if(softs->device_list[target][lun]){
  723                                 smartpqi_lun_rescan(softs, target, lun);
  724                         }
  725                 }
  726         }
  727 
  728         DBG_FUNC("OUT\n");
  729 }
  730 
  731 /*
  732  * Set the mode of tagged command queueing for the current task.
  733  */
  734 uint8_t
  735 os_get_task_attr(rcb_t *rcb)
  736 {
  737         union ccb *ccb = rcb->cm_ccb;
  738         uint8_t tag_action = SOP_TASK_ATTRIBUTE_SIMPLE;
  739 
  740         switch(ccb->csio.tag_action) {
  741         case MSG_HEAD_OF_Q_TAG:
  742                 tag_action = SOP_TASK_ATTRIBUTE_HEAD_OF_QUEUE;
  743                 break;
  744         case MSG_ORDERED_Q_TAG:
  745                 tag_action = SOP_TASK_ATTRIBUTE_ORDERED;
  746                 break;
  747         case MSG_SIMPLE_Q_TAG:
  748         default:
  749                 tag_action = SOP_TASK_ATTRIBUTE_SIMPLE;
  750                 break;
  751         }
  752         return tag_action;
  753 }
  754 
  755 /*
  756  * Complete all outstanding commands
  757  */
  758 void
  759 os_complete_outstanding_cmds_nodevice(pqisrc_softstate_t *softs)
  760 {
  761         int tag = 0;
  762         pqi_scsi_dev_t  *dvp = NULL;
  763 
  764         DBG_FUNC("IN\n");
  765 
  766         for (tag = 1; tag <= softs->max_outstanding_io; tag++) {
  767                 rcb_t *prcb = &softs->rcb[tag];
  768                 dvp = prcb->dvp;
  769                 if(prcb->req_pending && prcb->cm_ccb ) {
  770                         prcb->req_pending = false;
  771                         prcb->cm_ccb->ccb_h.status = CAM_REQ_ABORTED | CAM_REQ_CMP;
  772                         pqi_complete_scsi_io(&prcb->cm_ccb->csio, prcb);
  773                         if (dvp)
  774                                 pqisrc_decrement_device_active_io(softs, dvp);
  775 
  776                 }
  777         }
  778 
  779         DBG_FUNC("OUT\n");
  780 }
  781 
  782 /*
  783  * IO handling functionality entry point
  784  */
  785 static int
  786 pqisrc_io_start(struct cam_sim *sim, union ccb *ccb)
  787 {
  788         rcb_t *rcb;
  789         uint32_t tag, no_transfer = 0;
  790         pqisrc_softstate_t *softs = (struct pqisrc_softstate *)
  791                                         cam_sim_softc(sim);
  792         int32_t error;
  793         pqi_scsi_dev_t *dvp;
  794 
  795         DBG_FUNC("IN\n");
  796 
  797         if (softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun] == NULL) {
  798                 ccb->ccb_h.status = CAM_DEV_NOT_THERE;
  799                 DBG_INFO("Device  = %d not there\n", ccb->ccb_h.target_id);
  800                 return ENXIO;
  801         }
  802 
  803         dvp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun];
  804         /* Check  controller state */
  805         if (IN_PQI_RESET(softs)) {
  806                 ccb->ccb_h.status = CAM_SCSI_BUS_RESET
  807                                         | CAM_BUSY | CAM_REQ_INPROG;
  808                 DBG_WARN("Device  = %d BUSY/IN_RESET\n", ccb->ccb_h.target_id);
  809                 return ENXIO;
  810         }
  811         /* Check device state */
  812         if (pqisrc_ctrl_offline(softs) || DEV_GONE(dvp)) {
  813                 ccb->ccb_h.status = CAM_DEV_NOT_THERE | CAM_REQ_CMP;
  814                 DBG_WARN("Device  = %d GONE/OFFLINE\n", ccb->ccb_h.target_id);
  815                 return ENXIO;
  816         }
  817         /* Check device reset */
  818         if (DEVICE_RESET(dvp)) {
  819                 ccb->ccb_h.status = CAM_SCSI_BUSY | CAM_REQ_INPROG | CAM_BUSY;
  820                 DBG_WARN("Device %d reset returned busy\n", ccb->ccb_h.target_id);
  821                 return EBUSY;
  822         }
  823 
  824         if (dvp->expose_device == false) {
  825                 ccb->ccb_h.status = CAM_DEV_NOT_THERE;
  826                 DBG_INFO("Device  = %d not exposed\n", ccb->ccb_h.target_id);
  827                 return ENXIO;
  828         }
  829 
  830         tag = pqisrc_get_tag(&softs->taglist);
  831         if (tag == INVALID_ELEM) {
  832                 DBG_ERR("Get Tag failed\n");
  833                 xpt_freeze_simq(softs->os_specific.sim, 1);
  834                 softs->os_specific.pqi_flags |= PQI_FLAG_BUSY;
  835                 ccb->ccb_h.status |= (CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ);
  836                 return EIO;
  837         }
  838 
  839         DBG_IO("tag = %d &softs->taglist : %p\n", tag, &softs->taglist);
  840 
  841         rcb = &softs->rcb[tag];
  842         os_reset_rcb(rcb);
  843         rcb->tag = tag;
  844         rcb->softs = softs;
  845         rcb->cmdlen = ccb->csio.cdb_len;
  846         ccb->ccb_h.sim_priv.entries[0].ptr = rcb;
  847 
  848         switch (ccb->ccb_h.flags & CAM_DIR_MASK) {
  849                 case CAM_DIR_IN:
  850                         rcb->data_dir = SOP_DATA_DIR_FROM_DEVICE;
  851                         break;
  852                 case CAM_DIR_OUT:
  853                         rcb->data_dir = SOP_DATA_DIR_TO_DEVICE;
  854                         break;
  855                 case CAM_DIR_NONE:
  856                         no_transfer = 1;
  857                         break;
  858                 default:
  859                         DBG_ERR("Unknown Dir\n");
  860                         break;
  861         }
  862         rcb->cm_ccb = ccb;
  863         rcb->dvp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun];
  864 
  865         if (!no_transfer) {
  866                 rcb->cm_data = (void *)ccb->csio.data_ptr;
  867                 rcb->bcount = ccb->csio.dxfer_len;
  868         } else {
  869                 rcb->cm_data = NULL;
  870                 rcb->bcount = 0;
  871         }
  872         /*
  873          * Submit the request to the adapter.
  874          *
  875          * Note that this may fail if we're unable to map the request (and
  876          * if we ever learn a transport layer other than simple, may fail
  877          * if the adapter rejects the command).
  878          */
  879         if ((error = pqi_map_request(rcb)) != BSD_SUCCESS) {
  880                 xpt_freeze_simq(softs->os_specific.sim, 1);
  881                 if (error == EINPROGRESS) {
  882                         /* Release simq in the completion */
  883                         softs->os_specific.pqi_flags |= PQI_FLAG_BUSY;
  884                         error = BSD_SUCCESS;
  885                 } else {
  886                         rcb->req_pending = false;
  887                         ccb->ccb_h.status |= CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ;
  888                         DBG_WARN("Requeue req error = %d target = %d\n", error,
  889                                 ccb->ccb_h.target_id);
  890                         pqi_unmap_request(rcb);
  891                         error = EIO;
  892                 }
  893         }
  894 
  895         DBG_FUNC("OUT error = %d\n", error);
  896 
  897         return error;
  898 }
  899 
  900 static inline int
  901 pqi_tmf_status_to_bsd_tmf_status(int pqi_status, rcb_t *rcb)
  902 {
  903         if (PQI_STATUS_SUCCESS == pqi_status &&
  904                         REQUEST_SUCCESS == rcb->status)
  905                 return BSD_SUCCESS;
  906         else
  907                 return EIO;
  908 }
  909 
  910 /*
  911  * Abort a task, task management functionality
  912  */
  913 static int
  914 pqisrc_scsi_abort_task(pqisrc_softstate_t *softs,  union ccb *ccb)
  915 {
  916         struct ccb_hdr *ccb_h = &ccb->ccb_h;
  917         rcb_t *rcb = NULL;
  918         rcb_t *prcb = ccb->ccb_h.sim_priv.entries[0].ptr;
  919         uint32_t tag;
  920         int rval;
  921 
  922         DBG_FUNC("IN\n");
  923 
  924         tag = pqisrc_get_tag(&softs->taglist);
  925         rcb = &softs->rcb[tag];
  926         rcb->tag = tag;
  927 
  928         if (!rcb->dvp) {
  929                 DBG_ERR("dvp is null, tmf type : 0x%x\n", ccb_h->func_code);
  930                 rval = ENXIO;
  931                 goto error_tmf;
  932         }
  933 
  934         rcb->tm_req = true;
  935 
  936         rval = pqisrc_send_tmf(softs, rcb->dvp, rcb, prcb,
  937                 SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK);
  938 
  939         if ((rval = pqi_tmf_status_to_bsd_tmf_status(rval, rcb)) == BSD_SUCCESS)
  940                 ccb->ccb_h.status = CAM_REQ_ABORTED;
  941 
  942 error_tmf:
  943         os_reset_rcb(rcb);
  944         pqisrc_put_tag(&softs->taglist, tag);
  945 
  946         DBG_FUNC("OUT rval = %d\n", rval);
  947 
  948         return rval;
  949 }
  950 
  951 /*
  952  * Abort a taskset, task management functionality
  953  */
  954 static int
  955 pqisrc_scsi_abort_task_set(pqisrc_softstate_t *softs, union ccb *ccb)
  956 {
  957         struct ccb_hdr *ccb_h = &ccb->ccb_h;
  958         rcb_t *rcb = NULL;
  959         uint32_t tag;
  960         int rval;
  961 
  962         DBG_FUNC("IN\n");
  963 
  964         tag = pqisrc_get_tag(&softs->taglist);
  965         rcb = &softs->rcb[tag];
  966         rcb->tag = tag;
  967 
  968         if (!rcb->dvp) {
  969                 DBG_ERR("dvp is null, tmf type : 0x%x\n", ccb_h->func_code);
  970                 rval = ENXIO;
  971                 goto error_tmf;
  972         }
  973 
  974         rcb->tm_req = true;
  975 
  976         rval = pqisrc_send_tmf(softs, rcb->dvp, rcb, NULL,
  977                         SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK_SET);
  978 
  979         rval = pqi_tmf_status_to_bsd_tmf_status(rval, rcb);
  980 
  981 error_tmf:
  982         os_reset_rcb(rcb);
  983         pqisrc_put_tag(&softs->taglist, tag);
  984 
  985         DBG_FUNC("OUT rval = %d\n", rval);
  986 
  987         return rval;
  988 }
  989 
  990 /*
  991  * Target reset task management functionality
  992  */
  993 static int
  994 pqisrc_target_reset( pqisrc_softstate_t *softs,  union ccb *ccb)
  995 {
  996         struct ccb_hdr  *ccb_h = &ccb->ccb_h;
  997         pqi_scsi_dev_t *devp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun];
  998         rcb_t *rcb = NULL;
  999         uint32_t tag;
 1000         int rval;
 1001 
 1002         DBG_FUNC("IN\n");
 1003 
 1004         if (devp == NULL) {
 1005                 DBG_ERR("bad target %d, tmf type : 0x%x\n", ccb_h->target_id, ccb_h->func_code);
 1006                 return ENXIO;
 1007         }
 1008 
 1009         tag = pqisrc_get_tag(&softs->taglist);
 1010         rcb = &softs->rcb[tag];
 1011         rcb->tag = tag;
 1012 
 1013         devp->reset_in_progress = true;
 1014 
 1015         rcb->tm_req = true;
 1016 
 1017         rval = pqisrc_send_tmf(softs, devp, rcb, NULL,
 1018                 SOP_TASK_MANAGEMENT_LUN_RESET);
 1019 
 1020         rval = pqi_tmf_status_to_bsd_tmf_status(rval, rcb);
 1021         devp->reset_in_progress = false;
 1022 
 1023         os_reset_rcb(rcb);
 1024         pqisrc_put_tag(&softs->taglist, tag);
 1025 
 1026         DBG_FUNC("OUT rval = %d\n", rval);
 1027 
 1028         return rval;
 1029 
 1030 }
 1031 
 1032 /*
 1033  * cam entry point of the smartpqi module.
 1034  */
 1035 static void
 1036 smartpqi_cam_action(struct cam_sim *sim, union ccb *ccb)
 1037 {
 1038         struct pqisrc_softstate *softs = cam_sim_softc(sim);
 1039         struct ccb_hdr  *ccb_h = &ccb->ccb_h;
 1040 
 1041         DBG_FUNC("IN\n");
 1042 
 1043         switch (ccb_h->func_code) {
 1044                 case XPT_SCSI_IO:
 1045                 {
 1046                         if(!pqisrc_io_start(sim, ccb)) {
 1047                                 return;
 1048                         }
 1049                         break;
 1050                 }
 1051                 case XPT_CALC_GEOMETRY:
 1052                 {
 1053                         struct ccb_calc_geometry *ccg;
 1054                         ccg = &ccb->ccg;
 1055                         if (ccg->block_size == 0) {
 1056                                 ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
 1057                                 ccb->ccb_h.status |= CAM_REQ_INVALID;
 1058                                 break;
 1059                         }
 1060                         cam_calc_geometry(ccg, /* extended */ 1);
 1061                         ccb->ccb_h.status = CAM_REQ_CMP;
 1062                         break;
 1063                 }
 1064                 case XPT_PATH_INQ:
 1065                 {
 1066                         update_sim_properties(sim, &ccb->cpi);
 1067                         ccb->ccb_h.status = CAM_REQ_CMP;
 1068                         break;
 1069                 }
 1070                 case XPT_GET_TRAN_SETTINGS:
 1071                         get_transport_settings(softs, &ccb->cts);
 1072                         ccb->ccb_h.status = CAM_REQ_CMP;
 1073                         break;
 1074                 case XPT_ABORT:
 1075                         if(pqisrc_scsi_abort_task(softs,  ccb)) {
 1076                                 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
 1077                                 xpt_done(ccb);
 1078                                 DBG_ERR("Abort task failed on %d\n",
 1079                                         ccb->ccb_h.target_id);
 1080                                 return;
 1081                         }
 1082                         break;
 1083                 case XPT_TERM_IO:
 1084                         if (pqisrc_scsi_abort_task_set(softs,  ccb)) {
 1085                                 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
 1086                                 DBG_ERR("Abort task set failed on %d\n",
 1087                                         ccb->ccb_h.target_id);
 1088                                 xpt_done(ccb);
 1089                                 return;
 1090                         }
 1091                         break;
 1092                 case XPT_RESET_DEV:
 1093                         if(pqisrc_target_reset(softs,  ccb)) {
 1094                                 ccb->ccb_h.status = CAM_REQ_CMP_ERR;
 1095                                 DBG_ERR("Target reset failed on %d\n",
 1096                                         ccb->ccb_h.target_id);
 1097                                 xpt_done(ccb);
 1098                                 return;
 1099                         } else {
 1100                                 ccb->ccb_h.status = CAM_REQ_CMP;
 1101                         }
 1102                         break;
 1103                 case XPT_RESET_BUS:
 1104                         ccb->ccb_h.status = CAM_REQ_CMP;
 1105                         break;
 1106                 case XPT_SET_TRAN_SETTINGS:
 1107                         ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
 1108                         return;
 1109                 default:
 1110                         DBG_WARN("UNSUPPORTED FUNC CODE\n");
 1111                         ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
 1112                         break;
 1113         }
 1114         xpt_done(ccb);
 1115 
 1116         DBG_FUNC("OUT\n");
 1117 }
 1118 
 1119 /*
 1120  * Function to poll the response, when interrupts are unavailable
 1121  * This also serves supporting crash dump.
 1122  */
 1123 static void
 1124 smartpqi_poll(struct cam_sim *sim)
 1125 {
 1126         struct pqisrc_softstate *softs = cam_sim_softc(sim);
 1127         int i;
 1128 
 1129         for (i = 1; i < softs->intr_count; i++ )
 1130                 pqisrc_process_response_queue(softs, i);
 1131 }
 1132 
 1133 /*
 1134  * Function to adjust the queue depth of a device
 1135  */
 1136 void
 1137 smartpqi_adjust_queue_depth(struct cam_path *path, uint32_t queue_depth)
 1138 {
 1139         struct ccb_relsim crs;
 1140 
 1141         DBG_INFO("IN\n");
 1142 
 1143         memset(&crs, 0, sizeof(crs));
 1144         xpt_setup_ccb(&crs.ccb_h, path, 5);
 1145         crs.ccb_h.func_code = XPT_REL_SIMQ;
 1146         crs.ccb_h.flags = CAM_DEV_QFREEZE;
 1147         crs.release_flags = RELSIM_ADJUST_OPENINGS;
 1148         crs.openings = queue_depth;
 1149         xpt_action((union ccb *)&crs);
 1150         if(crs.ccb_h.status != CAM_REQ_CMP) {
 1151                 printf("XPT_REL_SIMQ failed stat=%d\n", crs.ccb_h.status);
 1152         }
 1153 
 1154         DBG_INFO("OUT\n");
 1155 }
 1156 
 1157 /*
 1158  * Function to register async callback for setting queue depth
 1159  */
 1160 static void
 1161 smartpqi_async(void *callback_arg, u_int32_t code,
 1162                 struct cam_path *path, void *arg)
 1163 {
 1164         struct pqisrc_softstate *softs;
 1165         softs = (struct pqisrc_softstate*)callback_arg;
 1166 
 1167         DBG_FUNC("IN\n");
 1168 
 1169         switch (code) {
 1170                 case AC_FOUND_DEVICE:
 1171                 {
 1172                         struct ccb_getdev *cgd;
 1173                         cgd = (struct ccb_getdev *)arg;
 1174                         if (cgd == NULL) {
 1175                                 break;
 1176                         }
 1177                         uint32_t t_id = cgd->ccb_h.target_id;
 1178 
 1179                         if (t_id <= (PQI_CTLR_INDEX - 1)) {
 1180                                 if (softs != NULL) {
 1181                                         pqi_scsi_dev_t *dvp = softs->device_list[t_id][cgd->ccb_h.target_lun];
 1182                                         if (dvp == NULL) {
 1183                                                 DBG_ERR("Target is null, target id=%d\n", t_id);
 1184                                                 break;
 1185                                         }
 1186                                         smartpqi_adjust_queue_depth(path,
 1187                                                         dvp->queue_depth);
 1188                                 }
 1189                         }
 1190                         break;
 1191                 }
 1192                 default:
 1193                         break;
 1194         }
 1195 
 1196         DBG_FUNC("OUT\n");
 1197 }
 1198 
 1199 /*
 1200  * Function to register sim with CAM layer for smartpqi driver
 1201  */
 1202 int
 1203 register_sim(struct pqisrc_softstate *softs, int card_index)
 1204 {
 1205         int max_transactions;
 1206         union ccb   *ccb = NULL;
 1207         int error;
 1208         struct ccb_setasync csa;
 1209         struct cam_sim *sim;
 1210 
 1211         DBG_FUNC("IN\n");
 1212 
 1213         max_transactions = softs->max_io_for_scsi_ml;
 1214         softs->os_specific.devq = cam_simq_alloc(max_transactions);
 1215         if (softs->os_specific.devq == NULL) {
 1216                 DBG_ERR("cam_simq_alloc failed txns = %d\n",
 1217                         max_transactions);
 1218                 return ENOMEM;
 1219         }
 1220 
 1221         sim = cam_sim_alloc(smartpqi_cam_action, \
 1222                                 smartpqi_poll, "smartpqi", softs, \
 1223                                 card_index, &softs->os_specific.cam_lock, \
 1224                                 1, max_transactions, softs->os_specific.devq);
 1225         if (sim == NULL) {
 1226                 DBG_ERR("cam_sim_alloc failed txns = %d\n",
 1227                         max_transactions);
 1228                 cam_simq_free(softs->os_specific.devq);
 1229                 return ENOMEM;
 1230         }
 1231 
 1232         softs->os_specific.sim = sim;
 1233         mtx_lock(&softs->os_specific.cam_lock);
 1234         error = xpt_bus_register(sim, softs->os_specific.pqi_dev, 0);
 1235         if (error != CAM_SUCCESS) {
 1236                 DBG_ERR("xpt_bus_register failed errno %d\n", error);
 1237                 cam_sim_free(softs->os_specific.sim, FALSE);
 1238                 cam_simq_free(softs->os_specific.devq);
 1239                 mtx_unlock(&softs->os_specific.cam_lock);
 1240                 return ENXIO;
 1241         }
 1242 
 1243         softs->os_specific.sim_registered = TRUE;
 1244         ccb = xpt_alloc_ccb_nowait();
 1245         if (ccb == NULL) {
 1246                 DBG_ERR("xpt_create_path failed\n");
 1247                 return ENXIO;
 1248         }
 1249 
 1250         if (xpt_create_path(&ccb->ccb_h.path, NULL,
 1251                         cam_sim_path(softs->os_specific.sim),
 1252                         CAM_TARGET_WILDCARD,
 1253                         CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
 1254                 DBG_ERR("xpt_create_path failed\n");
 1255                 xpt_free_ccb(ccb);
 1256                 xpt_bus_deregister(cam_sim_path(softs->os_specific.sim));
 1257                 cam_sim_free(softs->os_specific.sim, TRUE);
 1258                 mtx_unlock(&softs->os_specific.cam_lock);
 1259                 return ENXIO;
 1260         }
 1261         /*
 1262          * Callback to set the queue depth per target which is 
 1263          * derived from the FW.
 1264          */
 1265         softs->os_specific.path = ccb->ccb_h.path;
 1266         memset(&csa, 0, sizeof(csa));
 1267         xpt_setup_ccb(&csa.ccb_h, softs->os_specific.path, 5);
 1268         csa.ccb_h.func_code = XPT_SASYNC_CB;
 1269         csa.event_enable = AC_FOUND_DEVICE;
 1270         csa.callback = smartpqi_async;
 1271         csa.callback_arg = softs;
 1272         xpt_action((union ccb *)&csa);
 1273         if (csa.ccb_h.status != CAM_REQ_CMP) {
 1274                 DBG_ERR("Unable to register smartpqi_aysnc handler: %d!\n", 
 1275                         csa.ccb_h.status);
 1276         }
 1277 
 1278         mtx_unlock(&softs->os_specific.cam_lock);
 1279         DBG_INFO("OUT\n");
 1280 
 1281         return BSD_SUCCESS;
 1282 }
 1283 
 1284 /*
 1285  * Function to deregister smartpqi sim from cam layer
 1286  */
 1287 void
 1288 deregister_sim(struct pqisrc_softstate *softs)
 1289 {
 1290         struct ccb_setasync csa;
 1291         
 1292         DBG_FUNC("IN\n");
 1293 
 1294         if (softs->os_specific.mtx_init) {
 1295                 mtx_lock(&softs->os_specific.cam_lock);
 1296         }
 1297 
 1298 
 1299         memset(&csa, 0, sizeof(csa));
 1300         xpt_setup_ccb(&csa.ccb_h, softs->os_specific.path, 5);
 1301         csa.ccb_h.func_code = XPT_SASYNC_CB;
 1302         csa.event_enable = 0;
 1303         csa.callback = smartpqi_async;
 1304         csa.callback_arg = softs;
 1305         xpt_action((union ccb *)&csa);
 1306         xpt_free_path(softs->os_specific.path);
 1307 
 1308         if (softs->os_specific.sim) {
 1309                 xpt_release_simq(softs->os_specific.sim, 0);
 1310                 xpt_bus_deregister(cam_sim_path(softs->os_specific.sim));
 1311                 softs->os_specific.sim_registered = FALSE;
 1312                 cam_sim_free(softs->os_specific.sim, FALSE);
 1313                 softs->os_specific.sim = NULL;
 1314         }
 1315 
 1316         if (softs->os_specific.mtx_init) {
 1317                 mtx_unlock(&softs->os_specific.cam_lock);
 1318         }
 1319         if (softs->os_specific.devq != NULL) {
 1320                 cam_simq_free(softs->os_specific.devq);
 1321         }
 1322         if (softs->os_specific.mtx_init) {
 1323                 mtx_destroy(&softs->os_specific.cam_lock);
 1324                 softs->os_specific.mtx_init = FALSE;
 1325         }
 1326 
 1327         mtx_destroy(&softs->os_specific.map_lock);
 1328 
 1329         DBG_FUNC("OUT\n");
 1330 }
 1331 
 1332 void
 1333 os_rescan_target(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device)
 1334 {
 1335        struct cam_path *tmppath;
 1336 
 1337        DBG_FUNC("IN\n");
 1338 
 1339        if(softs->os_specific.sim_registered) {
 1340                if (xpt_create_path(&tmppath, NULL,
 1341                        cam_sim_path(softs->os_specific.sim),
 1342                        device->target, device->lun) != CAM_REQ_CMP) {
 1343                        DBG_ERR("unable to create path for async event!!! Bus: %d Target: %d Lun: %d\n",
 1344                                device->bus, device->target, device->lun);
 1345                        return;
 1346                }
 1347                xpt_async(AC_INQ_CHANGED, tmppath, NULL);
 1348                xpt_free_path(tmppath);
 1349        }
 1350 
 1351        device->scsi_rescan = false;
 1352 
 1353        DBG_FUNC("OUT\n");
 1354 }

Cache object: 9c0cdb5b547c757e3be8f7aca0c7545b


[ 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.