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); }
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; }
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); }
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; }
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); }
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; }
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; }