Beispiel #1
0
/**
 * @brief this routine is called by OS' DPC to start io requests from internal
 *        high priority request queue
 * @param[in] fw_controller The framework controller.
 *
 * @return none
 */
void scif_sas_controller_start_high_priority_io(
   SCIF_SAS_CONTROLLER_T * fw_controller
)
{
   POINTER_UINT            io_address;
   SCIF_SAS_IO_REQUEST_T * fw_io;
   SCI_STATUS              status;

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(fw_controller),
      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
      "scif_controller_start_high_priority_io(0x%x) enter\n",
      fw_controller
   ));

   while ( !sci_pool_empty(fw_controller->hprq.pool) )
   {
      sci_pool_get(fw_controller->hprq.pool, io_address);

      fw_io = (SCIF_SAS_IO_REQUEST_T *)io_address;

      status = fw_controller->state_handlers->start_high_priority_io_handler(
         (SCI_BASE_CONTROLLER_T*) fw_controller,
         (SCI_BASE_REMOTE_DEVICE_T*) fw_io->parent.device,
         (SCI_BASE_REQUEST_T*) fw_io,
         SCI_CONTROLLER_INVALID_IO_TAG
      );
   }
}
Beispiel #2
0
SCI_IO_STATUS scif_controller_start_io(
   SCI_CONTROLLER_HANDLE_T     controller,
   SCI_REMOTE_DEVICE_HANDLE_T  remote_device,
   SCI_IO_REQUEST_HANDLE_T     io_request,
   U16                         io_tag
)
{
   SCIF_SAS_CONTROLLER_T * fw_controller = (SCIF_SAS_CONTROLLER_T*) controller;
   SCI_STATUS              status;

   SCIF_LOG_TRACE((
      sci_base_object_get_logger(controller),
      SCIF_LOG_OBJECT_CONTROLLER | SCIF_LOG_OBJECT_IO_REQUEST,
      "scif_controller_start_io(0x%x, 0x%x, 0x%x, 0x%x) enter\n",
      controller, remote_device, io_request, io_tag
   ));

   if (
         sci_pool_empty(fw_controller->hprq.pool)
      || scif_sas_controller_sufficient_resource(controller)
      )
   {
      status = fw_controller->state_handlers->start_io_handler(
                (SCI_BASE_CONTROLLER_T*) controller,
                (SCI_BASE_REMOTE_DEVICE_T*) remote_device,
                (SCI_BASE_REQUEST_T*) io_request,
                io_tag
             );
   }
   else
      status = SCI_FAILURE_INSUFFICIENT_RESOURCES;

   return (SCI_IO_STATUS)status;
}
void
isci_io_request_execute_scsi_io(union ccb *ccb,
    struct ISCI_CONTROLLER *controller)
{
	struct ccb_scsiio *csio = &ccb->csio;
	target_id_t target_id = ccb->ccb_h.target_id;
	struct ISCI_REQUEST *request;
	struct ISCI_IO_REQUEST *io_request;
	struct ISCI_REMOTE_DEVICE *device =
	    controller->remote_device[target_id];
	int error;

	if (device == NULL) {
		ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
		ccb->ccb_h.status &= ~CAM_STATUS_MASK;
		ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
		xpt_done(ccb);
		return;
	}

	if (sci_pool_empty(controller->request_pool)) {
		ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
		ccb->ccb_h.status &= ~CAM_STATUS_MASK;
		ccb->ccb_h.status |= CAM_REQUEUE_REQ;
		xpt_freeze_simq(controller->sim, 1);
		controller->is_frozen = TRUE;
		xpt_done(ccb);
		return;
	}

	ASSERT(device->is_resetting == FALSE);

	sci_pool_get(controller->request_pool, request);
	io_request = (struct ISCI_IO_REQUEST *)request;

	io_request->ccb = ccb;
	io_request->current_sge_index = 0;
	io_request->parent.remote_device_handle = device->sci_object;

