예제 #1
0
const char *esas2r_info(struct Scsi_Host *sh)
{
	struct esas2r_adapter *a = (struct esas2r_adapter *)sh->hostdata;
	static char esas2r_info_str[512];

	esas2r_log_dev(ESAS2R_LOG_INFO, &(sh->shost_gendev),
		       "esas2r_info() called");

	/*
	 * if we haven't done so already, register as a char driver
	 * and stick a node under "/proc/scsi/esas2r/ATTOnode"
	 */

	if (esas2r_proc_major <= 0) {
		esas2r_proc_host = sh;

		esas2r_proc_major = register_chrdev(0, ESAS2R_DRVR_NAME,
						    &esas2r_proc_fops);

		esas2r_log_dev(ESAS2R_LOG_DEBG, &(sh->shost_gendev),
			       "register_chrdev (major %d)",
			       esas2r_proc_major);

		if (esas2r_proc_major > 0) {
			struct proc_dir_entry *pde;

			pde = proc_create(ATTONODE_NAME, 0,
					  sh->hostt->proc_dir,
					  &esas2r_proc_fops);

			if (!pde) {
				esas2r_log_dev(ESAS2R_LOG_WARN,
					       &(sh->shost_gendev),
					       "failed to create_proc_entry");
				esas2r_proc_major = -1;
			}
		}
	}

	sprintf(esas2r_info_str,
		ESAS2R_LONGNAME " (bus 0x%02X, device 0x%02X, IRQ 0x%02X)"
		" driver version: "ESAS2R_VERSION_STR "  firmware version: "
		"%s\n",
		a->pcid->bus->number, a->pcid->devfn, a->pcid->irq,
		a->fw_rev[0] ? a->fw_rev : "(none)");

	return esas2r_info_str;
}
예제 #2
0
int esas2r_release(struct Scsi_Host *sh)
{
	esas2r_log_dev(ESAS2R_LOG_INFO, &(sh->shost_gendev),
		       "esas2r_release() called");

	esas2r_cleanup(sh);
	if (sh->irq)
		free_irq(sh->irq, NULL);
	scsi_unregister(sh);
	return 0;
}
예제 #3
0
static void esas2r_remove(struct pci_dev *pdev)
{
	struct Scsi_Host *host;
	int index;

	if (pdev == NULL) {
		esas2r_log(ESAS2R_LOG_WARN, "esas2r_remove pdev==NULL");
		return;
	}

	host = pci_get_drvdata(pdev);

	if (host == NULL) {
		/*
		 * this can happen if pci_set_drvdata was already called
		 * to clear the host pointer.  if this is the case, we
		 * are okay; this channel has already been cleaned up.
		 */

		return;
	}

	esas2r_log_dev(ESAS2R_LOG_INFO, &(pdev->dev),
		       "esas2r_remove(%p) called; "
		       "host:%p", pdev,
		       host);

	index = esas2r_cleanup(host);

	if (index < 0)
		esas2r_log_dev(ESAS2R_LOG_WARN, &(pdev->dev),
			       "unknown host in %s",
			       __func__);

	found_adapters--;

	/* if this was the last adapter, clean up the rest of the driver */

	if (found_adapters == 0)
		esas2r_cleanup(NULL);
}
예제 #4
0
static void esas2r_remove(struct pci_dev *pdev)
{
	struct Scsi_Host *host = pci_get_drvdata(pdev);
	struct esas2r_adapter *a = (struct esas2r_adapter *)host->hostdata;

	esas2r_log_dev(ESAS2R_LOG_INFO, &(pdev->dev),
		       "esas2r_remove(%p) called; "
		       "host:%p", pdev,
		       host);

	esas2r_kill_adapter(a->index);
	found_adapters--;
}
예제 #5
0
/**
 * Searches the specified queue for the specified queue for the command
 * to abort.
 *
 * @param [in] a
 * @param [in] abort_request
 * @param [in] cmd
 * t
 * @return 0 on failure, 1 if command was not found, 2 if command was found
 */
