diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-07 19:28:53 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-07 19:28:53 +0300 |
commit | 4dfddf503670d8def0fddb497e628130fc4522a8 (patch) | |
tree | f4bbf85589c13a1994fef75622ec80c48684f475 /drivers/scsi/ipr.c | |
parent | d4e65476bc68dbc9231b3c772b71f1576579b6fb (diff) | |
parent | 14bf41dcef651c13911a1715e83220732a3a4071 (diff) | |
download | linux-4dfddf503670d8def0fddb497e628130fc4522a8.tar.xz |
Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI updates from James Bottomley:
"This update includes the usual round of major driver updates (hpsa,
be2iscsi, hisi_sas, zfcp, cxlflash). There's a new incarnation of hpsa
called smartpqi for which a driver is added, there's some cleanup work
of the ibm vscsi target and updates to libfc, plus a whole host of
minor fixes and updates and finally the removal of several ISA drivers
which seem not to have been used for years"
* tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (173 commits)
scsi: mvsas: Mark symbols static where possible
scsi: pm8001: Mark symbols static where possible
scsi: arcmsr: Simplify user_len checking
scsi: fcoe: fix off by one in eth2fc_speed()
scsi: dtc: remove from tree
scsi: t128: remove from tree
scsi: pas16: remove from tree
scsi: u14-34f: remove from tree
scsi: ultrastor: remove from tree
scsi: in2000: remove from tree
scsi: wd7000: remove from tree
scsi: scsi_dh_alua: Fix memory leak in alua_rtpg()
scsi: lpfc: Mark symbols static where possible
scsi: hpsa: correct call to hpsa_do_reset
scsi: ufs: Get a TM service response from the correct offset
scsi: ibmvfc: Fix I/O hang when port is not mapped
scsi: megaraid_sas: clean function declarations in megaraid_sas_base.c up
scsi: ipr: Remove redundant messages at adapter init time
scsi: ipr: Don't log unnecessary 9084 error details
scsi: smartpqi: raid bypass lba calculation fix
...
Diffstat (limited to 'drivers/scsi/ipr.c')
-rw-r--r-- | drivers/scsi/ipr.c | 134 |
1 files changed, 118 insertions, 16 deletions
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 17d04c702e1b..a8762a3efeef 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -493,15 +493,15 @@ struct ipr_error_table_t ipr_error_table[] = { "9072: Link not operational transition"}, {0x066B8200, 0, IPR_DEFAULT_LOG_LEVEL, "9032: Array exposed but still protected"}, - {0x066B8300, 0, IPR_DEFAULT_LOG_LEVEL + 1, + {0x066B8300, 0, IPR_DEBUG_LOG_LEVEL, "70DD: Device forced failed by disrupt device command"}, {0x066B9100, 0, IPR_DEFAULT_LOG_LEVEL, "4061: Multipath redundancy level got better"}, {0x066B9200, 0, IPR_DEFAULT_LOG_LEVEL, "4060: Multipath redundancy level got worse"}, - {0x06808100, 0, IPR_DEFAULT_LOG_LEVEL, + {0x06808100, 0, IPR_DEBUG_LOG_LEVEL, "9083: Device raw mode enabled"}, - {0x06808200, 0, IPR_DEFAULT_LOG_LEVEL, + {0x06808200, 0, IPR_DEBUG_LOG_LEVEL, "9084: Device raw mode disabled"}, {0x07270000, 0, 0, "Failure due to other device"}, @@ -1473,7 +1473,7 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd) struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); - list_del(&hostrcb->queue); + list_del_init(&hostrcb->queue); list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); if (ioasc) { @@ -2552,6 +2552,23 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg, } } +static struct ipr_hostrcb *ipr_get_free_hostrcb(struct ipr_ioa_cfg *ioa) +{ + struct ipr_hostrcb *hostrcb; + + hostrcb = list_first_entry_or_null(&ioa->hostrcb_free_q, + struct ipr_hostrcb, queue); + + if (unlikely(!hostrcb)) { + dev_info(&ioa->pdev->dev, "Reclaiming async error buffers."); + hostrcb = list_first_entry_or_null(&ioa->hostrcb_report_q, + struct ipr_hostrcb, queue); + } + + list_del_init(&hostrcb->queue); + return hostrcb; +} + /** * ipr_process_error - Op done function for an adapter error log. * @ipr_cmd: ipr command struct @@ -2569,13 +2586,14 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd) struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); u32 fd_ioasc; + char *envp[] = { "ASYNC_ERR_LOG=1", NULL }; if (ioa_cfg->sis64) fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error64.fd_ioasc); else fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error.fd_ioasc); - list_del(&hostrcb->queue); + list_del_init(&hostrcb->queue); list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q); if (!ioasc) { @@ -2588,6 +2606,10 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd) "Host RCB failed with IOASC: 0x%08X\n", ioasc); } + list_add_tail(&hostrcb->queue, &ioa_cfg->hostrcb_report_q); + hostrcb = ipr_get_free_hostrcb(ioa_cfg); + kobject_uevent_env(&ioa_cfg->host->shost_dev.kobj, KOBJ_CHANGE, envp); + ipr_send_hcam(ioa_cfg, IPR_HCAM_CDB_OP_CODE_LOG_DATA, hostrcb); } @@ -4095,6 +4117,64 @@ static struct device_attribute ipr_ioa_fw_type_attr = { .show = ipr_show_fw_type }; +static ssize_t ipr_read_async_err_log(struct file *filep, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, + loff_t off, size_t count) +{ + 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_hostrcb *hostrcb; + unsigned long lock_flags = 0; + int ret; + + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + hostrcb = list_first_entry_or_null(&ioa_cfg->hostrcb_report_q, + struct ipr_hostrcb, queue); + if (!hostrcb) { + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + return 0; + } + ret = memory_read_from_buffer(buf, count, &off, &hostrcb->hcam, + sizeof(hostrcb->hcam)); + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + return ret; +} + +static ssize_t ipr_next_async_err_log(struct file *filep, struct kobject *kobj, + struct bin_attribute *bin_attr, char *buf, + loff_t off, size_t count) +{ + 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_hostrcb *hostrcb; + unsigned long lock_flags = 0; + + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + hostrcb = list_first_entry_or_null(&ioa_cfg->hostrcb_report_q, + struct ipr_hostrcb, queue); + if (!hostrcb) { + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + return count; + } + + /* Reclaim hostrcb before exit */ + list_move_tail(&hostrcb->queue, &ioa_cfg->hostrcb_free_q); + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + return count; +} + +static struct bin_attribute ipr_ioa_async_err_log = { + .attr = { + .name = "async_err_log", + .mode = S_IRUGO | S_IWUSR, + }, + .size = 0, + .read = ipr_read_async_err_log, + .write = ipr_next_async_err_log +}; + static struct device_attribute *ipr_ioa_attrs[] = { &ipr_fw_version_attr, &ipr_log_level_attr, @@ -7026,8 +7106,7 @@ static int ipr_ioa_reset_done(struct ipr_cmnd *ipr_cmd) { struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; struct ipr_resource_entry *res; - struct ipr_hostrcb *hostrcb, *temp; - int i = 0, j; + int j; ENTER; ioa_cfg->in_reset_reload = 0; @@ -7048,12 +7127,16 @@ static int ipr_ioa_reset_done(struct ipr_cmnd *ipr_cmd) } schedule_work(&ioa_cfg->work_q); - list_for_each_entry_safe(hostrcb, temp, &ioa_cfg->hostrcb_free_q, queue) { - list_del(&hostrcb->queue); - if (i++ < IPR_NUM_LOG_HCAMS) - ipr_send_hcam(ioa_cfg, IPR_HCAM_CDB_OP_CODE_LOG_DATA, hostrcb); + for (j = 0; j < IPR_NUM_HCAMS; j++) { + list_del_init(&ioa_cfg->hostrcb[j]->queue); + if (j < IPR_NUM_LOG_HCAMS) + ipr_send_hcam(ioa_cfg, + IPR_HCAM_CDB_OP_CODE_LOG_DATA, + ioa_cfg->hostrcb[j]); else - ipr_send_hcam(ioa_cfg, IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE, hostrcb); + ipr_send_hcam(ioa_cfg, + IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE, + ioa_cfg->hostrcb[j]); } scsi_report_bus_reset(ioa_cfg->host, IPR_VSET_BUS); @@ -7966,7 +8049,8 @@ static int ipr_ioafp_identify_hrrq(struct ipr_cmnd *ipr_cmd) ENTER; ipr_cmd->job_step = ipr_ioafp_std_inquiry; - dev_info(&ioa_cfg->pdev->dev, "Starting IOA initialization sequence.\n"); + if (ioa_cfg->identify_hrrq_index == 0) + dev_info(&ioa_cfg->pdev->dev, "Starting IOA initialization sequence.\n"); if (ioa_cfg->identify_hrrq_index < ioa_cfg->hrrq_num) { hrrq = &ioa_cfg->hrrq[ioa_cfg->identify_hrrq_index]; @@ -8335,7 +8419,7 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg) hostrcb = list_entry(ioa_cfg->hostrcb_free_q.next, struct ipr_hostrcb, queue); - list_del(&hostrcb->queue); + list_del_init(&hostrcb->queue); memset(&hostrcb->hcam, 0, sizeof(hostrcb->hcam)); rc = ipr_get_ldump_data_section(ioa_cfg, @@ -9332,7 +9416,7 @@ static void ipr_free_mem(struct ipr_ioa_cfg *ioa_cfg) dma_free_coherent(&ioa_cfg->pdev->dev, ioa_cfg->cfg_table_size, ioa_cfg->u.cfg_table, ioa_cfg->cfg_table_dma); - for (i = 0; i < IPR_NUM_HCAMS; i++) { + for (i = 0; i < IPR_MAX_HCAMS; i++) { dma_free_coherent(&ioa_cfg->pdev->dev, sizeof(struct ipr_hostrcb), ioa_cfg->hostrcb[i], @@ -9572,7 +9656,7 @@ static int ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg) if (!ioa_cfg->u.cfg_table) goto out_free_host_rrq; - for (i = 0; i < IPR_NUM_HCAMS; i++) { + for (i = 0; i < IPR_MAX_HCAMS; i++) { ioa_cfg->hostrcb[i] = dma_alloc_coherent(&pdev->dev, sizeof(struct ipr_hostrcb), &ioa_cfg->hostrcb_dma[i], @@ -9714,6 +9798,7 @@ static void ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg, INIT_LIST_HEAD(&ioa_cfg->hostrcb_free_q); INIT_LIST_HEAD(&ioa_cfg->hostrcb_pending_q); + INIT_LIST_HEAD(&ioa_cfg->hostrcb_report_q); INIT_LIST_HEAD(&ioa_cfg->free_res_q); INIT_LIST_HEAD(&ioa_cfg->used_res_q); INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread); @@ -10352,6 +10437,8 @@ static void ipr_remove(struct pci_dev *pdev) &ipr_trace_attr); ipr_remove_dump_file(&ioa_cfg->host->shost_dev.kobj, &ipr_dump_attr); + sysfs_remove_bin_file(&ioa_cfg->host->shost_dev.kobj, + &ipr_ioa_async_err_log); scsi_remove_host(ioa_cfg->host); __ipr_remove(pdev); @@ -10400,10 +10487,25 @@ static int ipr_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id) return rc; } + rc = sysfs_create_bin_file(&ioa_cfg->host->shost_dev.kobj, + &ipr_ioa_async_err_log); + + if (rc) { + ipr_remove_dump_file(&ioa_cfg->host->shost_dev.kobj, + &ipr_dump_attr); + ipr_remove_trace_file(&ioa_cfg->host->shost_dev.kobj, + &ipr_trace_attr); + scsi_remove_host(ioa_cfg->host); + __ipr_remove(pdev); + return rc; + } + rc = ipr_create_dump_file(&ioa_cfg->host->shost_dev.kobj, &ipr_dump_attr); if (rc) { + sysfs_remove_bin_file(&ioa_cfg->host->shost_dev.kobj, + &ipr_ioa_async_err_log); ipr_remove_trace_file(&ioa_cfg->host->shost_dev.kobj, &ipr_trace_attr); scsi_remove_host(ioa_cfg->host); |