	if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) != 0)
		panic("Unexpected CAM_SCATTER_VALID flag!  flags = 0x%x\n",
		    ccb->ccb_h.flags);

	if ((ccb->ccb_h.flags & CAM_DATA_PHYS) != 0)
		panic("Unexpected CAM_DATA_PHYS flag!  flags = 0x%x\n",
		    ccb->ccb_h.flags);

	error = bus_dmamap_load(io_request->parent.dma_tag,
	    io_request->parent.dma_map, csio->data_ptr, csio->dxfer_len,
	    isci_io_request_construct, io_request, 0x0);

	/* A resource shortage from BUSDMA will be automatically
	 * continued at a later point, pushing the CCB processing
	 * forward, which will in turn unfreeze the simq.
	 */
	if (error == EINPROGRESS) {
		xpt_freeze_simq(controller->sim, 1);
		ccb->ccb_h.flags |= CAM_RELEASE_SIMQ;
	}
}
Beispiel #4
0
/**
 * @brief This method will be invoked to allocate memory dynamically.
 *
 * @param[in]  controller This parameter represents the controller
 *             object for which to allocate memory.
 * @param[out] mde This parameter represents the memory descriptor to
 *             be filled in by the user that will reference the newly
 *             allocated memory.
 *
 * @return none
 */
void scif_cb_controller_allocate_memory(SCI_CONTROLLER_HANDLE_T controller,
    SCI_PHYSICAL_MEMORY_DESCRIPTOR_T *mde)
{
	struct ISCI_CONTROLLER *isci_controller = (struct ISCI_CONTROLLER *)
	    sci_object_get_association(controller);

	/*
	 * Note this routine is only used for buffers needed to translate
	 * SCSI UNMAP commands to ATA DSM commands for SATA disks.
	 *
	 * We first try to pull a buffer from the controller's pool, and only
	 * call contigmalloc if one isn't there.
	 */
	if (!sci_pool_empty(isci_controller->unmap_buffer_pool)) {
		sci_pool_get(isci_controller->unmap_buffer_pool,
		    mde->virtual_address);
	} else
		mde->virtual_address = contigmalloc(PAGE_SIZE,
		    M_ISCI, M_NOWAIT, 0, BUS_SPACE_MAXADDR,
		    mde->constant_memory_alignment, 0);

	if (mde->virtual_address != NULL)
		bus_dmamap_load(isci_controller->buffer_dma_tag,
		    NULL, mde->virtual_address, PAGE_SIZE,
		    isci_single_map, &mde->physical_address,
		    BUS_DMA_NOWAIT);
}
Beispiel #5
0
/**
 * @brief This routine is to allocate the memory for creating a new internal
 *        request.
 *
 * @param[in] scif_controller handle to frame controller
 *
 * @return void* address to internal request memory
 */
void * scif_sas_controller_allocate_internal_request(
   SCIF_SAS_CONTROLLER_T * fw_controller
)
{
   POINTER_UINT internal_io_address;

   if( !sci_pool_empty(fw_controller->internal_request_memory_pool) )
   {
      sci_pool_get(
         fw_controller->internal_request_memory_pool, internal_io_address
      );

      //clean the memory.
      memset((char*)internal_io_address, 0, scif_sas_internal_request_get_object_size());

      return (void *) internal_io_address;
   }
   else
      return NULL;
}
Beispiel #6
0
void
isci_remote_device_reset(struct ISCI_REMOTE_DEVICE *remote_device,
    union ccb *ccb)
{
	struct ISCI_CONTROLLER *controller = remote_device->domain->controller;
	struct ISCI_REQUEST *request;
	struct ISCI_TASK_REQUEST *task_request;
	SCI_STATUS status;

	if (remote_device->is_resetting == TRUE) {
		/* device is already being reset, so return immediately */
		return;
	}

	if (sci_pool_empty(controller->request_pool)) {
		/* No requests are available in our request pool.  If this reset is tied
		 *  to a CCB, ask CAM to requeue it.  Otherwise, we need to put it on our
		 *  pending device reset list, so that the reset will occur when a request
		 *  frees up.
		 */
		if (ccb == NULL)
			sci_fast_list_insert_tail(
			    &controller->pending_device_reset_list,
			    &remote_device->pending_device_reset_element);
		else {
			ccb->ccb_h.status &= ~CAM_STATUS_MASK;
			ccb->ccb_h.status |= CAM_REQUEUE_REQ;
			xpt_done(ccb);
		}
		return;
	}