static int esas2r_check_active_queue(struct esas2r_adapter *a,
				     struct esas2r_request **abort_request,
				     struct scsi_cmnd *cmd,
				     struct list_head *queue)
{
	bool found = false;
	struct esas2r_request *ar = *abort_request;
	struct esas2r_request *rq;
	struct list_head *element, *next;

	list_for_each_safe(element, next, queue) {

		rq = list_entry(element, struct esas2r_request, req_list);

		if (rq->cmd == cmd) {

			/* Found the request.  See what to do with it. */
			if (queue == &a->active_list) {
				/*
				 * We are searching the active queue, which
				 * means that we need to send an abort request
				 * to the firmware.
				 */
				ar = esas2r_alloc_request(a);
				if (ar == NULL) {
					esas2r_log_dev(ESAS2R_LOG_WARN,
						       &(a->host->shost_gendev),
						       "unable to allocate an abort request for cmd %p",
						       cmd);
					return 0; /* Failure */
				}

				/*
				 * Task management request must be formatted
				 * with a lock held.
				 */
				ar->sense_len = 0;
				ar->vrq->scsi.length = 0;
				ar->target_id = rq->target_id;
				ar->vrq->scsi.flags |= cpu_to_le32(
					(u8)le32_to_cpu(rq->vrq->scsi.flags));

				memset(ar->vrq->scsi.cdb, 0,
				       sizeof(ar->vrq->scsi.cdb));

				ar->vrq->scsi.flags |= cpu_to_le32(
					FCP_CMND_TRM);
				ar->vrq->scsi.u.abort_handle =
					rq->vrq->scsi.handle;
			} else {
				/*
				 * The request is pending but not active on
				 * the firmware.  Just free it now and we'll
				 * report the successful abort below.
				 */
				list_del_init(&rq->req_list);
				esas2r_free_request(a, rq);
			}

			found = true;
			break;
		}

	}
예제 #6
0
static int esas2r_probe(struct pci_dev *pcid,
			const struct pci_device_id *id)
{
	struct Scsi_Host *host = NULL;
	struct esas2r_adapter *a;
	int err;

	size_t host_alloc_size = sizeof(struct esas2r_adapter)
				 + ((num_requests) +
				    1) * sizeof(struct esas2r_request);

	esas2r_log_dev(ESAS2R_LOG_DEBG, &(pcid->dev),
		       "esas2r_probe() 0x%02x 0x%02x 0x%02x 0x%02x",
		       pcid->vendor,
		       pcid->device,
		       pcid->subsystem_vendor,
		       pcid->subsystem_device);

	esas2r_log_dev(ESAS2R_LOG_INFO, &(pcid->dev),
		       "before pci_enable_device() "
		       "enable_cnt: %d",
		       pcid->enable_cnt.counter);

	err = pci_enable_device(pcid);
	if (err != 0) {
		esas2r_log_dev(ESAS2R_LOG_CRIT, &(pcid->dev),
			       "pci_enable_device() FAIL (%d)",
			       err);
		return -ENODEV;
	}

	esas2r_log_dev(ESAS2R_LOG_INFO, &(pcid->dev),
		       "pci_enable_device() OK");
	esas2r_log_dev(ESAS2R_LOG_INFO, &(pcid->dev),
		       "after pci_enable_device() enable_cnt: %d",
		       pcid->enable_cnt.counter);

	host = scsi_host_alloc(&driver_template, host_alloc_size);
	if (host == NULL) {
		esas2r_log(ESAS2R_LOG_CRIT, "scsi_host_alloc() FAIL");
		return -ENODEV;
	}

	memset(host->hostdata, 0, host_alloc_size);

	a = (struct esas2r_adapter *)host->hostdata;

	esas2r_log(ESAS2R_LOG_INFO, "scsi_host_alloc() OK host: %p", host);

	/* override max LUN and max target id */

	host->max_id = ESAS2R_MAX_ID + 1;
	host->max_lun = 255;

	/* we can handle 16-byte CDbs */

	host->max_cmd_len = 16;

	host->can_queue = can_queue;
	host->cmd_per_lun = cmd_per_lun;
	host->this_id = host->max_id + 1;
	host->max_channel = 0;
	host->unique_id = found_adapters;
	host->sg_tablesize = sg_tablesize;
	host->max_sectors = esas2r_max_sectors;

	/* set to bus master for BIOses that don't do it for us */

	esas2r_log(ESAS2R_LOG_INFO, "pci_set_master() called");

	pci_set_master(pcid);

	if (!esas2r_init_adapter(host, pcid, found_adapters)) {
		esas2r_log(ESAS2R_LOG_CRIT,
			   "unable to initialize device at PCI bus %x:%x",
			   pcid->bus->number,
			   pcid->devfn);

		esas2r_log_dev(ESAS2R_LOG_INFO, &(host->shost_gendev),
			       "scsi_host_put() called");

		scsi_host_put(host);

		return 0;

	}

	esas2r_log(ESAS2R_LOG_INFO, "pci_set_drvdata(%p, %p) called", pcid,
		   host->hostdata);

	pci_set_drvdata(pcid, host);

	esas2r_log(ESAS2R_LOG_INFO, "scsi_add_host() called");

	err = scsi_add_host(host, &pcid->dev);

	if (err) {
		esas2r_log(ESAS2R_LOG_CRIT, "scsi_add_host returned %d", err);
		esas2r_log_dev(ESAS2R_LOG_CRIT, &(host->shost_gendev),
			       "scsi_add_host() FAIL");

		esas2r_log_dev(ESAS2R_LOG_INFO, &(host->shost_gendev),
			       "scsi_host_put() called");

		scsi_host_put(host);

		esas2r_log_dev(ESAS2R_LOG_INFO, &(host->shost_gendev),
			       "pci_set_drvdata(%p, NULL) called",
			       pcid);

		pci_set_drvdata(pcid, NULL);

		return -ENODEV;
	}


	esas2r_fw_event_on(a);

	esas2r_log_dev(ESAS2R_LOG_INFO, &(host->shost_gendev),
		       "scsi_scan_host() called");

	scsi_scan_host(host);

	/* Add sysfs binary files */
	if (sysfs_create_bin_file(&host->shost_dev.kobj, &bin_attr_fw))
		esas2r_log_dev(ESAS2R_LOG_WARN, &(host->shost_gendev),
			       "Failed to create sysfs binary file: fw");
	else
		a->sysfs_fw_created = 1;

	if (sysfs_create_bin_file(&host->shost_dev.kobj, &bin_attr_fs))
		esas2r_log_dev(ESAS2R_LOG_WARN, &(host->shost_gendev),
			       "Failed to create sysfs binary file: fs");
	else
		a->sysfs_fs_created = 1;

	if (sysfs_create_bin_file(&host->shost_dev.kobj, &bin_attr_vda))
		esas2r_log_dev(ESAS2R_LOG_WARN, &(host->shost_gendev),
			       "Failed to create sysfs binary file: vda");
	else
		a->sysfs_vda_created = 1;

	if (sysfs_create_bin_file(&host->shost_dev.kobj, &bin_attr_hw))
		esas2r_log_dev(ESAS2R_LOG_WARN, &(host->shost_gendev),
			       "Failed to create sysfs binary file: hw");
	else
		a->sysfs_hw_created = 1;

	if (sysfs_create_bin_file(&host->shost_dev.kobj, &bin_attr_live_nvram))
		esas2r_log_dev(ESAS2R_LOG_WARN, &(host->shost_gendev),
			       "Failed to create sysfs binary file: live_nvram");
	else
		a->sysfs_live_nvram_created = 1;

	if (sysfs_create_bin_file(&host->shost_dev.kobj,
				  &bin_attr_default_nvram))
		esas2r_log_dev(ESAS2R_LOG_WARN, &(host->shost_gendev),
			       "Failed to create sysfs binary file: default_nvram");
	else
		a->sysfs_default_nvram_created = 1;

	found_adapters++;

	return 0;
}