#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/libata.h>
+#include <linux/hdreg.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/processor.h>
MODULE_PARM_DESC(log_level, "Set to 0 - 4 for increasing verbosity of device driver");
module_param_named(testmode, ipr_testmode, int, 0);
MODULE_PARM_DESC(testmode, "DANGEROUS!!! Allows unsupported configurations");
-module_param_named(fastfail, ipr_fastfail, int, 0);
+module_param_named(fastfail, ipr_fastfail, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(fastfail, "Reduce timeouts and retries");
module_param_named(transop_timeout, ipr_transop_timeout, int, 0);
MODULE_PARM_DESC(transop_timeout, "Time in seconds to wait for adapter to come operational (default: 300)");
module_param_named(enable_cache, ipr_enable_cache, int, 0);
MODULE_PARM_DESC(enable_cache, "Enable adapter's non-volatile write cache (default: 1)");
-module_param_named(debug, ipr_debug, int, 0);
+module_param_named(debug, ipr_debug, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Enable device driver debugging logging. Set to 1 to enable. (default: 0)");
module_param_named(dual_ioa_raid, ipr_dual_ioa_raid, int, 0);
MODULE_PARM_DESC(dual_ioa_raid, "Enable dual adapter RAID support. Set to 1 to enable. (default: 1)");
"9076: Configuration error, missing remote IOA"},
{0x06679100, 0, IPR_DEFAULT_LOG_LEVEL,
"4050: Enclosure does not support a required multipath function"},
+ {0x06690000, 0, IPR_DEFAULT_LOG_LEVEL,
+ "4070: Logically bad block written on device"},
{0x06690200, 0, IPR_DEFAULT_LOG_LEVEL,
"9041: Array protection temporarily suspended"},
{0x06698200, 0, IPR_DEFAULT_LOG_LEVEL,
sizeof(struct ipr_dump_entry_header);
driver_dump->location_entry.hdr.data_type = IPR_DUMP_DATA_TYPE_ASCII;
driver_dump->location_entry.hdr.id = IPR_DUMP_LOCATION_ID;
- strcpy(driver_dump->location_entry.location, ioa_cfg->pdev->dev.bus_id);
+ strcpy(driver_dump->location_entry.location, dev_name(&ioa_cfg->pdev->dev));
driver_dump->hdr.num_entries++;
}
}
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
- kobject_uevent(&ioa_cfg->host->shost_classdev.kobj, KOBJ_CHANGE);
+ kobject_uevent(&ioa_cfg->host->shost_dev.kobj, KOBJ_CHANGE);
LEAVE;
}
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
- struct class_device *cdev = container_of(kobj,struct class_device,kobj);
- struct Scsi_Host *shost = class_to_shost(cdev);
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
unsigned long lock_flags = 0;
- int size = IPR_TRACE_SIZE;
- char *src = (char *)ioa_cfg->trace;
-
- if (off > size)
- return 0;
- if (off + count > size) {
- size -= off;
- count = size;
- }
+ ssize_t ret;
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
- memcpy(buf, &src[off], count);
+ ret = memory_read_from_buffer(buf, count, &off, ioa_cfg->trace,
+ IPR_TRACE_SIZE);
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
- return count;
+
+ return ret;
}
static struct bin_attribute ipr_trace_attr = {
/**
* ipr_show_write_caching - Show the write caching attribute
- * @class_dev: class device struct
- * @buf: buffer
+ * @dev: device struct
+ * @buf: buffer
*
* Return value:
* number of bytes printed to buffer
**/
-static ssize_t ipr_show_write_caching(struct class_device *class_dev, char *buf)
+static ssize_t ipr_show_write_caching(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
unsigned long lock_flags = 0;
int i, len = 0;
/**
* ipr_store_write_caching - Enable/disable adapter write cache
- * @class_dev: class_device struct
- * @buf: buffer
- * @count: buffer size
+ * @dev: device struct
+ * @buf: buffer
+ * @count: buffer size
*
* This function will enable/disable adapter write cache.
*
* Return value:
* count on success / other on failure
**/
-static ssize_t ipr_store_write_caching(struct class_device *class_dev,
- const char *buf, size_t count)
+static ssize_t ipr_store_write_caching(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
unsigned long lock_flags = 0;
enum ipr_cache_state new_state = CACHE_INVALID;
return count;
}
-static struct class_device_attribute ipr_ioa_cache_attr = {
+static struct device_attribute ipr_ioa_cache_attr = {
.attr = {
.name = "write_cache",
.mode = S_IRUGO | S_IWUSR,
/**
* ipr_show_fw_version - Show the firmware version
- * @class_dev: class device struct
- * @buf: buffer
+ * @dev: class device struct
+ * @buf: buffer
*
* Return value:
* number of bytes printed to buffer
**/
-static ssize_t ipr_show_fw_version(struct class_device *class_dev, char *buf)
+static ssize_t ipr_show_fw_version(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
struct ipr_inquiry_page3 *ucode_vpd = &ioa_cfg->vpd_cbs->page3_data;
unsigned long lock_flags = 0;
return len;
}
-static struct class_device_attribute ipr_fw_version_attr = {
+static struct device_attribute ipr_fw_version_attr = {
.attr = {
.name = "fw_version",
.mode = S_IRUGO,
/**
* ipr_show_log_level - Show the adapter's error logging level
- * @class_dev: class device struct
- * @buf: buffer
+ * @dev: class device struct
+ * @buf: buffer
*
* Return value:
* number of bytes printed to buffer
**/
-static ssize_t ipr_show_log_level(struct class_device *class_dev, char *buf)
+static ssize_t ipr_show_log_level(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
unsigned long lock_flags = 0;
int len;
/**
* ipr_store_log_level - Change the adapter's error logging level
- * @class_dev: class device struct
- * @buf: buffer
+ * @dev: class device struct
+ * @buf: buffer
*
* Return value:
* number of bytes printed to buffer
**/
-static ssize_t ipr_store_log_level(struct class_device *class_dev,
+static ssize_t ipr_store_log_level(struct device *dev,
+ struct device_attribute *attr,
const char *buf, size_t count)
{
- struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
unsigned long lock_flags = 0;
return strlen(buf);
}
-static struct class_device_attribute ipr_log_level_attr = {
+static struct device_attribute ipr_log_level_attr = {
.attr = {
.name = "log_level",
.mode = S_IRUGO | S_IWUSR,
/**
* ipr_store_diagnostics - IOA Diagnostics interface
- * @class_dev: class_device struct
- * @buf: buffer
- * @count: buffer size
+ * @dev: device struct
+ * @buf: buffer
+ * @count: buffer size
*
* This function will reset the adapter and wait a reasonable
* amount of time for any errors that the adapter might log.
* Return value:
* count on success / other on failure
**/
-static ssize_t ipr_store_diagnostics(struct class_device *class_dev,
+static ssize_t ipr_store_diagnostics(struct device *dev,
+ struct device_attribute *attr,
const char *buf, size_t count)
{
- struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
unsigned long lock_flags = 0;
int rc = count;
return rc;
}
-static struct class_device_attribute ipr_diagnostics_attr = {
+static struct device_attribute ipr_diagnostics_attr = {
.attr = {
.name = "run_diagnostics",
.mode = S_IWUSR,
/**
* ipr_show_adapter_state - Show the adapter's state
- * @class_dev: class device struct
- * @buf: buffer
+ * @class_dev: device struct
+ * @buf: buffer
*
* Return value:
* number of bytes printed to buffer
**/
-static ssize_t ipr_show_adapter_state(struct class_device *class_dev, char *buf)
+static ssize_t ipr_show_adapter_state(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
- struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
unsigned long lock_flags = 0;
int len;
/**
* ipr_store_adapter_state - Change adapter state
- * @class_dev: class_device struct
- * @buf: buffer
- * @count: buffer size
+ * @dev: device struct
+ * @buf: buffer
+ * @count: buffer size
*
* This function will change the adapter's state.
*
* Return value:
* count on success / other on failure
**/
-static ssize_t ipr_store_adapter_state(struct class_device *class_dev,
+static ssize_t ipr_store_adapter_state(struct device *dev,
+ struct device_attribute *attr,
const char *buf, size_t count)
{
- struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
unsigned long lock_flags;
int result = count;
return result;
}
-static struct class_device_attribute ipr_ioa_state_attr = {
+static struct device_attribute ipr_ioa_state_attr = {
.attr = {
- .name = "state",
+ .name = "online_state",
.mode = S_IRUGO | S_IWUSR,
},
.show = ipr_show_adapter_state,
/**
* ipr_store_reset_adapter - Reset the adapter
- * @class_dev: class_device struct
- * @buf: buffer
- * @count: buffer size
+ * @dev: device struct
+ * @buf: buffer
+ * @count: buffer size
*
* This function will reset the adapter.
*
* Return value:
* count on success / other on failure
**/
-static ssize_t ipr_store_reset_adapter(struct class_device *class_dev,
+static ssize_t ipr_store_reset_adapter(struct device *dev,
+ struct device_attribute *attr,
const char *buf, size_t count)
{
- struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
unsigned long lock_flags;
int result = count;
return result;
}
-static struct class_device_attribute ipr_ioa_reset_attr = {
+static struct device_attribute ipr_ioa_reset_attr = {
.attr = {
.name = "reset_host",
.mode = S_IWUSR,
/**
* ipr_store_update_fw - Update the firmware on the adapter
- * @class_dev: class_device struct
- * @buf: buffer
- * @count: buffer size
+ * @class_dev: device struct
+ * @buf: buffer
+ * @count: buffer size
*
* This function will update the firmware on the adapter.
*
* Return value:
* count on success / other on failure
**/
-static ssize_t ipr_store_update_fw(struct class_device *class_dev,
- const char *buf, size_t count)
+static ssize_t ipr_store_update_fw(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
- struct Scsi_Host *shost = class_to_shost(class_dev);
+ struct Scsi_Host *shost = class_to_shost(dev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
struct ipr_ucode_image_header *image_hdr;
const struct firmware *fw_entry;
return result;
}
-static struct class_device_attribute ipr_update_fw_attr = {
+static struct device_attribute ipr_update_fw_attr = {
.attr = {
.name = "update_fw",
.mode = S_IWUSR,
.store = ipr_store_update_fw
};
-static struct class_device_attribute *ipr_ioa_attrs[] = {
+static struct device_attribute *ipr_ioa_attrs[] = {
&ipr_fw_version_attr,
&ipr_log_level_attr,
&ipr_diagnostics_attr,
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
- struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+ struct device *cdev = container_of(kobj, struct device, kobj);
struct Scsi_Host *shost = class_to_shost(cdev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
struct ipr_dump *dump;
struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
- struct class_device *cdev = container_of(kobj,struct class_device,kobj);
+ struct device *cdev = container_of(kobj, struct device, kobj);
struct Scsi_Host *shost = class_to_shost(cdev);
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)shost->hostdata;
int rc;
sdev->no_uld_attach = 1;
}
if (ipr_is_vset_device(res)) {
- sdev->timeout = IPR_VSET_RW_TIMEOUT;
+ blk_queue_rq_timeout(sdev->request_queue,
+ IPR_VSET_RW_TIMEOUT);
blk_queue_max_sectors(sdev->request_queue, IPR_VSET_MAX_SECTORS);
}
if (ipr_is_vset_device(res) || ipr_is_scsi_disk(res))
struct ipr_resource_entry *res;
res = (struct ipr_resource_entry *)sdev->hostdata;
- if (res && ipr_is_gata(res))
- return ata_scsi_ioctl(sdev, cmd, arg);
+ if (res && ipr_is_gata(res)) {
+ if (cmd == HDIO_GET_IDENTITY)
+ return -ENOTTY;
+ return ata_sas_scsi_ioctl(res->sata_port->ap, sdev, cmd, arg);
+ }
return -EINVAL;
}
}
/**
- * ipr_tf_read - Read the current ATA taskfile for the ATA port
- * @ap: ATA port
- * @tf: destination ATA taskfile
- *
- * Return value:
- * none
- **/
-static void ipr_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
-{
- struct ipr_sata_port *sata_port = ap->private_data;
- struct ipr_ioasa_gata *g = &sata_port->ioasa;
-
- tf->feature = g->error;
- tf->nsect = g->nsect;
- tf->lbal = g->lbal;
- tf->lbam = g->lbam;
- tf->lbah = g->lbah;
- tf->device = g->device;
- tf->command = g->status;
- tf->hob_nsect = g->hob_nsect;
- tf->hob_lbal = g->hob_lbal;
- tf->hob_lbam = g->hob_lbam;
- tf->hob_lbah = g->hob_lbah;
- tf->ctl = g->alt_status;
-}
-
-/**
* ipr_copy_sata_tf - Copy a SATA taskfile to an IOA data structure
* @regs: destination
* @tf: source ATA taskfile
}
/**
- * ipr_ata_check_status - Return last ATA status
- * @ap: ATA port
+ * ipr_qc_fill_rtf - Read result TF
+ * @qc: ATA queued command
*
* Return value:
- * ATA status
+ * true
**/
-static u8 ipr_ata_check_status(struct ata_port *ap)
+static bool ipr_qc_fill_rtf(struct ata_queued_cmd *qc)
{
- struct ipr_sata_port *sata_port = ap->private_data;
- return sata_port->ioasa.status;
-}
+ struct ipr_sata_port *sata_port = qc->ap->private_data;
+ struct ipr_ioasa_gata *g = &sata_port->ioasa;
+ struct ata_taskfile *tf = &qc->result_tf;
-/**
- * ipr_ata_check_altstatus - Return last ATA altstatus
- * @ap: ATA port
- *
- * Return value:
- * Alt ATA status
- **/
-static u8 ipr_ata_check_altstatus(struct ata_port *ap)
-{
- struct ipr_sata_port *sata_port = ap->private_data;
- return sata_port->ioasa.alt_status;
+ tf->feature = g->error;
+ tf->nsect = g->nsect;
+ tf->lbal = g->lbal;
+ tf->lbam = g->lbam;
+ tf->lbah = g->lbah;
+ tf->device = g->device;
+ tf->command = g->status;
+ tf->hob_nsect = g->hob_nsect;
+ tf->hob_lbal = g->hob_lbal;
+ tf->hob_lbam = g->hob_lbam;
+ tf->hob_lbah = g->hob_lbah;
+ tf->ctl = g->alt_status;
+
+ return true;
}
static struct ata_port_operations ipr_sata_ops = {
- .sff_check_status = ipr_ata_check_status,
- .sff_check_altstatus = ipr_ata_check_altstatus,
- .sff_dev_select = ata_noop_dev_select,
.phy_reset = ipr_ata_phy_reset,
.hardreset = ipr_sata_reset,
.post_internal_cmd = ipr_ata_post_internal,
- .sff_tf_read = ipr_tf_read,
.qc_prep = ata_noop_qc_prep,
.qc_issue = ipr_qc_issue,
- .qc_fill_rtf = ata_sff_qc_fill_rtf,
+ .qc_fill_rtf = ipr_qc_fill_rtf,
.port_start = ata_sas_port_start,
.port_stop = ata_sas_port_stop
};
list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
wake_up_all(&ioa_cfg->reset_wait_q);
- spin_unlock_irq(ioa_cfg->host->host_lock);
+ spin_unlock(ioa_cfg->host->host_lock);
scsi_unblock_requests(ioa_cfg->host);
- spin_lock_irq(ioa_cfg->host->host_lock);
+ spin_lock(ioa_cfg->host->host_lock);
if (!ioa_cfg->allow_cmds)
scsi_block_requests(ioa_cfg->host);
ENTER;
free_irq(pdev->irq, ioa_cfg);
+ pci_disable_msi(pdev);
iounmap(ioa_cfg->hdw_dma_regs);
pci_release_regions(pdev);
ipr_free_mem(ioa_cfg);
goto out;
}
+ if (!(rc = pci_enable_msi(pdev)))
+ dev_info(&pdev->dev, "MSI enabled\n");
+ else if (ipr_debug)
+ dev_info(&pdev->dev, "Cannot enable MSI\n");
+
dev_info(&pdev->dev, "Found IOA with IRQ: %d\n", pdev->irq);
host = scsi_host_alloc(&driver_template, sizeof(*ioa_cfg));
goto out_scsi_host_put;
}
- ipr_regs = ioremap(ipr_regs_pci, pci_resource_len(pdev, 0));
+ ipr_regs = pci_ioremap_bar(pdev, 0);
if (!ipr_regs) {
dev_err(&pdev->dev,
pci_set_master(pdev);
- rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
if (rc < 0) {
dev_err(&pdev->dev, "Failed to set PCI DMA mask\n");
goto cleanup_nomem;
out_scsi_host_put:
scsi_host_put(host);
out_disable:
+ pci_disable_msi(pdev);
pci_disable_device(pdev);
goto out;
}
ENTER;
- ipr_remove_trace_file(&ioa_cfg->host->shost_classdev.kobj,
+ ipr_remove_trace_file(&ioa_cfg->host->shost_dev.kobj,
&ipr_trace_attr);
- ipr_remove_dump_file(&ioa_cfg->host->shost_classdev.kobj,
+ ipr_remove_dump_file(&ioa_cfg->host->shost_dev.kobj,
&ipr_dump_attr);
scsi_remove_host(ioa_cfg->host);
return rc;
}
- rc = ipr_create_trace_file(&ioa_cfg->host->shost_classdev.kobj,
+ rc = ipr_create_trace_file(&ioa_cfg->host->shost_dev.kobj,
&ipr_trace_attr);
if (rc) {
return rc;
}
- rc = ipr_create_dump_file(&ioa_cfg->host->shost_classdev.kobj,
+ rc = ipr_create_dump_file(&ioa_cfg->host->shost_dev.kobj,
&ipr_dump_attr);
if (rc) {
- ipr_remove_trace_file(&ioa_cfg->host->shost_classdev.kobj,
+ ipr_remove_trace_file(&ioa_cfg->host->shost_dev.kobj,
&ipr_trace_attr);
scsi_remove_host(ioa_cfg->host);
__ipr_remove(pdev);
.remove = ipr_remove,
.shutdown = ipr_shutdown,
.err_handler = &ipr_err_handler,
- .dynids.use_driver_data = 1
};
/**