	isci_log_message(0, "ISCI",
	    "Sending reset to device on controller %d domain %d CAM index %d\n",
	    controller->index, remote_device->domain->index,
	    remote_device->index
	);

	sci_pool_get(controller->request_pool, request);
	task_request = (struct ISCI_TASK_REQUEST *)request;

	task_request->parent.remote_device_handle = remote_device->sci_object;
	task_request->ccb = ccb;

	remote_device->is_resetting = TRUE;

	status = (SCI_STATUS) scif_task_request_construct(
	    controller->scif_controller_handle, remote_device->sci_object,
	    SCI_CONTROLLER_INVALID_IO_TAG, (void *)task_request,
	    (void *)((char*)task_request + sizeof(struct ISCI_TASK_REQUEST)),
	    &task_request->sci_object);

	if (status != SCI_SUCCESS) {
		isci_task_request_complete(controller->scif_controller_handle,
		    remote_device->sci_object, task_request->sci_object,
		    (SCI_TASK_STATUS)status);
		return;
	}

	status = (SCI_STATUS)scif_controller_start_task(
	    controller->scif_controller_handle, remote_device->sci_object,
	    task_request->sci_object, SCI_CONTROLLER_INVALID_IO_TAG);

	if (status != SCI_SUCCESS) {
		isci_task_request_complete(
		    controller->scif_controller_handle,
		    remote_device->sci_object, task_request->sci_object,
		    (SCI_TASK_STATUS)status);
		return;
	}
}
Beispiel #7
0
void
isci_io_request_execute_smp_io(union ccb *ccb,
    struct ISCI_CONTROLLER *controller)
{
	SCI_STATUS status;
	target_id_t target_id = ccb->ccb_h.target_id;
	struct ISCI_REQUEST *request;
	struct ISCI_IO_REQUEST *io_request;
	SCI_REMOTE_DEVICE_HANDLE_T smp_device_handle;
	struct ISCI_REMOTE_DEVICE *end_device = controller->remote_device[target_id];

	/* SMP commands are sent to an end device, because SMP devices are not
	 *  exposed to the kernel.  It is our responsibility to use this method
	 *  to get the SMP device that contains the specified end device.  If
	 *  the device is direct-attached, the handle will come back NULL, and
	 *  we'll just fail the SMP_IO with DEV_NOT_THERE.
	 */
	scif_remote_device_get_containing_device(end_device->sci_object,
	    &smp_device_handle);

	if (smp_device_handle == NULL) {
		ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
		ccb->ccb_h.status &= ~CAM_STATUS_MASK;
		ccb->ccb_h.status |= CAM_DEV_NOT_THERE;
		xpt_done(ccb);
		return;
	}

	if (sci_pool_empty(controller->request_pool)) {
		ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
		ccb->ccb_h.status &= ~CAM_STATUS_MASK;
		ccb->ccb_h.status |= CAM_REQUEUE_REQ;
		xpt_freeze_simq(controller->sim, 1);
		controller->is_frozen = TRUE;
		xpt_done(ccb);
		return;
	}

	ASSERT(device->is_resetting == FALSE);

	sci_pool_get(controller->request_pool, request);
	io_request = (struct ISCI_IO_REQUEST *)request;

	io_request->ccb = ccb;
	io_request->parent.remote_device_handle = smp_device_handle;

	status = isci_smp_request_construct(io_request);

	if (status != SCI_SUCCESS) {
		isci_io_request_complete(controller->scif_controller_handle,
		    smp_device_handle, io_request, (SCI_IO_STATUS)status);
		return;
	}

	sci_object_set_association(io_request->sci_object, io_request);

	status = (SCI_STATUS) scif_controller_start_io(
	    controller->scif_controller_handle, smp_device_handle,
	    io_request->sci_object, SCI_CONTROLLER_INVALID_IO_TAG);

	if (status != SCI_SUCCESS) {
		isci_io_request_complete(controller->scif_controller_handle,
		    smp_device_handle, io_request, (SCI_IO_STATUS)status);
		return;
	}

	if (ccb->ccb_h.timeout != CAM_TIME_INFINITY)
		callout_reset(&io_request->parent.timer, ccb->ccb_h.timeout,
		    isci_io_request_timeout, request);
}