示例#1
0
static void __exit esas2r_exit(void)
{
	esas2r_log(ESAS2R_LOG_INFO, "%s called", __func__);

	if (esas2r_proc_major > 0) {
		esas2r_log(ESAS2R_LOG_INFO, "unregister proc");

		remove_proc_entry(ATTONODE_NAME,
				  esas2r_proc_host->hostt->proc_dir);
		unregister_chrdev(esas2r_proc_major, ESAS2R_DRVR_NAME);

		esas2r_proc_major = 0;
	}

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

	pci_unregister_driver(&esas2r_pci_driver);
}
示例#2
0
int esas2r_show_info(struct seq_file *m, struct Scsi_Host *sh)
{
	struct esas2r_adapter *a = (struct esas2r_adapter *)sh->hostdata;

	struct esas2r_target *t;
	int dev_count = 0;

	esas2r_log(ESAS2R_LOG_DEBG, "esas2r_show_info (%p,%d)", m, sh->host_no);

	seq_printf(m, ESAS2R_LONGNAME "\n"
		   "Driver version: "ESAS2R_VERSION_STR "\n"
		   "Flash version: %s\n"
		   "Firmware version: %s\n"
		   "Copyright "ESAS2R_COPYRIGHT_YEARS "\n"
		   "http://www.attotech.com\n"
		   "\n",
		   a->flash_rev,
		   a->fw_rev[0] ? a->fw_rev : "(none)");


	seq_printf(m, "Adapter information:\n"
		   "--------------------\n"
		   "Model: %s\n"
		   "SAS address: %02X%02X%02X%02X:%02X%02X%02X%02X\n",
		   esas2r_get_model_name(a),
		   a->nvram->sas_addr[0],
		   a->nvram->sas_addr[1],
		   a->nvram->sas_addr[2],
		   a->nvram->sas_addr[3],
		   a->nvram->sas_addr[4],
		   a->nvram->sas_addr[5],
		   a->nvram->sas_addr[6],
		   a->nvram->sas_addr[7]);

	seq_puts(m, "\n"
		   "Discovered devices:\n"
		   "\n"
		   "   #  Target ID\n"
		   "---------------\n");

	for (t = a->targetdb; t < a->targetdb_end; t++)
		if (t->buffered_target_state == TS_PRESENT) {
			seq_printf(m, " %3d   %3d\n",
				   ++dev_count,
				   (u16)(uintptr_t)(t - a->targetdb));
		}

	if (dev_count == 0)
		seq_puts(m, "none\n");

	seq_putc(m, '\n');
	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 ssize_t write_hw(struct file *file, struct kobject *kobj,
			struct bin_attribute *attr,
			char *buf, loff_t off, size_t count)
{
	struct esas2r_adapter *a = esas2r_adapter_from_kobj(kobj);
	int length = min(sizeof(struct atto_ioctl), count);

	if (!a->local_atto_ioctl) {
		a->local_atto_ioctl = kmalloc(sizeof(struct atto_ioctl),
					      GFP_KERNEL);
		if (a->local_atto_ioctl == NULL) {
			esas2r_log(ESAS2R_LOG_WARN,
				   "write_hw kzalloc failed for %zu bytes",
				   sizeof(struct atto_ioctl));
			return -ENOMEM;
		}
	}

	memset(a->local_atto_ioctl, 0, sizeof(struct atto_ioctl));
	memcpy(a->local_atto_ioctl, buf, length);

	return length;
}
示例#5
0
static int __init esas2r_init(void)
{
	int i;

	esas2r_log(ESAS2R_LOG_INFO, "%s called", __func__);

	/* verify valid parameters */

	if (can_queue < 1) {
		esas2r_log(ESAS2R_LOG_WARN,
			   "warning: can_queue must be at least 1, value "
			   "forced.");
		can_queue = 1;
	} else if (can_queue > 2048) {
		esas2r_log(ESAS2R_LOG_WARN,
			   "warning: can_queue must be no larger than 2048, "
			   "value forced.");
		can_queue = 2048;
	}

	if (cmd_per_lun < 1) {
		esas2r_log(ESAS2R_LOG_WARN,
			   "warning: cmd_per_lun must be at least 1, value "
			   "forced.");
		cmd_per_lun = 1;
	} else if (cmd_per_lun > 2048) {
		esas2r_log(ESAS2R_LOG_WARN,
			   "warning: cmd_per_lun must be no larger than "
			   "2048, value forced.");
		cmd_per_lun = 2048;
	}

	if (sg_tablesize < 32) {
		esas2r_log(ESAS2R_LOG_WARN,
			   "warning: sg_tablesize must be at least 32, "
			   "value forced.");
		sg_tablesize = 32;
	}

	if (esas2r_max_sectors < 1) {
		esas2r_log(ESAS2R_LOG_WARN,
			   "warning: esas2r_max_sectors must be at least "
			   "1, value forced.");
		esas2r_max_sectors = 1;
	} else if (esas2r_max_sectors > 0xffff) {
		esas2r_log(ESAS2R_LOG_WARN,
			   "warning: esas2r_max_sectors must be no larger "
			   "than 0xffff, value forced.");
		esas2r_max_sectors = 0xffff;
	}

	sgl_page_size &= ~(ESAS2R_SGL_ALIGN - 1);

	if (sgl_page_size < SGL_PG_SZ_MIN)
		sgl_page_size = SGL_PG_SZ_MIN;
	else if (sgl_page_size > SGL_PG_SZ_MAX)
		sgl_page_size = SGL_PG_SZ_MAX;

	if (num_sg_lists < NUM_SGL_MIN)
		num_sg_lists = NUM_SGL_MIN;
	else if (num_sg_lists > NUM_SGL_MAX)
		num_sg_lists = NUM_SGL_MAX;

	if (num_requests < NUM_REQ_MIN)
		num_requests = NUM_REQ_MIN;
	else if (num_requests > NUM_REQ_MAX)
		num_requests = NUM_REQ_MAX;

	if (num_ae_requests < NUM_AE_MIN)
		num_ae_requests = NUM_AE_MIN;
	else if (num_ae_requests > NUM_AE_MAX)
		num_ae_requests = NUM_AE_MAX;

	/* set up other globals */

	for (i = 0; i < MAX_ADAPTERS; i++)
		esas2r_adapters[i] = NULL;

	return pci_register_driver(&esas2r_pci_driver);
}
示例#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;
}
示例#7
0
static int __init esas2r_init(void)
{
	int i;

	esas2r_log(ESAS2R_LOG_INFO, "%s called", __func__);

	/* verify valid parameters */

	if (can_queue < 1) {
		esas2r_log(ESAS2R_LOG_WARN,
			   "warning: can_queue must be at least 1, value "
			   "forced.");
		can_queue = 1;
	} else if (can_queue > 2048) {
		esas2r_log(ESAS2R_LOG_WARN,
			   "warning: can_queue must be no larger than 2048, "
			   "value forced.");
		can_queue = 2048;
	}

	if (cmd_per_lun < 1) {
		esas2r_log(ESAS2R_LOG_WARN,
			   "warning: cmd_per_lun must be at least 1, value "
			   "forced.");
		cmd_per_lun = 1;
	} else if (cmd_per_lun > 2048) {
		esas2r_log(ESAS2R_LOG_WARN,
			   "warning: cmd_per_lun must be no larger than "
			   "2048, value forced.");
		cmd_per_lun = 2048;
	}

	if (sg_tablesize < 32) {
		esas2r_log(ESAS2R_LOG_WARN,
			   "warning: sg_tablesize must be at least 32, "
			   "value forced.");
		sg_tablesize = 32;
	}

	if (esas2r_max_sectors < 1) {
		esas2r_log(ESAS2R_LOG_WARN,
			   "warning: esas2r_max_sectors must be at least "
			   "1, value forced.");
		esas2r_max_sectors = 1;
	} else if (esas2r_max_sectors > 0xffff) {
		esas2r_log(ESAS2R_LOG_WARN,
			   "warning: esas2r_max_sectors must be no larger "
			   "than 0xffff, value forced.");
		esas2r_max_sectors = 0xffff;
	}

	sgl_page_size &= ~(ESAS2R_SGL_ALIGN - 1);

	if (sgl_page_size < SGL_PG_SZ_MIN)
		sgl_page_size = SGL_PG_SZ_MIN;
	else if (sgl_page_size > SGL_PG_SZ_MAX)
		sgl_page_size = SGL_PG_SZ_MAX;

	if (num_sg_lists < NUM_SGL_MIN)
		num_sg_lists = NUM_SGL_MIN;
	else if (num_sg_lists > NUM_SGL_MAX)
		num_sg_lists = NUM_SGL_MAX;

	if (num_requests < NUM_REQ_MIN)
		num_requests = NUM_REQ_MIN;
	else if (num_requests > NUM_REQ_MAX)
		num_requests = NUM_REQ_MAX;

	if (num_ae_requests < NUM_AE_MIN)
		num_ae_requests = NUM_AE_MIN;
	else if (num_ae_requests > NUM_AE_MAX)
		num_ae_requests = NUM_AE_MAX;

	/* set up other globals */

	for (i = 0; i < MAX_ADAPTERS; i++)
		esas2r_adapters[i] = NULL;

	/* initialize */

	driver_template.module = THIS_MODULE;

	if (pci_register_driver(&esas2r_pci_driver) != 0)
		esas2r_log(ESAS2R_LOG_CRIT, "pci_register_driver FAILED");
	else
		esas2r_log(ESAS2R_LOG_INFO, "pci_register_driver() OK");

	if (!found_adapters) {
		pci_unregister_driver(&esas2r_pci_driver);
		esas2r_cleanup(NULL);

		esas2r_log(ESAS2R_LOG_CRIT,
			   "driver will not be loaded because no ATTO "
			   "%s devices were found",
			   ESAS2R_DRVR_NAME);
		return -1;
	} else {
		esas2r_log(ESAS2R_LOG_INFO, "found %d adapters",
			   found_adapters);
	}

	return 0;
}