From e6b50c30fa8d46c9401c2d48eee2351bdbb4c51c Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 7 May 2010 10:53:45 +0200 Subject: [SCSI] be2iscsi: correct return value in mgmt_invalidate_icds() This function should return 0 on error. Returning -1 would cause a crash. Also there is an extra space before the newline character and a missing space between the "for" and the "mgmt_invalidate_icds". I put the string on one line. The current version of checkpatch.pl complains that the line is too long, but it makes grepping easier. Signed-off-by: Dan Carpenter Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/be2iscsi/be_mgmt.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index e641922f20bc..350cbeaae160 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -167,10 +167,9 @@ unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, &nonemb_cmd.dma); if (nonemb_cmd.va == NULL) { SE_DEBUG(DBG_LVL_1, - "Failed to allocate memory for" - "mgmt_invalidate_icds \n"); + "Failed to allocate memory for mgmt_invalidate_icds\n"); spin_unlock(&ctrl->mbox_lock); - return -1; + return 0; } nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); req = nonemb_cmd.va; -- cgit v1.2.3 From 438b03311108b05a7b794bcf3941700853c62d1e Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Mon, 10 May 2010 09:13:00 -0700 Subject: [SCSI] ipr: implement fixes for 64 bit adapter support Implement some small fixes for 64 bit support that were preventing the adapter from becoming operational. Signed-off-by: Wayne Boyer Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 13 +++++++++---- drivers/scsi/ipr.h | 3 ++- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 6a6661c35b2f..735402f61aba 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -1040,7 +1040,7 @@ static void ipr_init_res_entry(struct ipr_resource_entry *res, proto = cfgtew->u.cfgte64->proto; res->res_flags = cfgtew->u.cfgte64->res_flags; res->qmodel = IPR_QUEUEING_MODEL64(res); - res->type = cfgtew->u.cfgte64->res_type & 0x0f; + res->type = cfgtew->u.cfgte64->res_type; memcpy(res->res_path, &cfgtew->u.cfgte64->res_path, sizeof(res->res_path)); @@ -5014,6 +5014,8 @@ static int ipr_build_ioadl64(struct ipr_ioa_cfg *ioa_cfg, ipr_cmd->dma_use_sg = nseg; + ioarcb->data_transfer_length = cpu_to_be32(length); + if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) { ioadl_flags = IPR_IOADL_FLAGS_WRITE; ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ; @@ -6706,7 +6708,7 @@ static int ipr_init_res_table(struct ipr_cmnd *ipr_cmd) list_move_tail(&res->queue, &old_res); if (ioa_cfg->sis64) - entries = ioa_cfg->u.cfg_table64->hdr64.num_entries; + entries = be16_to_cpu(ioa_cfg->u.cfg_table64->hdr64.num_entries); else entries = ioa_cfg->u.cfg_table->hdr.num_entries; @@ -6792,6 +6794,7 @@ static int ipr_ioafp_query_ioa_cfg(struct ipr_cmnd *ipr_cmd) ioarcb->res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE); ioarcb->cmd_pkt.cdb[0] = IPR_QUERY_IOA_CONFIG; + ioarcb->cmd_pkt.cdb[6] = (ioa_cfg->cfg_table_size >> 16) & 0xff; ioarcb->cmd_pkt.cdb[7] = (ioa_cfg->cfg_table_size >> 8) & 0xff; ioarcb->cmd_pkt.cdb[8] = ioa_cfg->cfg_table_size & 0xff; @@ -7122,7 +7125,9 @@ static int ipr_reset_next_stage(struct ipr_cmnd *ipr_cmd) ipr_dbg("IPL stage = 0x%lx, IPL stage time = %ld\n", stage, stage_time); /* sanity check the stage_time value */ - if (stage_time < IPR_IPL_INIT_MIN_STAGE_TIME) + if (stage_time == 0) + stage_time = IPR_IPL_INIT_DEFAULT_STAGE_TIME; + else if (stage_time < IPR_IPL_INIT_MIN_STAGE_TIME) stage_time = IPR_IPL_INIT_MIN_STAGE_TIME; else if (stage_time > IPR_LONG_OPERATIONAL_TIMEOUT) stage_time = IPR_LONG_OPERATIONAL_TIMEOUT; @@ -7364,7 +7369,7 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) } } - ENTER; + LEAVE; return IPR_RC_JOB_CONTINUE; } diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 4c267b5e0b96..4e7f81494ea4 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -244,6 +244,7 @@ #define IPR_RUNTIME_RESET 0x40000000 #define IPR_IPL_INIT_MIN_STAGE_TIME 5 +#define IPR_IPL_INIT_DEFAULT_STAGE_TIME 15 #define IPR_IPL_INIT_STAGE_UNKNOWN 0x0 #define IPR_IPL_INIT_STAGE_TRANSOP 0xB0000000 #define IPR_IPL_INIT_STAGE_MASK 0xff000000 @@ -804,7 +805,7 @@ struct ipr_hostrcb_array_data_entry_enhanced { }__attribute__((packed, aligned (4))); struct ipr_hostrcb_type_ff_error { - __be32 ioa_data[502]; + __be32 ioa_data[758]; }__attribute__((packed, aligned (4))); struct ipr_hostrcb_type_01_error { -- cgit v1.2.3 From 96d21f00ab59c9f27fad191d12a2ccfeff3c9108 Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Mon, 10 May 2010 09:13:27 -0700 Subject: [SCSI] ipr: include the resource path in the IOA status area structure The IOA status area now includes the new resource path field for 64 bit adapters. This patch changes the driver to fix the ioasa structure and to use the correct structure definition based on the type of adatper. Signed-off-by: Wayne Boyer Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 131 ++++++++++++++++++++++++++++++----------------------- drivers/scsi/ipr.h | 26 ++++++++++- 2 files changed, 98 insertions(+), 59 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 735402f61aba..8c2f4c4041c1 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -567,7 +567,8 @@ static void ipr_trc_hook(struct ipr_cmnd *ipr_cmd, static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd) { struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; - struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; + struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa; + struct ipr_ioasa64 *ioasa64 = &ipr_cmd->s.ioasa64; dma_addr_t dma_addr = ipr_cmd->dma_addr; memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt)); @@ -576,19 +577,19 @@ static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd) ioarcb->ioadl_len = 0; ioarcb->read_ioadl_len = 0; - if (ipr_cmd->ioa_cfg->sis64) + if (ipr_cmd->ioa_cfg->sis64) { ioarcb->u.sis64_addr_data.data_ioadl_addr = cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ioadl64)); - else { + ioasa64->u.gata.status = 0; + } else { ioarcb->write_ioadl_addr = cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, i.ioadl)); ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr; + ioasa->u.gata.status = 0; } - ioasa->ioasc = 0; - ioasa->residual_data_len = 0; - ioasa->u.gata.status = 0; - + ioasa->hdr.ioasc = 0; + ioasa->hdr.residual_data_len = 0; ipr_cmd->scsi_cmd = NULL; ipr_cmd->qc = NULL; ipr_cmd->sense_buffer[0] = 0; @@ -768,8 +769,8 @@ static void ipr_fail_all_ops(struct ipr_ioa_cfg *ioa_cfg) list_for_each_entry_safe(ipr_cmd, temp, &ioa_cfg->pending_q, queue) { list_del(&ipr_cmd->queue); - ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_IOA_WAS_RESET); - ipr_cmd->ioasa.ilid = cpu_to_be32(IPR_DRIVER_ILID); + ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_IOA_WAS_RESET); + ipr_cmd->s.ioasa.hdr.ilid = cpu_to_be32(IPR_DRIVER_ILID); if (ipr_cmd->scsi_cmd) ipr_cmd->done = ipr_scsi_eh_done; @@ -1319,7 +1320,7 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd) { struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; - u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); + u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); list_del(&hostrcb->queue); list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); @@ -2354,7 +2355,7 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd) { struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; - u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); + u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); u32 fd_ioasc; if (ioa_cfg->sis64) @@ -4509,11 +4510,16 @@ static int ipr_device_reset(struct ipr_ioa_cfg *ioa_cfg, } ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT); - ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); + ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); - if (ipr_is_gata(res) && res->sata_port && ioasc != IPR_IOASC_IOA_WAS_RESET) - memcpy(&res->sata_port->ioasa, &ipr_cmd->ioasa.u.gata, - sizeof(struct ipr_ioasa_gata)); + if (ipr_is_gata(res) && res->sata_port && ioasc != IPR_IOASC_IOA_WAS_RESET) { + if (ipr_cmd->ioa_cfg->sis64) + memcpy(&res->sata_port->ioasa, &ipr_cmd->s.ioasa64.u.gata, + sizeof(struct ipr_ioasa_gata)); + else + memcpy(&res->sata_port->ioasa, &ipr_cmd->s.ioasa.u.gata, + sizeof(struct ipr_ioasa_gata)); + } LEAVE; return (IPR_IOASC_SENSE_KEY(ioasc) ? -EIO : 0); @@ -4768,7 +4774,7 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd) scmd_printk(KERN_ERR, scsi_cmd, "Aborting command: %02X\n", scsi_cmd->cmnd[0]); ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_CANCEL_ALL_TIMEOUT); - ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); + ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); /* * If the abort task timed out and we sent a bus reset, we will get @@ -4940,7 +4946,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) ipr_cmd = ioa_cfg->ipr_cmnd_list[cmd_index]; - ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); + ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); ipr_trc_hook(ipr_cmd, IPR_TRACE_FINISH, ioasc); @@ -5137,7 +5143,7 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd) struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; struct ipr_resource_entry *res = scsi_cmd->device->hostdata; struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; - u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); + u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); if (IPR_IOASC_SENSE_KEY(ioasc) > 0) { scsi_cmd->result |= (DID_ERROR << 16); @@ -5168,7 +5174,7 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd) static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd) { struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; - struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; + struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa; dma_addr_t dma_addr = ipr_cmd->dma_addr; memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt)); @@ -5176,8 +5182,8 @@ static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd) ioarcb->read_data_transfer_length = 0; ioarcb->ioadl_len = 0; ioarcb->read_ioadl_len = 0; - ioasa->ioasc = 0; - ioasa->residual_data_len = 0; + ioasa->hdr.ioasc = 0; + ioasa->hdr.residual_data_len = 0; if (ipr_cmd->ioa_cfg->sis64) ioarcb->u.sis64_addr_data.data_ioadl_addr = @@ -5202,7 +5208,7 @@ static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd) static void ipr_erp_request_sense(struct ipr_cmnd *ipr_cmd) { struct ipr_cmd_pkt *cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt; - u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); + u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); if (IPR_IOASC_SENSE_KEY(ioasc) > 0) { ipr_erp_done(ipr_cmd); @@ -5279,12 +5285,12 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg, int i; u16 data_len; u32 ioasc, fd_ioasc; - struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; + struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa; __be32 *ioasa_data = (__be32 *)ioasa; int error_index; - ioasc = be32_to_cpu(ioasa->ioasc) & IPR_IOASC_IOASC_MASK; - fd_ioasc = be32_to_cpu(ioasa->fd_ioasc) & IPR_IOASC_IOASC_MASK; + ioasc = be32_to_cpu(ioasa->hdr.ioasc) & IPR_IOASC_IOASC_MASK; + fd_ioasc = be32_to_cpu(ioasa->hdr.fd_ioasc) & IPR_IOASC_IOASC_MASK; if (0 == ioasc) return; @@ -5299,7 +5305,7 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg, if (ioa_cfg->log_level < IPR_MAX_LOG_LEVEL) { /* Don't log an error if the IOA already logged one */ - if (ioasa->ilid != 0) + if (ioasa->hdr.ilid != 0) return; if (!ipr_is_gscsi(res)) @@ -5311,10 +5317,11 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg, ipr_res_err(ioa_cfg, res, "%s\n", ipr_error_table[error_index].error); - if (sizeof(struct ipr_ioasa) < be16_to_cpu(ioasa->ret_stat_len)) + data_len = be16_to_cpu(ioasa->hdr.ret_stat_len); + if (ioa_cfg->sis64 && sizeof(struct ipr_ioasa64) < data_len) + data_len = sizeof(struct ipr_ioasa64); + else if (!ioa_cfg->sis64 && sizeof(struct ipr_ioasa) < data_len) data_len = sizeof(struct ipr_ioasa); - else - data_len = be16_to_cpu(ioasa->ret_stat_len); ipr_err("IOASA Dump:\n"); @@ -5340,8 +5347,8 @@ static void ipr_gen_sense(struct ipr_cmnd *ipr_cmd) u32 failing_lba; u8 *sense_buf = ipr_cmd->scsi_cmd->sense_buffer; struct ipr_resource_entry *res = ipr_cmd->scsi_cmd->device->hostdata; - struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; - u32 ioasc = be32_to_cpu(ioasa->ioasc); + struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa; + u32 ioasc = be32_to_cpu(ioasa->hdr.ioasc); memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE); @@ -5384,7 +5391,7 @@ static void ipr_gen_sense(struct ipr_cmnd *ipr_cmd) /* Illegal request */ if ((IPR_IOASC_SENSE_KEY(ioasc) == 0x05) && - (be32_to_cpu(ioasa->ioasc_specific) & IPR_FIELD_POINTER_VALID)) { + (be32_to_cpu(ioasa->hdr.ioasc_specific) & IPR_FIELD_POINTER_VALID)) { sense_buf[7] = 10; /* additional length */ /* IOARCB was in error */ @@ -5395,10 +5402,10 @@ static void ipr_gen_sense(struct ipr_cmnd *ipr_cmd) sense_buf[16] = ((IPR_FIELD_POINTER_MASK & - be32_to_cpu(ioasa->ioasc_specific)) >> 8) & 0xff; + be32_to_cpu(ioasa->hdr.ioasc_specific)) >> 8) & 0xff; sense_buf[17] = (IPR_FIELD_POINTER_MASK & - be32_to_cpu(ioasa->ioasc_specific)) & 0xff; + be32_to_cpu(ioasa->hdr.ioasc_specific)) & 0xff; } else { if (ioasc == IPR_IOASC_MED_DO_NOT_REALLOC) { if (ipr_is_vset_device(res)) @@ -5430,14 +5437,20 @@ static void ipr_gen_sense(struct ipr_cmnd *ipr_cmd) **/ static int ipr_get_autosense(struct ipr_cmnd *ipr_cmd) { - struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; + struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa; + struct ipr_ioasa64 *ioasa64 = &ipr_cmd->s.ioasa64; - if ((be32_to_cpu(ioasa->ioasc_specific) & IPR_AUTOSENSE_VALID) == 0) + if ((be32_to_cpu(ioasa->hdr.ioasc_specific) & IPR_AUTOSENSE_VALID) == 0) return 0; - memcpy(ipr_cmd->scsi_cmd->sense_buffer, ioasa->auto_sense.data, - min_t(u16, be16_to_cpu(ioasa->auto_sense.auto_sense_len), - SCSI_SENSE_BUFFERSIZE)); + if (ipr_cmd->ioa_cfg->sis64) + memcpy(ipr_cmd->scsi_cmd->sense_buffer, ioasa64->auto_sense.data, + min_t(u16, be16_to_cpu(ioasa64->auto_sense.auto_sense_len), + SCSI_SENSE_BUFFERSIZE)); + else + memcpy(ipr_cmd->scsi_cmd->sense_buffer, ioasa->auto_sense.data, + min_t(u16, be16_to_cpu(ioasa->auto_sense.auto_sense_len), + SCSI_SENSE_BUFFERSIZE)); return 1; } @@ -5457,7 +5470,7 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg, { struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; struct ipr_resource_entry *res = scsi_cmd->device->hostdata; - u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); + u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); u32 masked_ioasc = ioasc & IPR_IOASC_IOASC_MASK; if (!res) { @@ -5549,9 +5562,9 @@ static void ipr_scsi_done(struct ipr_cmnd *ipr_cmd) { struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; - u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); + u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); - scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->ioasa.residual_data_len)); + scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->s.ioasa.hdr.residual_data_len)); if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) { scsi_dma_unmap(ipr_cmd->scsi_cmd); @@ -5841,19 +5854,23 @@ static void ipr_sata_done(struct ipr_cmnd *ipr_cmd) struct ata_queued_cmd *qc = ipr_cmd->qc; struct ipr_sata_port *sata_port = qc->ap->private_data; struct ipr_resource_entry *res = sata_port->res; - u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); + u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); - memcpy(&sata_port->ioasa, &ipr_cmd->ioasa.u.gata, - sizeof(struct ipr_ioasa_gata)); + if (ipr_cmd->ioa_cfg->sis64) + memcpy(&sata_port->ioasa, &ipr_cmd->s.ioasa64.u.gata, + sizeof(struct ipr_ioasa_gata)); + else + memcpy(&sata_port->ioasa, &ipr_cmd->s.ioasa.u.gata, + sizeof(struct ipr_ioasa_gata)); ipr_dump_ioasa(ioa_cfg, ipr_cmd, res); - if (be32_to_cpu(ipr_cmd->ioasa.ioasc_specific) & IPR_ATA_DEVICE_WAS_RESET) + if (be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc_specific) & IPR_ATA_DEVICE_WAS_RESET) scsi_report_device_reset(ioa_cfg->host, res->bus, res->target); if (IPR_IOASC_SENSE_KEY(ioasc) > RECOVERED_ERROR) - qc->err_mask |= __ac_err_mask(ipr_cmd->ioasa.u.gata.status); + qc->err_mask |= __ac_err_mask(sata_port->ioasa.status); else - qc->err_mask |= ac_err_mask(ipr_cmd->ioasa.u.gata.status); + qc->err_mask |= ac_err_mask(sata_port->ioasa.status); list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); ata_qc_complete(qc); } @@ -6522,7 +6539,7 @@ static void ipr_build_mode_sense(struct ipr_cmnd *ipr_cmd, static int ipr_reset_cmd_failed(struct ipr_cmnd *ipr_cmd) { struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; - u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); + u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); dev_err(&ioa_cfg->pdev->dev, "0x%02X failed with IOASC: 0x%08X\n", @@ -6546,7 +6563,7 @@ static int ipr_reset_cmd_failed(struct ipr_cmnd *ipr_cmd) static int ipr_reset_mode_sense_failed(struct ipr_cmnd *ipr_cmd) { struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; - u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); + u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) { ipr_cmd->job_step = ipr_set_supported_devs; @@ -6636,7 +6653,7 @@ static int ipr_ioafp_mode_select_page24(struct ipr_cmnd *ipr_cmd) **/ static int ipr_reset_mode_sense_page24_failed(struct ipr_cmnd *ipr_cmd) { - u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); + u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) { ipr_cmd->job_step = ipr_ioafp_mode_sense_page28; @@ -7337,12 +7354,12 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) rc = pci_restore_state(ioa_cfg->pdev); if (rc != PCIBIOS_SUCCESSFUL) { - ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); + ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); return IPR_RC_JOB_CONTINUE; } if (ipr_set_pcix_cmd_reg(ioa_cfg)) { - ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); + ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); return IPR_RC_JOB_CONTINUE; } @@ -7411,7 +7428,7 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd) if (rc != PCIBIOS_SUCCESSFUL) { pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev); - ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); + ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); rc = IPR_RC_JOB_CONTINUE; } else { ipr_cmd->job_step = ipr_reset_bist_done; @@ -7670,7 +7687,7 @@ static void ipr_reset_ioa_job(struct ipr_cmnd *ipr_cmd) struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; do { - ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); + ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); if (ioa_cfg->reset_cmd != ipr_cmd) { /* @@ -8053,13 +8070,13 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg) ioarcb->u.sis64_addr_data.data_ioadl_addr = cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ioadl64)); ioarcb->u.sis64_addr_data.ioasa_host_pci_addr = - cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, ioasa)); + cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, s.ioasa64)); } else { ioarcb->write_ioadl_addr = cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, i.ioadl)); ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr; ioarcb->ioasa_host_pci_addr = - cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, ioasa)); + cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, s.ioasa)); } ioarcb->ioasa_len = cpu_to_be16(sizeof(struct ipr_ioasa)); ipr_cmd->cmd_index = i; diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 4e7f81494ea4..f8a17d88db84 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -614,7 +614,7 @@ struct ipr_auto_sense { __be32 data[SCSI_SENSE_BUFFERSIZE/sizeof(__be32)]; }; -struct ipr_ioasa { +struct ipr_ioasa_hdr { __be32 ioasc; #define IPR_IOASC_SENSE_KEY(ioasc) ((ioasc) >> 24) #define IPR_IOASC_SENSE_CODE(ioasc) (((ioasc) & 0x00ff0000) >> 16) @@ -646,6 +646,25 @@ struct ipr_ioasa { #define IPR_FIELD_POINTER_VALID (0x80000000 >> 8) #define IPR_FIELD_POINTER_MASK 0x0000ffff +}__attribute__((packed, aligned (4))); + +struct ipr_ioasa { + struct ipr_ioasa_hdr hdr; + + union { + struct ipr_ioasa_vset vset; + struct ipr_ioasa_af_dasd dasd; + struct ipr_ioasa_gpdd gpdd; + struct ipr_ioasa_gata gata; + } u; + + struct ipr_auto_sense auto_sense; +}__attribute__((packed, aligned (4))); + +struct ipr_ioasa64 { + struct ipr_ioasa_hdr hdr; + u8 fd_res_path[8]; + union { struct ipr_ioasa_vset vset; struct ipr_ioasa_af_dasd dasd; @@ -1465,7 +1484,10 @@ struct ipr_cmnd { struct ipr_ioadl64_desc ioadl64[IPR_NUM_IOADL_ENTRIES]; struct ipr_ata64_ioadl ata_ioadl; } i; - struct ipr_ioasa ioasa; + union { + struct ipr_ioasa ioasa; + struct ipr_ioasa64 ioasa64; + } s; struct list_head queue; struct scsi_cmnd *scsi_cmd; struct ata_queued_cmd *qc; -- cgit v1.2.3 From 7be96900a2a662c67403559acd250f011b1d70db Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Mon, 10 May 2010 09:14:07 -0700 Subject: [SCSI] ipr: fix a register read to use the correct address for 64 bit adapters Fix ipr_reset_enable_ioa() to read the correct IOA to host interrupt register address for 64 bit adapters. We need to read the lower 32 bits, not the upper 32 bits. Also change the write of the 64 bit mask value to a single writeq instead of two writel calls. Finally, use the correct u8 type for the type field in the ipr_resource_entry structure. Signed-off-by: Wayne Boyer Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 12 ++++++++---- drivers/scsi/ipr.h | 2 +- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 8c2f4c4041c1..2f280d08fcc6 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -7187,13 +7187,14 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd) { struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; volatile u32 int_reg; + volatile u64 maskval; ENTER; ipr_cmd->job_step = ipr_ioafp_identify_hrrq; ipr_init_ioa_mem(ioa_cfg); ioa_cfg->allow_interrupts = 1; - int_reg = readl(ioa_cfg->regs.sense_interrupt_reg); + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { writel((IPR_PCII_ERROR_INTERRUPTS | IPR_PCII_HRRQ_UPDATED), @@ -7205,9 +7206,12 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd) /* Enable destructive diagnostics on IOA */ writel(ioa_cfg->doorbell, ioa_cfg->regs.set_uproc_interrupt_reg32); - writel(IPR_PCII_OPER_INTERRUPTS, ioa_cfg->regs.clr_interrupt_mask_reg32); - if (ioa_cfg->sis64) - writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_mask_reg); + if (ioa_cfg->sis64) { + maskval = IPR_PCII_IPL_STAGE_CHANGE; + maskval = (maskval << 32) | IPR_PCII_OPER_INTERRUPTS; + writeq(maskval, ioa_cfg->regs.clr_interrupt_mask_reg); + } else + writel(IPR_PCII_OPER_INTERRUPTS, ioa_cfg->regs.clr_interrupt_mask_reg32); int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index f8a17d88db84..9ecd2259eb39 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -1201,7 +1201,7 @@ struct ipr_resource_entry { u8 flags; __be16 res_flags; - __be32 type; + u8 type; u8 qmodel; struct ipr_std_inq_data std_inq_data; -- cgit v1.2.3 From b8803b1cef28af785c4e903b9b1449898d68c758 Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Fri, 14 May 2010 08:55:13 -0700 Subject: [SCSI] ipr: set the data list length in the request control block In bring up testing for the new 64 bit adapters, the first read command failed after loading the driver. The cause was that the command requires more than one scatter gather element and the corresponding code to set the data list length in the request control block was missing. This patch adds the correct assignment. Signed-off-by: Wayne Boyer Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 2f280d08fcc6..5244282cd97f 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -5021,6 +5021,8 @@ static int ipr_build_ioadl64(struct ipr_ioa_cfg *ioa_cfg, ipr_cmd->dma_use_sg = nseg; ioarcb->data_transfer_length = cpu_to_be32(length); + ioarcb->ioadl_len = + cpu_to_be32(sizeof(struct ipr_ioadl64_desc) * ipr_cmd->dma_use_sg); if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) { ioadl_flags = IPR_IOADL_FLAGS_WRITE; -- cgit v1.2.3 From 64ffdb762241c0a9c0c8fac7ea92aa0ba1529334 Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Wed, 19 May 2010 11:56:13 -0700 Subject: [SCSI] ipr: improve interrupt service routine performance During performance testing on P7 machines it was observed that the interrupt service routine was doing unnecessary MMIO operations. This patch rearranges the logic of the routine and moves some of the code out of the main routine. The result is that there are now fewer MMIO operations in the performance path of the code. Signed-off-by: Wayne Boyer Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 63 ++++++++++++++++++++++++++---------------------------- 1 file changed, 30 insertions(+), 33 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 5244282cd97f..82ea4a8226b0 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -4818,15 +4818,39 @@ static int ipr_eh_abort(struct scsi_cmnd * scsi_cmd) /** * ipr_handle_other_interrupt - Handle "other" interrupts * @ioa_cfg: ioa config struct - * @int_reg: interrupt register * * Return value: * IRQ_NONE / IRQ_HANDLED **/ -static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg, - volatile u32 int_reg) +static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg) { irqreturn_t rc = IRQ_HANDLED; + volatile u32 int_reg, int_mask_reg; + + int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32); + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; + + /* If an interrupt on the adapter did not occur, ignore it. + * Or in the case of SIS 64, check for a stage change interrupt. + */ + if ((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0) { + if (ioa_cfg->sis64) { + int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; + if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) { + + /* clear stage change */ + writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg); + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; + list_del(&ioa_cfg->reset_cmd->queue); + del_timer(&ioa_cfg->reset_cmd->timer); + ipr_reset_ioa_job(ioa_cfg->reset_cmd); + return IRQ_HANDLED; + } + } + + return IRQ_NONE; + } if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { /* Mask the interrupt */ @@ -4887,7 +4911,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) { struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp; unsigned long lock_flags = 0; - volatile u32 int_reg, int_mask_reg; + volatile u32 int_reg; u32 ioasc; u16 cmd_index; int num_hrrq = 0; @@ -4902,33 +4926,6 @@ static irqreturn_t ipr_isr(int irq, void *devp) return IRQ_NONE; } - int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32); - int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; - - /* If an interrupt on the adapter did not occur, ignore it. - * Or in the case of SIS 64, check for a stage change interrupt. - */ - if (unlikely((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0)) { - if (ioa_cfg->sis64) { - int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); - int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; - if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) { - - /* clear stage change */ - writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg); - int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; - list_del(&ioa_cfg->reset_cmd->queue); - del_timer(&ioa_cfg->reset_cmd->timer); - ipr_reset_ioa_job(ioa_cfg->reset_cmd); - spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); - return IRQ_HANDLED; - } - } - - spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); - return IRQ_NONE; - } - while (1) { ipr_cmd = NULL; @@ -4968,7 +4965,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) /* Clear the PCI interrupt */ do { writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32); - int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); } while (int_reg & IPR_PCII_HRRQ_UPDATED && num_hrrq++ < IPR_MAX_HRRQ_RETRIES); @@ -4983,7 +4980,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) } if (unlikely(rc == IRQ_NONE)) - rc = ipr_handle_other_interrupt(ioa_cfg, int_reg); + rc = ipr_handle_other_interrupt(ioa_cfg); spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); return rc; -- cgit v1.2.3 From 8c38a2951026e6b428d3ce6e518d123c35becd18 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Fri, 21 May 2010 18:24:16 -0500 Subject: [SCSI] iscsi_tcp: remove sk_sleep check There is no need to call sk_sleep before calling wake_up_interruptible, because the wait_queue_head is now with the socket. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index bf55d3057413..fec47de72535 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -601,10 +601,8 @@ static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); write_unlock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock); - if (sk_sleep(sock->sk)) { - sock->sk->sk_err = EIO; - wake_up_interruptible(sk_sleep(sock->sk)); - } + sock->sk->sk_err = EIO; + wake_up_interruptible(sk_sleep(sock->sk)); iscsi_conn_stop(cls_conn, flag); iscsi_sw_tcp_release_conn(conn); -- cgit v1.2.3 From 7873ca4e4401f0ecd8868bf1543113467e6bae61 Mon Sep 17 00:00:00 2001 From: Krishna Gudipati Date: Fri, 21 May 2010 14:39:45 -0700 Subject: [SCSI] bfa: fix system crash when reading sysfs fc_host statistics The port data structure related to fc_host statistics collection is not initialized. This causes system crash when reading the fc_host statistics. The fix is to initialize port structure during driver attach. Signed-off-by: Krishna Gudipati Signed-off-by: James Bottomley --- drivers/scsi/bfa/bfa_core.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index 0c08e185a766..3a7b3f88932f 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c @@ -84,11 +84,32 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo) for (i = 0; hal_mods[i]; i++) hal_mods[i]->meminfo(cfg, &km_len, &dm_len); + dm_len += bfa_port_meminfo(); meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_len = km_len; meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_len = dm_len; } +static void +bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi) +{ + struct bfa_port_s *port = &bfa->modules.port; + uint32_t dm_len; + uint8_t *dm_kva; + uint64_t dm_pa; + + dm_len = bfa_port_meminfo(); + dm_kva = bfa_meminfo_dma_virt(mi); + dm_pa = bfa_meminfo_dma_phys(mi); + + memset(port, 0, sizeof(struct bfa_port_s)); + bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod, bfa->logm); + bfa_port_mem_claim(port, dm_kva, dm_pa); + + bfa_meminfo_dma_virt(mi) = dm_kva + dm_len; + bfa_meminfo_dma_phys(mi) = dm_pa + dm_len; +} + /** * Use this function to do attach the driver instance with the BFA * library. This function will not trigger any HW initialization @@ -140,6 +161,7 @@ bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, for (i = 0; hal_mods[i]; i++) hal_mods[i]->attach(bfa, bfad, cfg, meminfo, pcidev); + bfa_com_port_attach(bfa, meminfo); } /** -- cgit v1.2.3 From 36b83ded062a7416bb9184f4d6c537ad99571f4d Mon Sep 17 00:00:00 2001 From: Nick Cheng Date: Mon, 17 May 2010 11:22:42 +0800 Subject: [SCSI] arcmsr: Support HW reset for EH and polling scheme for scsi device 1. To support instantaneous report for SCSI device existing by periodic polling 2. In arcmsr_iop_xfer(), inform AP of F/W's deadlock state to prevent endless waiting 3. To block the coming SCSI command while the driver is handling bus reset 4. To support HW reset in bus reset error handler Signed-off-by: Nick Cheng Signed-off-by: James Bottomley --- drivers/scsi/arcmsr/arcmsr.h | 29 +- drivers/scsi/arcmsr/arcmsr_attr.c | 3 + drivers/scsi/arcmsr/arcmsr_hba.c | 684 ++++++++++++++++++++++++++++---------- 3 files changed, 525 insertions(+), 191 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index ab646e580d64..ce5371b3cdd5 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h @@ -48,7 +48,7 @@ struct device_attribute; /*The limit of outstanding scsi command that firmware can handle*/ #define ARCMSR_MAX_OUTSTANDING_CMD 256 #define ARCMSR_MAX_FREECCB_NUM 320 -#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2008/02/27" +#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2008/11/03" #define ARCMSR_SCSI_INITIATOR_ID 255 #define ARCMSR_MAX_XFER_SECTORS 512 #define ARCMSR_MAX_XFER_SECTORS_B 4096 @@ -110,6 +110,8 @@ struct CMD_MESSAGE_FIELD #define FUNCTION_SAY_HELLO 0x0807 #define FUNCTION_SAY_GOODBYE 0x0808 #define FUNCTION_FLUSH_ADAPTER_CACHE 0x0809 +#define FUNCTION_GET_FIRMWARE_STATUS 0x080A +#define FUNCTION_HARDWARE_RESET 0x080B /* ARECA IO CONTROL CODE*/ #define ARCMSR_MESSAGE_READ_RQBUFFER \ ARECA_SATA_RAID | FUNCTION_READ_RQBUFFER @@ -133,6 +135,7 @@ struct CMD_MESSAGE_FIELD #define ARCMSR_MESSAGE_RETURNCODE_OK 0x00000001 #define ARCMSR_MESSAGE_RETURNCODE_ERROR 0x00000006 #define ARCMSR_MESSAGE_RETURNCODE_3F 0x0000003F +#define ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON 0x00000088 /* ************************************************************* ** structure for holding DMA address data @@ -341,13 +344,13 @@ struct MessageUnit_B uint32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; uint32_t postq_index; uint32_t doneq_index; - void __iomem *drv2iop_doorbell_reg; - void __iomem *drv2iop_doorbell_mask_reg; - void __iomem *iop2drv_doorbell_reg; - void __iomem *iop2drv_doorbell_mask_reg; - void __iomem *msgcode_rwbuffer_reg; - void __iomem *ioctl_wbuffer_reg; - void __iomem *ioctl_rbuffer_reg; + uint32_t __iomem *drv2iop_doorbell_reg; + uint32_t __iomem *drv2iop_doorbell_mask_reg; + uint32_t __iomem *iop2drv_doorbell_reg; + uint32_t __iomem *iop2drv_doorbell_mask_reg; + uint32_t __iomem *msgcode_rwbuffer_reg; + uint32_t __iomem *ioctl_wbuffer_reg; + uint32_t __iomem *ioctl_rbuffer_reg; }; /* @@ -375,6 +378,7 @@ struct AdapterControlBlock /* message unit ATU inbound base address0 */ uint32_t acb_flags; + uint8_t adapter_index; #define ACB_F_SCSISTOPADAPTER 0x0001 #define ACB_F_MSG_STOP_BGRB 0x0002 /* stop RAID background rebuild */ @@ -390,7 +394,7 @@ struct AdapterControlBlock #define ACB_F_BUS_RESET 0x0080 #define ACB_F_IOP_INITED 0x0100 /* iop init */ - + #define ACB_F_FIRMWARE_TRAP 0x0400 struct CommandControlBlock * pccb_pool[ARCMSR_MAX_FREECCB_NUM]; /* used for memory free */ struct list_head ccb_free_list; @@ -423,12 +427,19 @@ struct AdapterControlBlock #define ARECA_RAID_GOOD 0xaa uint32_t num_resets; uint32_t num_aborts; + uint32_t signature; uint32_t firm_request_len; uint32_t firm_numbers_queue; uint32_t firm_sdram_size; uint32_t firm_hd_channels; char firm_model[12]; char firm_version[20]; + char device_map[20]; /*21,84-99*/ + struct work_struct arcmsr_do_message_isr_bh; + struct timer_list eternal_timer; + unsigned short fw_state; + atomic_t rq_map_token; + int ante_token_value; };/* HW_DEVICE_EXTENSION */ /* ******************************************************************************* diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index a4e04c50c436..07fdfe57e38e 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c @@ -192,6 +192,7 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = { .attr = { .name = "mu_read", .mode = S_IRUSR , + .owner = THIS_MODULE, }, .size = 1032, .read = arcmsr_sysfs_iop_message_read, @@ -201,6 +202,7 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = { .attr = { .name = "mu_write", .mode = S_IWUSR, + .owner = THIS_MODULE, }, .size = 1032, .write = arcmsr_sysfs_iop_message_write, @@ -210,6 +212,7 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = { .attr = { .name = "mu_clear", .mode = S_IWUSR, + .owner = THIS_MODULE, }, .size = 1, .write = arcmsr_sysfs_iop_message_clear, diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index ffbe2192da3c..ffa54792bb33 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -72,8 +72,16 @@ #include #include "arcmsr.h" +#ifdef CONFIG_SCSI_ARCMSR_RESET + static int sleeptime = 20; + static int retrycount = 12; + module_param(sleeptime, int, S_IRUGO|S_IWUSR); + MODULE_PARM_DESC(sleeptime, "The waiting period for FW ready while bus reset"); + module_param(retrycount, int, S_IRUGO|S_IWUSR); + MODULE_PARM_DESC(retrycount, "The retry count for FW ready while bus reset"); +#endif MODULE_AUTHOR("Erich Chen "); -MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID HOST Adapter"); +MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID Host Bus Adapter"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_VERSION(ARCMSR_DRIVER_VERSION); @@ -96,6 +104,13 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb); static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb); static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb); +static void arcmsr_request_device_map(unsigned long pacb); +static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb); +static void arcmsr_request_hbb_device_map(struct AdapterControlBlock *acb); +static void arcmsr_message_isr_bh_fn(struct work_struct *work); +static void *arcmsr_get_firmware_spec(struct AdapterControlBlock *acb, int mode); +static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); + static const char *arcmsr_info(struct Scsi_Host *); static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, @@ -112,7 +127,7 @@ static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, static struct scsi_host_template arcmsr_scsi_host_template = { .module = THIS_MODULE, - .name = "ARCMSR ARECA SATA/SAS RAID HOST Adapter" + .name = "ARCMSR ARECA SATA/SAS RAID Host Bus Adapter" ARCMSR_DRIVER_VERSION, .info = arcmsr_info, .queuecommand = arcmsr_queue_command, @@ -128,16 +143,6 @@ static struct scsi_host_template arcmsr_scsi_host_template = { .use_clustering = ENABLE_CLUSTERING, .shost_attrs = arcmsr_host_attrs, }; -#ifdef CONFIG_SCSI_ARCMSR_AER -static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev); -static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, - pci_channel_state_t state); - -static struct pci_error_handlers arcmsr_pci_error_handlers = { - .error_detected = arcmsr_pci_error_detected, - .slot_reset = arcmsr_pci_slot_reset, -}; -#endif static struct pci_device_id arcmsr_device_id_table[] = { {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)}, {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1120)}, @@ -166,9 +171,6 @@ static struct pci_driver arcmsr_pci_driver = { .probe = arcmsr_probe, .remove = arcmsr_remove, .shutdown = arcmsr_shutdown, - #ifdef CONFIG_SCSI_ARCMSR_AER - .err_handler = &arcmsr_pci_error_handlers, - #endif }; static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id) @@ -236,10 +238,9 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) void *dma_coherent; dma_addr_t dma_coherent_handle, dma_addr; struct CommandControlBlock *ccb_tmp; - uint32_t intmask_org; int i, j; - acb->pmuA = pci_ioremap_bar(pdev, 0); + acb->pmuA = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); if (!acb->pmuA) { printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", acb->host->host_no); @@ -281,12 +282,6 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) for (i = 0; i < ARCMSR_MAX_TARGETID; i++) for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) acb->devstate[i][j] = ARECA_RAID_GONE; - - /* - ** here we need to tell iop 331 our ccb_tmp.HighPart - ** if ccb_tmp.HighPart is not zero - */ - intmask_org = arcmsr_disable_outbound_ints(acb); } break; @@ -297,7 +292,6 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) void __iomem *mem_base0, *mem_base1; void *dma_coherent; dma_addr_t dma_coherent_handle, dma_addr; - uint32_t intmask_org; struct CommandControlBlock *ccb_tmp; int i, j; @@ -333,11 +327,13 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) reg = (struct MessageUnit_B *)(dma_coherent + ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock)); acb->pmuB = reg; - mem_base0 = pci_ioremap_bar(pdev, 0); + mem_base0 = ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); if (!mem_base0) goto out; - mem_base1 = pci_ioremap_bar(pdev, 2); + mem_base1 = ioremap(pci_resource_start(pdev, 2), + pci_resource_len(pdev, 2)); if (!mem_base1) { iounmap(mem_base0); goto out; @@ -357,12 +353,6 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) for (i = 0; i < ARCMSR_MAX_TARGETID; i++) for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) acb->devstate[i][j] = ARECA_RAID_GOOD; - - /* - ** here we need to tell iop 331 our ccb_tmp.HighPart - ** if ccb_tmp.HighPart is not zero - */ - intmask_org = arcmsr_disable_outbound_ints(acb); } break; } @@ -374,6 +364,88 @@ out: sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle); return -ENOMEM; } +static void arcmsr_message_isr_bh_fn(struct work_struct *work) +{ + struct AdapterControlBlock *acb = container_of(work, struct AdapterControlBlock, arcmsr_do_message_isr_bh); + + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + + struct MessageUnit_A __iomem *reg = acb->pmuA; + char *acb_dev_map = (char *)acb->device_map; + uint32_t __iomem *signature = (uint32_t __iomem *) (®->message_rwbuffer[0]); + char __iomem *devicemap = (char __iomem *) (®->message_rwbuffer[21]); + int target, lun; + struct scsi_device *psdev; + char diff; + + atomic_inc(&acb->rq_map_token); + if (readl(signature) == ARCMSR_SIGNATURE_GET_CONFIG) { + for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++) { + diff = (*acb_dev_map)^readb(devicemap); + if (diff != 0) { + char temp; + *acb_dev_map = readb(devicemap); + temp = *acb_dev_map; + for (lun = 0; lun < ARCMSR_MAX_TARGETLUN; lun++) { + if ((temp & 0x01) == 1 && (diff & 0x01) == 1) { + scsi_add_device(acb->host, 0, target, lun); + } else if ((temp & 0x01) == 0 && (diff & 0x01) == 1) { + psdev = scsi_device_lookup(acb->host, 0, target, lun); + if (psdev != NULL) { + scsi_remove_device(psdev); + scsi_device_put(psdev); + } + } + temp >>= 1; + diff >>= 1; + } + } + devicemap++; + acb_dev_map++; + } + } + break; + } + + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = acb->pmuB; + char *acb_dev_map = (char *)acb->device_map; + uint32_t __iomem *signature = (uint32_t __iomem *)(®->msgcode_rwbuffer_reg[0]); + char __iomem *devicemap = (char __iomem *)(®->msgcode_rwbuffer_reg[21]); + int target, lun; + struct scsi_device *psdev; + char diff; + + atomic_inc(&acb->rq_map_token); + if (readl(signature) == ARCMSR_SIGNATURE_GET_CONFIG) { + for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++) { + diff = (*acb_dev_map)^readb(devicemap); + if (diff != 0) { + char temp; + *acb_dev_map = readb(devicemap); + temp = *acb_dev_map; + for (lun = 0; lun < ARCMSR_MAX_TARGETLUN; lun++) { + if ((temp & 0x01) == 1 && (diff & 0x01) == 1) { + scsi_add_device(acb->host, 0, target, lun); + } else if ((temp & 0x01) == 0 && (diff & 0x01) == 1) { + psdev = scsi_device_lookup(acb->host, 0, target, lun); + if (psdev != NULL) { + scsi_remove_device(psdev); + scsi_device_put(psdev); + } + } + temp >>= 1; + diff >>= 1; + } + } + devicemap++; + acb_dev_map++; + } + } + } + } +} static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id) @@ -432,17 +504,17 @@ static int arcmsr_probe(struct pci_dev *pdev, ACB_F_MESSAGE_WQBUFFER_READED); acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; INIT_LIST_HEAD(&acb->ccb_free_list); - + INIT_WORK(&acb->arcmsr_do_message_isr_bh, arcmsr_message_isr_bh_fn); error = arcmsr_alloc_ccb_pool(acb); if (error) goto out_release_regions; + arcmsr_iop_init(acb); error = request_irq(pdev->irq, arcmsr_do_interrupt, IRQF_SHARED, "arcmsr", acb); if (error) goto out_free_ccb_pool; - arcmsr_iop_init(acb); pci_set_drvdata(pdev, host); if (strncmp(acb->firm_version, "V1.42", 5) >= 0) host->max_sectors= ARCMSR_MAX_XFER_SECTORS_B; @@ -459,6 +531,14 @@ static int arcmsr_probe(struct pci_dev *pdev, #ifdef CONFIG_SCSI_ARCMSR_AER pci_enable_pcie_error_reporting(pdev); #endif + atomic_set(&acb->rq_map_token, 16); + acb->fw_state = true; + init_timer(&acb->eternal_timer); + acb->eternal_timer.expires = jiffies + msecs_to_jiffies(10*HZ); + acb->eternal_timer.data = (unsigned long) acb; + acb->eternal_timer.function = &arcmsr_request_device_map; + add_timer(&acb->eternal_timer); + return 0; out_free_sysfs: out_free_irq: @@ -518,40 +598,48 @@ static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) return 0xff; } -static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) +static uint8_t arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) { struct MessageUnit_A __iomem *reg = acb->pmuA; writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0); - if (arcmsr_hba_wait_msgint_ready(acb)) + if (arcmsr_hba_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'abort all outstanding command' timeout \n" , acb->host->host_no); + return 0xff; + } + return 0x00; } -static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) +static uint8_t arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) { struct MessageUnit_B *reg = acb->pmuB; writel(ARCMSR_MESSAGE_ABORT_CMD, reg->drv2iop_doorbell_reg); - if (arcmsr_hbb_wait_msgint_ready(acb)) + if (arcmsr_hbb_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'abort all outstanding command' timeout \n" , acb->host->host_no); + return 0xff; + } + return 0x00; } -static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) +static uint8_t arcmsr_abort_allcmd(struct AdapterControlBlock *acb) { + uint8_t rtnval = 0; switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - arcmsr_abort_hba_allcmd(acb); + rtnval = arcmsr_abort_hba_allcmd(acb); } break; case ACB_ADAPTER_TYPE_B: { - arcmsr_abort_hbb_allcmd(acb); + rtnval = arcmsr_abort_hbb_allcmd(acb); } } + return rtnval; } static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb) @@ -649,8 +737,7 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_A : { struct MessageUnit_A __iomem *reg = acb->pmuA; - orig_mask = readl(®->outbound_intmask)|\ - ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; + orig_mask = readl(®->outbound_intmask); writel(orig_mask|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, \ ®->outbound_intmask); } @@ -658,8 +745,7 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) case ACB_ADAPTER_TYPE_B : { struct MessageUnit_B *reg = acb->pmuB; - orig_mask = readl(reg->iop2drv_doorbell_mask_reg) & \ - (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); + orig_mask = readl(reg->iop2drv_doorbell_mask_reg); writel(0, reg->iop2drv_doorbell_mask_reg); } break; @@ -795,12 +881,13 @@ static void arcmsr_remove(struct pci_dev *pdev) struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; int poll_count = 0; - arcmsr_free_sysfs_attr(acb); scsi_remove_host(host); + flush_scheduled_work(); + del_timer_sync(&acb->eternal_timer); + arcmsr_disable_outbound_ints(acb); arcmsr_stop_adapter_bgrb(acb); arcmsr_flush_adapter_cache(acb); - arcmsr_disable_outbound_ints(acb); acb->acb_flags |= ACB_F_SCSISTOPADAPTER; acb->acb_flags &= ~ACB_F_IOP_INITED; @@ -841,7 +928,9 @@ static void arcmsr_shutdown(struct pci_dev *pdev) struct Scsi_Host *host = pci_get_drvdata(pdev); struct AdapterControlBlock *acb = (struct AdapterControlBlock *)host->hostdata; - + del_timer_sync(&acb->eternal_timer); + arcmsr_disable_outbound_ints(acb); + flush_scheduled_work(); arcmsr_stop_adapter_bgrb(acb); arcmsr_flush_adapter_cache(acb); } @@ -861,7 +950,7 @@ static void arcmsr_module_exit(void) module_init(arcmsr_module_init); module_exit(arcmsr_module_exit); -static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \ +static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, u32 intmask_org) { u32 mask; @@ -871,7 +960,8 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \ case ACB_ADAPTER_TYPE_A : { struct MessageUnit_A __iomem *reg = acb->pmuA; mask = intmask_org & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | - ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); + ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE| + ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE); writel(mask, ®->outbound_intmask); acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; } @@ -879,8 +969,10 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \ case ACB_ADAPTER_TYPE_B : { struct MessageUnit_B *reg = acb->pmuB; - mask = intmask_org | (ARCMSR_IOP2DRV_DATA_WRITE_OK | \ - ARCMSR_IOP2DRV_DATA_READ_OK | ARCMSR_IOP2DRV_CDB_DONE); + mask = intmask_org | (ARCMSR_IOP2DRV_DATA_WRITE_OK | + ARCMSR_IOP2DRV_DATA_READ_OK | + ARCMSR_IOP2DRV_CDB_DONE | + ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); writel(mask, reg->iop2drv_doorbell_mask_reg); acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; } @@ -1048,8 +1140,8 @@ static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb) } case ACB_ADAPTER_TYPE_B: { struct MessageUnit_B *reg = acb->pmuB; - iounmap(reg->drv2iop_doorbell_reg - ARCMSR_DRV2IOP_DOORBELL); - iounmap(reg->ioctl_wbuffer_reg - ARCMSR_IOCTL_WBUFFER); + iounmap((u8 *)reg->drv2iop_doorbell_reg - ARCMSR_DRV2IOP_DOORBELL); + iounmap((u8 *)reg->ioctl_wbuffer_reg - ARCMSR_IOCTL_WBUFFER); dma_free_coherent(&acb->pdev->dev, (ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20 + sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle); @@ -1249,13 +1341,36 @@ static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) reg->doneq_index = index; } } +/* +********************************************************************************** +** Handle a message interrupt +** +** The only message interrupt we expect is in response to a query for the current adapter config. +** We want this in order to compare the drivemap so that we can detect newly-attached drives. +********************************************************************************** +*/ +static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) +{ + struct MessageUnit_A *reg = acb->pmuA; + + /*clear interrupt and message state*/ + writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT, ®->outbound_intstatus); + schedule_work(&acb->arcmsr_do_message_isr_bh); +} +static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) +{ + struct MessageUnit_B *reg = acb->pmuB; + /*clear interrupt and message state*/ + writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN, reg->iop2drv_doorbell_reg); + schedule_work(&acb->arcmsr_do_message_isr_bh); +} static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) { uint32_t outbound_intstatus; struct MessageUnit_A __iomem *reg = acb->pmuA; - outbound_intstatus = readl(®->outbound_intstatus) & \ + outbound_intstatus = readl(®->outbound_intstatus) & acb->outbound_int_enable; if (!(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT)) { return 1; @@ -1267,6 +1382,10 @@ static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { arcmsr_hba_postqueue_isr(acb); } + if (outbound_intstatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { + /* messenger of "driver to iop commands" */ + arcmsr_hba_message_isr(acb); + } return 0; } @@ -1275,13 +1394,14 @@ static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) uint32_t outbound_doorbell; struct MessageUnit_B *reg = acb->pmuB; - outbound_doorbell = readl(reg->iop2drv_doorbell_reg) & \ + outbound_doorbell = readl(reg->iop2drv_doorbell_reg) & acb->outbound_int_enable; if (!outbound_doorbell) return 1; writel(~outbound_doorbell, reg->iop2drv_doorbell_reg); - /*in case the last action of doorbell interrupt clearance is cached, this action can push HW to write down the clear bit*/ + /*in case the last action of doorbell interrupt clearance is cached, + this action can push HW to write down the clear bit*/ readl(reg->iop2drv_doorbell_reg); writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg); if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { @@ -1293,6 +1413,10 @@ static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) if (outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { arcmsr_hbb_postqueue_isr(acb); } + if (outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { + /* messenger of "driver to iop commands" */ + arcmsr_hbb_message_isr(acb); + } return 0; } @@ -1360,7 +1484,7 @@ void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb) } } -static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ +static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_cmnd *cmd) { struct CMD_MESSAGE_FIELD *pcmdmessagefld; @@ -1398,6 +1522,13 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ retvalue = ARCMSR_MESSAGE_FAIL; goto message_out; } + + if (!acb->fw_state) { + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; + goto message_out; + } + ptmpQbuffer = ver_addr; while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) && (allxfer_len < 1031)) { @@ -1444,6 +1575,12 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ retvalue = ARCMSR_MESSAGE_FAIL; goto message_out; } + if (!acb->fw_state) { + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; + goto message_out; + } + ptmpuserbuffer = ver_addr; user_len = pcmdmessagefld->cmdmessage.Length; memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len); @@ -1496,6 +1633,11 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { uint8_t *pQbuffer = acb->rqbuffer; + if (!acb->fw_state) { + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; + goto message_out; + } if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; @@ -1511,6 +1653,11 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { uint8_t *pQbuffer = acb->wqbuffer; + if (!acb->fw_state) { + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; + goto message_out; + } if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; @@ -1529,6 +1676,11 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { uint8_t *pQbuffer; + if (!acb->fw_state) { + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; + goto message_out; + } if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; @@ -1551,13 +1703,22 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ break; case ARCMSR_MESSAGE_RETURN_CODE_3F: { + if (!acb->fw_state) { + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; + goto message_out; + } pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; } break; case ARCMSR_MESSAGE_SAY_HELLO: { int8_t *hello_string = "Hello! I am ARCMSR"; - + if (!acb->fw_state) { + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; + goto message_out; + } memcpy(pcmdmessagefld->messagedatabuffer, hello_string , (int16_t)strlen(hello_string)); pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; @@ -1565,10 +1726,20 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ break; case ARCMSR_MESSAGE_SAY_GOODBYE: + if (!acb->fw_state) { + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; + goto message_out; + } arcmsr_iop_parking(acb); break; case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: + if (!acb->fw_state) { + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; + goto message_out; + } arcmsr_flush_adapter_cache(acb); break; @@ -1651,16 +1822,57 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd, struct CommandControlBlock *ccb; int target = cmd->device->id; int lun = cmd->device->lun; - + uint8_t scsicmd = cmd->cmnd[0]; cmd->scsi_done = done; cmd->host_scribble = NULL; cmd->result = 0; + + if ((scsicmd == SYNCHRONIZE_CACHE) || (scsicmd == SEND_DIAGNOSTIC)) { + if (acb->devstate[target][lun] == ARECA_RAID_GONE) { + cmd->result = (DID_NO_CONNECT << 16); + } + cmd->scsi_done(cmd); + return 0; + } + if (acb->acb_flags & ACB_F_BUS_RESET) { - printk(KERN_NOTICE "arcmsr%d: bus reset" - " and return busy \n" - , acb->host->host_no); + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + struct MessageUnit_A __iomem *reg = acb->pmuA; + uint32_t intmask_org, outbound_doorbell; + + if ((readl(®->outbound_msgaddr1) & + ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) { + printk(KERN_NOTICE "arcmsr%d: bus reset and return busy\n", + acb->host->host_no); return SCSI_MLQUEUE_HOST_BUSY; } + + acb->acb_flags &= ~ACB_F_FIRMWARE_TRAP; + printk(KERN_NOTICE "arcmsr%d: hardware bus reset and reset ok\n", + acb->host->host_no); + /* disable all outbound interrupt */ + intmask_org = arcmsr_disable_outbound_ints(acb); + arcmsr_get_firmware_spec(acb, 1); + /*start background rebuild*/ + arcmsr_start_adapter_bgrb(acb); + /* clear Qbuffer if door bell ringed */ + outbound_doorbell = readl(®->outbound_doorbell); + /*clear interrupt */ + writel(outbound_doorbell, ®->outbound_doorbell); + writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, + ®->inbound_doorbell); + /* enable outbound Post Queue,outbound doorbell Interrupt */ + arcmsr_enable_outbound_ints(acb, intmask_org); + acb->acb_flags |= ACB_F_IOP_INITED; + acb->acb_flags &= ~ACB_F_BUS_RESET; + } + break; + case ACB_ADAPTER_TYPE_B: { + } + } + } + if (target == 16) { /* virtual device for iop message transfer */ arcmsr_handle_virtual_command(acb, cmd); @@ -1699,21 +1911,25 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd, return 0; } -static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) +static void *arcmsr_get_hba_config(struct AdapterControlBlock *acb, int mode) { struct MessageUnit_A __iomem *reg = acb->pmuA; char *acb_firm_model = acb->firm_model; char *acb_firm_version = acb->firm_version; + char *acb_device_map = acb->device_map; char __iomem *iop_firm_model = (char __iomem *)(®->message_rwbuffer[15]); char __iomem *iop_firm_version = (char __iomem *)(®->message_rwbuffer[17]); + char __iomem *iop_device_map = (char __iomem *) (®->message_rwbuffer[21]); int count; writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); if (arcmsr_hba_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ miscellaneous data' timeout \n", acb->host->host_no); + return NULL; } + if (mode == 1) { count = 8; while (count) { *acb_firm_model = readb(iop_firm_model); @@ -1730,34 +1946,48 @@ static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) count--; } + count = 16; + while (count) { + *acb_device_map = readb(iop_device_map); + acb_device_map++; + iop_device_map++; + count--; + } + printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n" , acb->host->host_no , acb->firm_version); - + acb->signature = readl(®->message_rwbuffer[0]); acb->firm_request_len = readl(®->message_rwbuffer[1]); acb->firm_numbers_queue = readl(®->message_rwbuffer[2]); acb->firm_sdram_size = readl(®->message_rwbuffer[3]); acb->firm_hd_channels = readl(®->message_rwbuffer[4]); } - -static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) + return reg->message_rwbuffer; +} +static void __iomem *arcmsr_get_hbb_config(struct AdapterControlBlock *acb, int mode) { struct MessageUnit_B *reg = acb->pmuB; uint32_t __iomem *lrwbuffer = reg->msgcode_rwbuffer_reg; char *acb_firm_model = acb->firm_model; char *acb_firm_version = acb->firm_version; + char *acb_device_map = acb->device_map; char __iomem *iop_firm_model = (char __iomem *)(&lrwbuffer[15]); /*firm_model,15,60-67*/ char __iomem *iop_firm_version = (char __iomem *)(&lrwbuffer[17]); /*firm_version,17,68-83*/ + char __iomem *iop_device_map = (char __iomem *) (&lrwbuffer[21]); + /*firm_version,21,84-99*/ int count; writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell_reg); if (arcmsr_hbb_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ miscellaneous data' timeout \n", acb->host->host_no); + return NULL; } + if (mode == 1) { count = 8; while (count) { @@ -1776,11 +2006,20 @@ static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) count--; } + count = 16; + while (count) { + *acb_device_map = readb(iop_device_map); + acb_device_map++; + iop_device_map++; + count--; + } + printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", acb->host->host_no, acb->firm_version); - lrwbuffer++; + acb->signature = readl(lrwbuffer++); + /*firm_signature,1,00-03*/ acb->firm_request_len = readl(lrwbuffer++); /*firm_request_len,1,04-07*/ acb->firm_numbers_queue = readl(lrwbuffer++); @@ -1790,20 +2029,23 @@ static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) acb->firm_hd_channels = readl(lrwbuffer); /*firm_ide_channels,4,16-19*/ } - -static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) + return reg->msgcode_rwbuffer_reg; +} +static void *arcmsr_get_firmware_spec(struct AdapterControlBlock *acb, int mode) { + void *rtnval = 0; switch (acb->adapter_type) { case ACB_ADAPTER_TYPE_A: { - arcmsr_get_hba_config(acb); + rtnval = arcmsr_get_hba_config(acb, mode); } break; case ACB_ADAPTER_TYPE_B: { - arcmsr_get_hbb_config(acb); + rtnval = arcmsr_get_hbb_config(acb, mode); } break; } + return rtnval; } static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, @@ -2043,6 +2285,66 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) } } +static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb) +{ + struct MessageUnit_A __iomem *reg = acb->pmuA; + + if (unlikely(atomic_read(&acb->rq_map_token) == 0)) { + acb->fw_state = false; + } else { + /*to prevent rq_map_token from changing by other interrupt, then + avoid the dead-lock*/ + acb->fw_state = true; + atomic_dec(&acb->rq_map_token); + if (!(acb->fw_state) || + (acb->ante_token_value == atomic_read(&acb->rq_map_token))) { + atomic_set(&acb->rq_map_token, 16); + } + acb->ante_token_value = atomic_read(&acb->rq_map_token); + writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); + } + mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6000)); + return; +} + +static void arcmsr_request_hbb_device_map(struct AdapterControlBlock *acb) +{ + struct MessageUnit_B __iomem *reg = acb->pmuB; + + if (unlikely(atomic_read(&acb->rq_map_token) == 0)) { + acb->fw_state = false; + } else { + /*to prevent rq_map_token from changing by other interrupt, then + avoid the dead-lock*/ + acb->fw_state = true; + atomic_dec(&acb->rq_map_token); + if (!(acb->fw_state) || + (acb->ante_token_value == atomic_read(&acb->rq_map_token))) { + atomic_set(&acb->rq_map_token, 16); + } + acb->ante_token_value = atomic_read(&acb->rq_map_token); + writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell_reg); + } + mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6000)); + return; +} + +static void arcmsr_request_device_map(unsigned long pacb) +{ + struct AdapterControlBlock *acb = (struct AdapterControlBlock *)pacb; + + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + arcmsr_request_hba_device_map(acb); + } + break; + case ACB_ADAPTER_TYPE_B: { + arcmsr_request_hbb_device_map(acb); + } + break; + } +} + static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) { struct MessageUnit_A __iomem *reg = acb->pmuA; @@ -2121,6 +2423,60 @@ static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) return; } +static void arcmsr_hardware_reset(struct AdapterControlBlock *acb) +{ + uint8_t value[64]; + int i; + + /* backup pci config data */ + for (i = 0; i < 64; i++) { + pci_read_config_byte(acb->pdev, i, &value[i]); + } + /* hardware reset signal */ + pci_write_config_byte(acb->pdev, 0x84, 0x20); + msleep(1000); + /* write back pci config data */ + for (i = 0; i < 64; i++) { + pci_write_config_byte(acb->pdev, i, value[i]); + } + msleep(1000); + return; +} +/* +**************************************************************************** +**************************************************************************** +*/ +#ifdef CONFIG_SCSI_ARCMSR_RESET + int arcmsr_sleep_for_bus_reset(struct scsi_cmnd *cmd) + { + struct Scsi_Host *shost = NULL; + spinlock_t *host_lock = NULL; + int i, isleep; + + shost = cmd->device->host; + host_lock = shost->host_lock; + + printk(KERN_NOTICE "Host %d bus reset over, sleep %d seconds (busy %d, can queue %d) ...........\n", + shost->host_no, sleeptime, shost->host_busy, shost->can_queue); + isleep = sleeptime / 10; + spin_unlock_irq(host_lock); + if (isleep > 0) { + for (i = 0; i < isleep; i++) { + msleep(10000); + printk(KERN_NOTICE "^%d^\n", i); + } + } + + isleep = sleeptime % 10; + if (isleep > 0) { + msleep(isleep * 1000); + printk(KERN_NOTICE "^v^\n"); + } + spin_lock_irq(host_lock); + printk(KERN_NOTICE "***** wake up *****\n"); + return 0; + } +#endif static void arcmsr_iop_init(struct AdapterControlBlock *acb) { uint32_t intmask_org; @@ -2129,7 +2485,7 @@ static void arcmsr_iop_init(struct AdapterControlBlock *acb) intmask_org = arcmsr_disable_outbound_ints(acb); arcmsr_wait_firmware_ready(acb); arcmsr_iop_confirm(acb); - arcmsr_get_firmware_spec(acb); + arcmsr_get_firmware_spec(acb, 1); /*start background rebuild*/ arcmsr_start_adapter_bgrb(acb); /* empty doorbell Qbuffer if door bell ringed */ @@ -2140,51 +2496,110 @@ static void arcmsr_iop_init(struct AdapterControlBlock *acb) acb->acb_flags |= ACB_F_IOP_INITED; } -static void arcmsr_iop_reset(struct AdapterControlBlock *acb) +static uint8_t arcmsr_iop_reset(struct AdapterControlBlock *acb) { struct CommandControlBlock *ccb; uint32_t intmask_org; + uint8_t rtnval = 0x00; int i = 0; if (atomic_read(&acb->ccboutstandingcount) != 0) { + /* disable all outbound interrupt */ + intmask_org = arcmsr_disable_outbound_ints(acb); /* talk to iop 331 outstanding command aborted */ - arcmsr_abort_allcmd(acb); - + rtnval = arcmsr_abort_allcmd(acb); /* wait for 3 sec for all command aborted*/ ssleep(3); - - /* disable all outbound interrupt */ - intmask_org = arcmsr_disable_outbound_ints(acb); /* clear all outbound posted Q */ arcmsr_done4abort_postqueue(acb); for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { ccb = acb->pccb_pool[i]; if (ccb->startdone == ARCMSR_CCB_START) { - ccb->startdone = ARCMSR_CCB_ABORTED; arcmsr_ccb_complete(ccb, 1); } } + atomic_set(&acb->ccboutstandingcount, 0); /* enable all outbound interrupt */ arcmsr_enable_outbound_ints(acb, intmask_org); + return rtnval; } + return rtnval; } static int arcmsr_bus_reset(struct scsi_cmnd *cmd) { struct AdapterControlBlock *acb = (struct AdapterControlBlock *)cmd->device->host->hostdata; - int i; + int retry = 0; - acb->num_resets++; + if (acb->acb_flags & ACB_F_BUS_RESET) + return SUCCESS; + + printk(KERN_NOTICE "arcmsr%d: bus reset ..... \n", acb->adapter_index); acb->acb_flags |= ACB_F_BUS_RESET; - for (i = 0; i < 400; i++) { - if (!atomic_read(&acb->ccboutstandingcount)) + acb->num_resets++; + while (atomic_read(&acb->ccboutstandingcount) != 0 && retry < 4) { + arcmsr_interrupt(acb); + retry++; + } + + if (arcmsr_iop_reset(acb)) { + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + printk(KERN_NOTICE "arcmsr%d: do hardware bus reset, num_resets = %d num_aborts = %d \n", + acb->adapter_index, acb->num_resets, acb->num_aborts); + arcmsr_hardware_reset(acb); + acb->acb_flags |= ACB_F_FIRMWARE_TRAP; + acb->acb_flags &= ~ACB_F_IOP_INITED; + #ifdef CONFIG_SCSI_ARCMSR_RESET + struct MessageUnit_A __iomem *reg = acb->pmuA; + uint32_t intmask_org, outbound_doorbell; + int retry_count = 0; +sleep_again: + arcmsr_sleep_for_bus_reset(cmd); + if ((readl(®->outbound_msgaddr1) & + ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) { + printk(KERN_NOTICE "arcmsr%d: hardware bus reset and return busy, retry=%d \n", + acb->host->host_no, retry_count); + if (retry_count > retrycount) { + printk(KERN_NOTICE "arcmsr%d: hardware bus reset and return busy, retry aborted \n", + acb->host->host_no); + return SUCCESS; + } + retry_count++; + goto sleep_again; + } + acb->acb_flags &= ~ACB_F_FIRMWARE_TRAP; + acb->acb_flags |= ACB_F_IOP_INITED; + acb->acb_flags &= ~ACB_F_BUS_RESET; + printk(KERN_NOTICE "arcmsr%d: hardware bus reset and reset ok \n", + acb->host->host_no); + /* disable all outbound interrupt */ + intmask_org = arcmsr_disable_outbound_ints(acb); + arcmsr_get_firmware_spec(acb, 1); + /*start background rebuild*/ + arcmsr_start_adapter_bgrb(acb); + /* clear Qbuffer if door bell ringed */ + outbound_doorbell = readl(®->outbound_doorbell); + writel(outbound_doorbell, ®->outbound_doorbell); /*clear interrupt */ + writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell); + /* enable outbound Post Queue,outbound doorbell Interrupt */ + arcmsr_enable_outbound_ints(acb, intmask_org); + atomic_set(&acb->rq_map_token, 16); + init_timer(&acb->eternal_timer); + acb->eternal_timer.expires = jiffies + msecs_to_jiffies(20*HZ); + acb->eternal_timer.data = (unsigned long) acb; + acb->eternal_timer.function = &arcmsr_request_device_map; + add_timer(&acb->eternal_timer); + #endif + } break; - arcmsr_interrupt(acb);/* FIXME: need spinlock */ - msleep(25); + case ACB_ADAPTER_TYPE_B: { } - arcmsr_iop_reset(acb); + } + } else { acb->acb_flags &= ~ACB_F_BUS_RESET; + } return SUCCESS; } @@ -2277,98 +2692,3 @@ static const char *arcmsr_info(struct Scsi_Host *host) ARCMSR_DRIVER_VERSION); return buf; } -#ifdef CONFIG_SCSI_ARCMSR_AER -static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev) -{ - struct Scsi_Host *host = pci_get_drvdata(pdev); - struct AdapterControlBlock *acb = - (struct AdapterControlBlock *) host->hostdata; - uint32_t intmask_org; - int i, j; - - if (pci_enable_device(pdev)) { - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - intmask_org = arcmsr_disable_outbound_ints(acb); - acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | - ACB_F_MESSAGE_RQBUFFER_CLEARED | - ACB_F_MESSAGE_WQBUFFER_READED); - acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; - for (i = 0; i < ARCMSR_MAX_TARGETID; i++) - for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) - acb->devstate[i][j] = ARECA_RAID_GONE; - - arcmsr_wait_firmware_ready(acb); - arcmsr_iop_confirm(acb); - /* disable all outbound interrupt */ - arcmsr_get_firmware_spec(acb); - /*start background rebuild*/ - arcmsr_start_adapter_bgrb(acb); - /* empty doorbell Qbuffer if door bell ringed */ - arcmsr_clear_doorbell_queue_buffer(acb); - arcmsr_enable_eoi_mode(acb); - /* enable outbound Post Queue,outbound doorbell Interrupt */ - arcmsr_enable_outbound_ints(acb, intmask_org); - acb->acb_flags |= ACB_F_IOP_INITED; - - pci_enable_pcie_error_reporting(pdev); - return PCI_ERS_RESULT_RECOVERED; -} - -static void arcmsr_pci_ers_need_reset_forepart(struct pci_dev *pdev) -{ - struct Scsi_Host *host = pci_get_drvdata(pdev); - struct AdapterControlBlock *acb = (struct AdapterControlBlock *)host->hostdata; - struct CommandControlBlock *ccb; - uint32_t intmask_org; - int i = 0; - - if (atomic_read(&acb->ccboutstandingcount) != 0) { - /* talk to iop 331 outstanding command aborted */ - arcmsr_abort_allcmd(acb); - /* wait for 3 sec for all command aborted*/ - ssleep(3); - /* disable all outbound interrupt */ - intmask_org = arcmsr_disable_outbound_ints(acb); - /* clear all outbound posted Q */ - arcmsr_done4abort_postqueue(acb); - for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { - ccb = acb->pccb_pool[i]; - if (ccb->startdone == ARCMSR_CCB_START) { - ccb->startdone = ARCMSR_CCB_ABORTED; - arcmsr_ccb_complete(ccb, 1); - } - } - /* enable all outbound interrupt */ - arcmsr_enable_outbound_ints(acb, intmask_org); - } - pci_disable_device(pdev); -} - -static void arcmsr_pci_ers_disconnect_forepart(struct pci_dev *pdev) -{ - struct Scsi_Host *host = pci_get_drvdata(pdev); - struct AdapterControlBlock *acb = \ - (struct AdapterControlBlock *)host->hostdata; - - arcmsr_stop_adapter_bgrb(acb); - arcmsr_flush_adapter_cache(acb); -} - -static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, - pci_channel_state_t state) -{ - switch (state) { - case pci_channel_io_frozen: - arcmsr_pci_ers_need_reset_forepart(pdev); - return PCI_ERS_RESULT_NEED_RESET; - case pci_channel_io_perm_failure: - arcmsr_pci_ers_disconnect_forepart(pdev); - return PCI_ERS_RESULT_DISCONNECT; - break; - default: - return PCI_ERS_RESULT_NEED_RESET; - } -} -#endif -- cgit v1.2.3 From 8a52da632ceb9d8b776494563df579e87b7b586b Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 15 May 2010 11:46:12 +0200 Subject: [SCSI] aacraid: Eliminate use after free The debugging code using the freed structure is moved before the kfree. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @free@ expression E; position p; @@ kfree@p(E) @@ expression free.E, subE<=free.E, E1; position free.p; @@ kfree@p(E) ... ( subE = E1 | * E ) // Signed-off-by: Julia Lawall Signed-off-by: James Bottomley --- drivers/scsi/aacraid/commctrl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 9c0c91178538..1a5bf5724750 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -655,9 +655,9 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) /* Does this really need to be GFP_DMA? */ p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA); if(!p) { - kfree (usg); - dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", + dprintk((KERN_DEBUG "aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", usg->sg[i].count,i,usg->count)); + kfree(usg); rcode = -ENOMEM; goto cleanup; } -- cgit v1.2.3 From f9e8894ae5157796dd69249c56062042d02a431d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 18 Mar 2010 15:39:30 -0400 Subject: [SCSI] fix race in scsi_target_reap This patch (as1357) fixes a race in SCSI target allocation and release. Putting a target in the STARGET_DEL state isn't protected by the host lock, so an old target structure could be reused by a new device even though it's about to be deleted. The cure is to change the state while still holding the host lock. Signed-off-by: Alan Stern Signed-off-by: James Bottomley --- drivers/scsi/scsi_scan.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index c992ecf4e372..a77468cd5a33 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -492,19 +492,20 @@ void scsi_target_reap(struct scsi_target *starget) struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); unsigned long flags; enum scsi_target_state state; - int empty; + int empty = 0; spin_lock_irqsave(shost->host_lock, flags); state = starget->state; - empty = --starget->reap_ref == 0 && - list_empty(&starget->devices) ? 1 : 0; + if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { + empty = 1; + starget->state = STARGET_DEL; + } spin_unlock_irqrestore(shost->host_lock, flags); if (!empty) return; BUG_ON(state == STARGET_DEL); - starget->state = STARGET_DEL; if (state == STARGET_CREATED) scsi_target_destroy(starget); else -- cgit v1.2.3 From 6869b15efccce954a28d14c84b25350d125e2f93 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 17 May 2009 12:17:28 +0200 Subject: m68k/scsi: gvp11 - Kill ugly DMA() macro Acked-by: James Bottomley Signed-off-by: Geert Uytterhoeven --- drivers/scsi/gvp11.c | 52 ++++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 24 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index 18b7102bb80e..777972e6bbf3 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c @@ -22,15 +22,13 @@ #include -#define DMA(ptr) ((gvp11_scsiregs *)((ptr)->base)) - -static irqreturn_t gvp11_intr(int irq, void *_instance) +static irqreturn_t gvp11_intr(int irq, void *data) { + struct Scsi_Host *instance = data; + gvp11_scsiregs *regs = (gvp11_scsiregs *)(instance->base); + unsigned int status = regs->CNTR; unsigned long flags; - unsigned int status; - struct Scsi_Host *instance = (struct Scsi_Host *)_instance; - status = DMA(instance)->CNTR; if (!(status & GVP11_DMAC_INT_PENDING)) return IRQ_NONE; @@ -51,6 +49,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) { struct Scsi_Host *instance = cmd->device->host; struct WD33C93_hostdata *hdata = shost_priv(instance); + gvp11_scsiregs *regs = (gvp11_scsiregs *)(instance->base); unsigned short cntr = GVP11_DMAC_INT_ENABLE; unsigned long addr = virt_to_bus(cmd->SCp.ptr); int bank_mask; @@ -117,10 +116,10 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) cntr |= GVP11_DMAC_DIR_WRITE; hdata->dma_dir = dir_in; - DMA(cmd->device->host)->CNTR = cntr; + regs->CNTR = cntr; /* setup DMA *physical* address */ - DMA(cmd->device->host)->ACR = addr; + regs->ACR = addr; if (dir_in) { /* invalidate any cache */ @@ -132,10 +131,10 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) bank_mask = (~hdata->dma_xfer_mask >> 18) & 0x01c0; if (bank_mask) - DMA(cmd->device->host)->BANK = bank_mask & (addr >> 18); + regs->BANK = bank_mask & (addr >> 18); /* start DMA */ - DMA(cmd->device->host)->ST_DMA = 1; + regs->ST_DMA = 1; /* return success */ return 0; @@ -144,12 +143,13 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, int status) { + gvp11_scsiregs *regs = (gvp11_scsiregs *)(instance->base); struct WD33C93_hostdata *hdata = shost_priv(instance); /* stop DMA */ - DMA(instance)->SP_DMA = 1; + regs->SP_DMA = 1; /* remove write bit from CONTROL bits */ - DMA(instance)->CNTR = GVP11_DMAC_INT_ENABLE; + regs->CNTR = GVP11_DMAC_INT_ENABLE; /* copy from a bounce buffer, if necessary */ if (status && hdata->dma_bounce_buffer) { @@ -178,7 +178,8 @@ int __init gvp11_detect(struct scsi_host_template *tpnt) struct zorro_dev *z = NULL; unsigned int default_dma_xfer_mask; struct WD33C93_hostdata *hdata; - wd33c93_regs regs; + gvp11_scsiregs *regs; + wd33c93_regs wdregs; int num_gvp11 = 0; #ifdef CHECK_WD33C93 volatile unsigned char *sasr_3393, *scmd_3393; @@ -310,33 +311,34 @@ int __init gvp11_detect(struct scsi_host_template *tpnt) else hdata->dma_xfer_mask = default_dma_xfer_mask; - DMA(instance)->secret2 = 1; - DMA(instance)->secret1 = 0; - DMA(instance)->secret3 = 15; - while (DMA(instance)->CNTR & GVP11_DMAC_BUSY) + regs = (gvp11_scsiregs *)(instance->base); + regs->secret2 = 1; + regs->secret1 = 0; + regs->secret3 = 15; + while (regs->CNTR & GVP11_DMAC_BUSY) ; - DMA(instance)->CNTR = 0; + regs->CNTR = 0; - DMA(instance)->BANK = 0; + regs->BANK = 0; epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000); /* * Check for 14MHz SCSI clock */ - regs.SASR = &(DMA(instance)->SASR); - regs.SCMD = &(DMA(instance)->SCMD); + wdregs.SASR = ®s->SASR; + wdregs.SCMD = ®s->SCMD; hdata->no_sync = 0xff; hdata->fast = 0; hdata->dma_mode = CTRL_DMA; - wd33c93_init(instance, regs, dma_setup, dma_stop, + wd33c93_init(instance, wdregs, dma_setup, dma_stop, (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10 : WD33C93_FS_12_15); if (request_irq(IRQ_AMIGA_PORTS, gvp11_intr, IRQF_SHARED, "GVP11 SCSI", instance)) goto unregister; - DMA(instance)->CNTR = GVP11_DMAC_INT_ENABLE; + regs->CNTR = GVP11_DMAC_INT_ENABLE; num_gvp11++; continue; @@ -391,7 +393,9 @@ static struct scsi_host_template driver_template = { int gvp11_release(struct Scsi_Host *instance) { #ifdef MODULE - DMA(instance)->CNTR = 0; + gvp11_scsiregs *regs = (gvp11_scsiregs *)(instance->base); + + regs->CNTR = 0; release_mem_region(ZTWO_PADDR(instance->base), 256); free_irq(IRQ_AMIGA_PORTS, instance); #endif -- cgit v1.2.3 From d753722ee0223f80e6d0a553c68583c6ae57c1b2 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 17 May 2009 12:17:23 +0200 Subject: m68k/scsi: a3000 - Kill ugly DMA() macro Acked-by: James Bottomley Signed-off-by: Geert Uytterhoeven --- drivers/scsi/a3000.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c index bc6eb69f5fd0..ae9b25a3e3e7 100644 --- a/drivers/scsi/a3000.c +++ b/drivers/scsi/a3000.c @@ -22,16 +22,15 @@ #include -#define DMA(ptr) ((a3000_scsiregs *)((ptr)->base)) - static struct Scsi_Host *a3000_host = NULL; static int a3000_release(struct Scsi_Host *instance); static irqreturn_t a3000_intr(int irq, void *dummy) { + a3000_scsiregs *regs = (a3000_scsiregs *)(a3000_host->base); + unsigned int status = regs->ISTR; unsigned long flags; - unsigned int status = DMA(a3000_host)->ISTR; if (!(status & ISTR_INT_P)) return IRQ_NONE; @@ -48,6 +47,7 @@ static irqreturn_t a3000_intr(int irq, void *dummy) static int dma_setup(struct scsi_cmnd *cmd, int dir_in) { struct WD33C93_hostdata *hdata = shost_priv(a3000_host); + a3000_scsiregs *regs = (a3000_scsiregs *)(a3000_host->base); unsigned short cntr = CNTR_PDMD | CNTR_INTEN; unsigned long addr = virt_to_bus(cmd->SCp.ptr); @@ -84,10 +84,10 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) /* remember direction */ hdata->dma_dir = dir_in; - DMA(a3000_host)->CNTR = cntr; + regs->CNTR = cntr; /* setup DMA *physical* address */ - DMA(a3000_host)->ACR = addr; + regs->ACR = addr; if (dir_in) { /* invalidate any cache */ @@ -99,7 +99,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) /* start DMA */ mb(); /* make sure setup is completed */ - DMA(a3000_host)->ST_DMA = 1; + regs->ST_DMA = 1; mb(); /* make sure DMA has started before next IO */ /* return success */ @@ -110,6 +110,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, int status) { struct WD33C93_hostdata *hdata = shost_priv(instance); + a3000_scsiregs *regs = (a3000_scsiregs *)(instance->base); /* disable SCSI interrupts */ unsigned short cntr = CNTR_PDMD; @@ -117,14 +118,14 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, if (!hdata->dma_dir) cntr |= CNTR_DDIR; - DMA(instance)->CNTR = cntr; + regs->CNTR = cntr; mb(); /* make sure CNTR is updated before next IO */ /* flush if we were reading */ if (hdata->dma_dir) { - DMA(instance)->FLUSH = 1; + regs->FLUSH = 1; mb(); /* don't allow prefetch */ - while (!(DMA(instance)->ISTR & ISTR_FE_FLG)) + while (!(regs->ISTR & ISTR_FE_FLG)) barrier(); mb(); /* no IO until FLUSH is done */ } @@ -133,14 +134,14 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, /* I think that this CINT is only necessary if you are * using the terminal count features. HM 7 Mar 1994 */ - DMA(instance)->CINT = 1; + regs->CINT = 1; /* stop DMA */ - DMA(instance)->SP_DMA = 1; + regs->SP_DMA = 1; mb(); /* make sure DMA is stopped before next IO */ /* restore the CONTROL bits (minus the direction flag) */ - DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN; + regs->CNTR = CNTR_PDMD | CNTR_INTEN; mb(); /* make sure CNTR is updated before next IO */ /* copy from a bounce buffer, if necessary */ @@ -163,7 +164,8 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, static int __init a3000_detect(struct scsi_host_template *tpnt) { - wd33c93_regs regs; + wd33c93_regs wdregs; + a3000_scsiregs *regs; struct WD33C93_hostdata *hdata; if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(A3000_SCSI)) @@ -180,18 +182,20 @@ static int __init a3000_detect(struct scsi_host_template *tpnt) a3000_host->base = ZTWO_VADDR(0xDD0000); a3000_host->irq = IRQ_AMIGA_PORTS; - DMA(a3000_host)->DAWR = DAWR_A3000; - regs.SASR = &(DMA(a3000_host)->SASR); - regs.SCMD = &(DMA(a3000_host)->SCMD); + regs = (a3000_scsiregs *)(a3000_host->base); + regs->DAWR = DAWR_A3000; + wdregs.SASR = ®s->SASR; + wdregs.SCMD = ®s->SCMD; hdata = shost_priv(a3000_host); hdata->no_sync = 0xff; hdata->fast = 0; hdata->dma_mode = CTRL_DMA; - wd33c93_init(a3000_host, regs, dma_setup, dma_stop, WD33C93_FS_12_15); + wd33c93_init(a3000_host, wdregs, dma_setup, dma_stop, + WD33C93_FS_12_15); if (request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, "A3000 SCSI", a3000_intr)) goto fail_irq; - DMA(a3000_host)->CNTR = CNTR_PDMD | CNTR_INTEN; + regs->CNTR = CNTR_PDMD | CNTR_INTEN; return 1; @@ -239,7 +243,9 @@ static struct scsi_host_template driver_template = { static int a3000_release(struct Scsi_Host *instance) { - DMA(instance)->CNTR = 0; + a3000_scsiregs *regs = (a3000_scsiregs *)(instance->base); + + regs->CNTR = 0; release_mem_region(0xDD0000, 256); free_irq(IRQ_AMIGA_PORTS, a3000_intr); return 1; -- cgit v1.2.3 From 4616ac7e84c58660a11b991460cf2611552faa76 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 17 May 2009 13:35:13 +0200 Subject: m68k/scsi: mvme147 - Kill static global mvme147_host Acked-by: James Bottomley Signed-off-by: Geert Uytterhoeven --- drivers/scsi/mvme147.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c index 716d1785cda7..1b6195b4717d 100644 --- a/drivers/scsi/mvme147.c +++ b/drivers/scsi/mvme147.c @@ -16,12 +16,12 @@ #include -static struct Scsi_Host *mvme147_host = NULL; - -static irqreturn_t mvme147_intr(int irq, void *dummy) +static irqreturn_t mvme147_intr(int irq, void *data) { + struct Scsi_Host *instance = data; + if (irq == MVME147_IRQ_SCSI_PORT) - wd33c93_intr(mvme147_host); + wd33c93_intr(instance); else m147_pcc->dma_intr = 0x89; /* Ack and enable ints */ return IRQ_HANDLED; @@ -29,7 +29,8 @@ static irqreturn_t mvme147_intr(int irq, void *dummy) static int dma_setup(struct scsi_cmnd *cmd, int dir_in) { - struct WD33C93_hostdata *hdata = shost_priv(mvme147_host); + struct Scsi_Host *instance = cmd->device->host; + struct WD33C93_hostdata *hdata = shost_priv(instance); unsigned char flags = 0x01; unsigned long addr = virt_to_bus(cmd->SCp.ptr); @@ -66,6 +67,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, int mvme147_detect(struct scsi_host_template *tpnt) { static unsigned char called = 0; + struct Scsi_Host *instance; wd33c93_regs regs; struct WD33C93_hostdata *hdata; @@ -76,25 +78,25 @@ int mvme147_detect(struct scsi_host_template *tpnt) tpnt->proc_name = "MVME147"; tpnt->proc_info = &wd33c93_proc_info; - mvme147_host = scsi_register(tpnt, sizeof(struct WD33C93_hostdata)); - if (!mvme147_host) + instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata)); + if (!instance) goto err_out; - mvme147_host->base = 0xfffe4000; - mvme147_host->irq = MVME147_IRQ_SCSI_PORT; + instance->base = 0xfffe4000; + instance->irq = MVME147_IRQ_SCSI_PORT; regs.SASR = (volatile unsigned char *)0xfffe4000; regs.SCMD = (volatile unsigned char *)0xfffe4001; - hdata = shost_priv(mvme147_host); + hdata = shost_priv(instance); hdata->no_sync = 0xff; hdata->fast = 0; hdata->dma_mode = CTRL_DMA; - wd33c93_init(mvme147_host, regs, dma_setup, dma_stop, WD33C93_FS_8_10); + wd33c93_init(instance, regs, dma_setup, dma_stop, WD33C93_FS_8_10); if (request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0, - "MVME147 SCSI PORT", mvme147_intr)) + "MVME147 SCSI PORT", instance)) goto err_unregister; if (request_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr, 0, - "MVME147 SCSI DMA", mvme147_intr)) + "MVME147 SCSI DMA", instance)) goto err_free_irq; #if 0 /* Disabled; causes problems booting */ m147_pcc->scsi_interrupt = 0x10; /* Assert SCSI bus reset */ @@ -113,7 +115,7 @@ int mvme147_detect(struct scsi_host_template *tpnt) err_free_irq: free_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr); err_unregister: - scsi_unregister(mvme147_host); + scsi_unregister(instance); err_out: return 0; } -- cgit v1.2.3 From a8169e6057e9b7dd41c9e3b7a41efebc4bd859c9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 17 May 2009 13:35:07 +0200 Subject: m68k/scsi: a3000 - Kill static global a3000_host Acked-by: James Bottomley Signed-off-by: Geert Uytterhoeven --- drivers/scsi/a3000.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c index ae9b25a3e3e7..eabc41b65dad 100644 --- a/drivers/scsi/a3000.c +++ b/drivers/scsi/a3000.c @@ -22,22 +22,21 @@ #include -static struct Scsi_Host *a3000_host = NULL; - static int a3000_release(struct Scsi_Host *instance); -static irqreturn_t a3000_intr(int irq, void *dummy) +static irqreturn_t a3000_intr(int irq, void *data) { - a3000_scsiregs *regs = (a3000_scsiregs *)(a3000_host->base); + struct Scsi_Host *instance = data; + a3000_scsiregs *regs = (a3000_scsiregs *)(instance->base); unsigned int status = regs->ISTR; unsigned long flags; if (!(status & ISTR_INT_P)) return IRQ_NONE; if (status & ISTR_INTS) { - spin_lock_irqsave(a3000_host->host_lock, flags); - wd33c93_intr(a3000_host); - spin_unlock_irqrestore(a3000_host->host_lock, flags); + spin_lock_irqsave(instance->host_lock, flags); + wd33c93_intr(instance); + spin_unlock_irqrestore(instance->host_lock, flags); return IRQ_HANDLED; } printk("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n", status); @@ -46,8 +45,9 @@ static irqreturn_t a3000_intr(int irq, void *dummy) static int dma_setup(struct scsi_cmnd *cmd, int dir_in) { - struct WD33C93_hostdata *hdata = shost_priv(a3000_host); - a3000_scsiregs *regs = (a3000_scsiregs *)(a3000_host->base); + struct Scsi_Host *instance = cmd->device->host; + struct WD33C93_hostdata *hdata = shost_priv(instance); + a3000_scsiregs *regs = (a3000_scsiregs *)(instance->base); unsigned short cntr = CNTR_PDMD | CNTR_INTEN; unsigned long addr = virt_to_bus(cmd->SCp.ptr); @@ -164,6 +164,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, static int __init a3000_detect(struct scsi_host_template *tpnt) { + struct Scsi_Host *instance; wd33c93_regs wdregs; a3000_scsiregs *regs; struct WD33C93_hostdata *hdata; @@ -176,31 +177,30 @@ static int __init a3000_detect(struct scsi_host_template *tpnt) tpnt->proc_name = "A3000"; tpnt->proc_info = &wd33c93_proc_info; - a3000_host = scsi_register(tpnt, sizeof(struct WD33C93_hostdata)); - if (a3000_host == NULL) + instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata)); + if (instance == NULL) goto fail_register; - a3000_host->base = ZTWO_VADDR(0xDD0000); - a3000_host->irq = IRQ_AMIGA_PORTS; - regs = (a3000_scsiregs *)(a3000_host->base); + instance->base = ZTWO_VADDR(0xDD0000); + instance->irq = IRQ_AMIGA_PORTS; + regs = (a3000_scsiregs *)(instance->base); regs->DAWR = DAWR_A3000; wdregs.SASR = ®s->SASR; wdregs.SCMD = ®s->SCMD; - hdata = shost_priv(a3000_host); + hdata = shost_priv(instance); hdata->no_sync = 0xff; hdata->fast = 0; hdata->dma_mode = CTRL_DMA; - wd33c93_init(a3000_host, wdregs, dma_setup, dma_stop, - WD33C93_FS_12_15); + wd33c93_init(instance, wdregs, dma_setup, dma_stop, WD33C93_FS_12_15); if (request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, "A3000 SCSI", - a3000_intr)) + instance)) goto fail_irq; regs->CNTR = CNTR_PDMD | CNTR_INTEN; return 1; fail_irq: - scsi_unregister(a3000_host); + scsi_unregister(instance); fail_register: release_mem_region(0xDD0000, 256); return 0; -- cgit v1.2.3 From 11ca46eaf207e2fde20f6207b6a3ae7b6295da07 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 17 May 2009 20:44:16 +0200 Subject: m68k/scsi: gvp11 - Extract check_wd33c93() Acked-by: James Bottomley Signed-off-by: Geert Uytterhoeven --- drivers/scsi/gvp11.c | 160 ++++++++++++++++++++++++++------------------------- 1 file changed, 83 insertions(+), 77 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index 777972e6bbf3..59a7bff53e13 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c @@ -22,6 +22,8 @@ #include +#define CHECK_WD33C93 + static irqreturn_t gvp11_intr(int irq, void *data) { struct Scsi_Host *instance = data; @@ -167,7 +169,85 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, } } -#define CHECK_WD33C93 +static int __init check_wd33c93(gvp11_scsiregs *regs) +{ +#ifdef CHECK_WD33C93 + volatile unsigned char *sasr_3393, *scmd_3393; + unsigned char save_sasr; + unsigned char q, qq; + + /* + * These darn GVP boards are a problem - it can be tough to tell + * whether or not they include a SCSI controller. This is the + * ultimate Yet-Another-GVP-Detection-Hack in that it actually + * probes for a WD33c93 chip: If we find one, it's extremely + * likely that this card supports SCSI, regardless of Product_ + * Code, Board_Size, etc. + */ + + /* Get pointers to the presumed register locations and save contents */ + + sasr_3393 = ®s->SASR; + scmd_3393 = ®s->SCMD; + save_sasr = *sasr_3393; + + /* First test the AuxStatus Reg */ + + q = *sasr_3393; /* read it */ + if (q & 0x08) /* bit 3 should always be clear */ + return -ENODEV; + *sasr_3393 = WD_AUXILIARY_STATUS; /* setup indirect address */ + if (*sasr_3393 == WD_AUXILIARY_STATUS) { /* shouldn't retain the write */ + *sasr_3393 = save_sasr; /* Oops - restore this byte */ + return -ENODEV; + } + if (*sasr_3393 != q) { /* should still read the same */ + *sasr_3393 = save_sasr; /* Oops - restore this byte */ + return -ENODEV; + } + if (*scmd_3393 != q) /* and so should the image at 0x1f */ + return -ENODEV; + + /* + * Ok, we probably have a wd33c93, but let's check a few other places + * for good measure. Make sure that this works for both 'A and 'B + * chip versions. + */ + + *sasr_3393 = WD_SCSI_STATUS; + q = *scmd_3393; + *sasr_3393 = WD_SCSI_STATUS; + *scmd_3393 = ~q; + *sasr_3393 = WD_SCSI_STATUS; + qq = *scmd_3393; + *sasr_3393 = WD_SCSI_STATUS; + *scmd_3393 = q; + if (qq != q) /* should be read only */ + return -ENODEV; + *sasr_3393 = 0x1e; /* this register is unimplemented */ + q = *scmd_3393; + *sasr_3393 = 0x1e; + *scmd_3393 = ~q; + *sasr_3393 = 0x1e; + qq = *scmd_3393; + *sasr_3393 = 0x1e; + *scmd_3393 = q; + if (qq != q || qq != 0xff) /* should be read only, all 1's */ + return -ENODEV; + *sasr_3393 = WD_TIMEOUT_PERIOD; + q = *scmd_3393; + *sasr_3393 = WD_TIMEOUT_PERIOD; + *scmd_3393 = ~q; + *sasr_3393 = WD_TIMEOUT_PERIOD; + qq = *scmd_3393; + *sasr_3393 = WD_TIMEOUT_PERIOD; + *scmd_3393 = q; + if (qq != (~q & 0xff)) /* should be read/write */ + return -ENODEV; +#endif /* CHECK_WD33C93 */ + + return 0; +} int __init gvp11_detect(struct scsi_host_template *tpnt) { @@ -181,11 +261,6 @@ int __init gvp11_detect(struct scsi_host_template *tpnt) gvp11_scsiregs *regs; wd33c93_regs wdregs; int num_gvp11 = 0; -#ifdef CHECK_WD33C93 - volatile unsigned char *sasr_3393, *scmd_3393; - unsigned char save_sasr; - unsigned char q, qq; -#endif if (!MACH_IS_AMIGA || called) return 0; @@ -226,77 +301,9 @@ int __init gvp11_detect(struct scsi_host_template *tpnt) if (!request_mem_region(address, 256, "wd33c93")) continue; -#ifdef CHECK_WD33C93 - - /* - * These darn GVP boards are a problem - it can be tough to tell - * whether or not they include a SCSI controller. This is the - * ultimate Yet-Another-GVP-Detection-Hack in that it actually - * probes for a WD33c93 chip: If we find one, it's extremely - * likely that this card supports SCSI, regardless of Product_ - * Code, Board_Size, etc. - */ - - /* Get pointers to the presumed register locations and save contents */ - - sasr_3393 = &(((gvp11_scsiregs *)(ZTWO_VADDR(address)))->SASR); - scmd_3393 = &(((gvp11_scsiregs *)(ZTWO_VADDR(address)))->SCMD); - save_sasr = *sasr_3393; - - /* First test the AuxStatus Reg */ - - q = *sasr_3393; /* read it */ - if (q & 0x08) /* bit 3 should always be clear */ - goto release; - *sasr_3393 = WD_AUXILIARY_STATUS; /* setup indirect address */ - if (*sasr_3393 == WD_AUXILIARY_STATUS) { /* shouldn't retain the write */ - *sasr_3393 = save_sasr; /* Oops - restore this byte */ - goto release; - } - if (*sasr_3393 != q) { /* should still read the same */ - *sasr_3393 = save_sasr; /* Oops - restore this byte */ - goto release; - } - if (*scmd_3393 != q) /* and so should the image at 0x1f */ - goto release; - - /* - * Ok, we probably have a wd33c93, but let's check a few other places - * for good measure. Make sure that this works for both 'A and 'B - * chip versions. - */ - - *sasr_3393 = WD_SCSI_STATUS; - q = *scmd_3393; - *sasr_3393 = WD_SCSI_STATUS; - *scmd_3393 = ~q; - *sasr_3393 = WD_SCSI_STATUS; - qq = *scmd_3393; - *sasr_3393 = WD_SCSI_STATUS; - *scmd_3393 = q; - if (qq != q) /* should be read only */ - goto release; - *sasr_3393 = 0x1e; /* this register is unimplemented */ - q = *scmd_3393; - *sasr_3393 = 0x1e; - *scmd_3393 = ~q; - *sasr_3393 = 0x1e; - qq = *scmd_3393; - *sasr_3393 = 0x1e; - *scmd_3393 = q; - if (qq != q || qq != 0xff) /* should be read only, all 1's */ + regs = (gvp11_scsiregs *)(ZTWO_VADDR(address)); + if (check_wd33c93(regs)) goto release; - *sasr_3393 = WD_TIMEOUT_PERIOD; - q = *scmd_3393; - *sasr_3393 = WD_TIMEOUT_PERIOD; - *scmd_3393 = ~q; - *sasr_3393 = WD_TIMEOUT_PERIOD; - qq = *scmd_3393; - *sasr_3393 = WD_TIMEOUT_PERIOD; - *scmd_3393 = q; - if (qq != (~q & 0xff)) /* should be read/write */ - goto release; -#endif instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata)); if (instance == NULL) @@ -311,7 +318,6 @@ int __init gvp11_detect(struct scsi_host_template *tpnt) else hdata->dma_xfer_mask = default_dma_xfer_mask; - regs = (gvp11_scsiregs *)(instance->base); regs->secret2 = 1; regs->secret1 = 0; regs->secret3 = 15; -- cgit v1.2.3 From 56522e39ab75ea7f1f4f5fe4cb760f00815f3d81 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 17 May 2009 21:05:54 +0200 Subject: m68k/scsi: a2091 - Kill a2091_scsiregs typedef Acked-by: James Bottomley Signed-off-by: Geert Uytterhoeven --- drivers/scsi/a2091.c | 12 ++++++------ drivers/scsi/a2091.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c index 308541ff85cf..09b3d77db03f 100644 --- a/drivers/scsi/a2091.c +++ b/drivers/scsi/a2091.c @@ -27,7 +27,7 @@ static int a2091_release(struct Scsi_Host *instance); static irqreturn_t a2091_intr(int irq, void *data) { struct Scsi_Host *instance = data; - a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base); + struct a2091_scsiregs *regs = (struct a2091_scsiregs *)(instance->base); unsigned int status = regs->ISTR; unsigned long flags; @@ -44,7 +44,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) { struct Scsi_Host *instance = cmd->device->host; struct WD33C93_hostdata *hdata = shost_priv(instance); - a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base); + struct a2091_scsiregs *regs = (struct a2091_scsiregs *)(instance->base); unsigned short cntr = CNTR_PDMD | CNTR_INTEN; unsigned long addr = virt_to_bus(cmd->SCp.ptr); @@ -109,7 +109,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, int status) { struct WD33C93_hostdata *hdata = shost_priv(instance); - a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base); + struct a2091_scsiregs *regs = (struct a2091_scsiregs *)(instance->base); /* disable SCSI interrupts */ unsigned short cntr = CNTR_PDMD; @@ -154,7 +154,7 @@ static int __init a2091_detect(struct scsi_host_template *tpnt) unsigned long address; struct zorro_dev *z = NULL; wd33c93_regs wdregs; - a2091_scsiregs *regs; + struct a2091_scsiregs *regs; struct WD33C93_hostdata *hdata; int num_a2091 = 0; @@ -179,7 +179,7 @@ static int __init a2091_detect(struct scsi_host_template *tpnt) instance->base = ZTWO_VADDR(address); instance->irq = IRQ_AMIGA_PORTS; instance->unique_id = z->slotaddr; - regs = (a2091_scsiregs *)(instance->base); + regs = (struct a2091_scsiregs *)(instance->base); regs->DAWR = DAWR_A2091; wdregs.SASR = ®s->SASR; wdregs.SCMD = ®s->SCMD; @@ -243,7 +243,7 @@ static struct scsi_host_template driver_template = { static int a2091_release(struct Scsi_Host *instance) { #ifdef MODULE - a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base); + struct a2091_scsiregs *regs = (struct a2091_scsiregs *)(instance->base); regs->CNTR = 0; release_mem_region(ZTWO_PADDR(instance->base), 256); diff --git a/drivers/scsi/a2091.h b/drivers/scsi/a2091.h index 1c3daa1fd754..794b8e65c711 100644 --- a/drivers/scsi/a2091.h +++ b/drivers/scsi/a2091.h @@ -25,7 +25,7 @@ */ #define A2091_XFER_MASK (0xff000001) -typedef struct { +struct a2091_scsiregs { unsigned char pad1[64]; volatile unsigned short ISTR; volatile unsigned short CNTR; @@ -44,7 +44,7 @@ typedef struct { volatile unsigned short CINT; unsigned char pad7[2]; volatile unsigned short FLUSH; -} a2091_scsiregs; +}; #define DAWR_A2091 (3) -- cgit v1.2.3 From 349d65fdc8e5bb3335fa5e6984ca2c12154a8269 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 17 May 2009 21:05:55 +0200 Subject: m68k/scsi: gvp11 - Kill gvp11_scsiregs typedef Acked-by: James Bottomley Signed-off-by: Geert Uytterhoeven --- drivers/scsi/gvp11.c | 14 +++++++------- drivers/scsi/gvp11.h | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index 59a7bff53e13..874cbee1be23 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c @@ -27,7 +27,7 @@ static irqreturn_t gvp11_intr(int irq, void *data) { struct Scsi_Host *instance = data; - gvp11_scsiregs *regs = (gvp11_scsiregs *)(instance->base); + struct gvp11_scsiregs *regs = (struct gvp11_scsiregs *)(instance->base); unsigned int status = regs->CNTR; unsigned long flags; @@ -51,7 +51,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) { struct Scsi_Host *instance = cmd->device->host; struct WD33C93_hostdata *hdata = shost_priv(instance); - gvp11_scsiregs *regs = (gvp11_scsiregs *)(instance->base); + struct gvp11_scsiregs *regs = (struct gvp11_scsiregs *)(instance->base); unsigned short cntr = GVP11_DMAC_INT_ENABLE; unsigned long addr = virt_to_bus(cmd->SCp.ptr); int bank_mask; @@ -145,7 +145,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, int status) { - gvp11_scsiregs *regs = (gvp11_scsiregs *)(instance->base); + struct gvp11_scsiregs *regs = (struct gvp11_scsiregs *)(instance->base); struct WD33C93_hostdata *hdata = shost_priv(instance); /* stop DMA */ @@ -169,7 +169,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, } } -static int __init check_wd33c93(gvp11_scsiregs *regs) +static int __init check_wd33c93(struct gvp11_scsiregs *regs) { #ifdef CHECK_WD33C93 volatile unsigned char *sasr_3393, *scmd_3393; @@ -258,7 +258,7 @@ int __init gvp11_detect(struct scsi_host_template *tpnt) struct zorro_dev *z = NULL; unsigned int default_dma_xfer_mask; struct WD33C93_hostdata *hdata; - gvp11_scsiregs *regs; + struct gvp11_scsiregs *regs; wd33c93_regs wdregs; int num_gvp11 = 0; @@ -301,7 +301,7 @@ int __init gvp11_detect(struct scsi_host_template *tpnt) if (!request_mem_region(address, 256, "wd33c93")) continue; - regs = (gvp11_scsiregs *)(ZTWO_VADDR(address)); + regs = (struct gvp11_scsiregs *)(ZTWO_VADDR(address)); if (check_wd33c93(regs)) goto release; @@ -399,7 +399,7 @@ static struct scsi_host_template driver_template = { int gvp11_release(struct Scsi_Host *instance) { #ifdef MODULE - gvp11_scsiregs *regs = (gvp11_scsiregs *)(instance->base); + struct gvp11_scsiregs *regs = (struct gvp11_scsiregs *)(instance->base); regs->CNTR = 0; release_mem_region(ZTWO_PADDR(instance->base), 256); diff --git a/drivers/scsi/gvp11.h b/drivers/scsi/gvp11.h index e2efdf9601ef..b27a3ee3313e 100644 --- a/drivers/scsi/gvp11.h +++ b/drivers/scsi/gvp11.h @@ -30,7 +30,7 @@ int gvp11_release(struct Scsi_Host *); */ #define GVP11_XFER_MASK (0xff000001) -typedef struct { +struct gvp11_scsiregs { unsigned char pad1[64]; volatile unsigned short CNTR; unsigned char pad2[31]; @@ -46,7 +46,7 @@ typedef struct { volatile unsigned short SP_DMA; volatile unsigned short secret2; /* store 1 here */ volatile unsigned short secret3; /* store 15 here */ -} gvp11_scsiregs; +}; /* bits in CNTR */ #define GVP11_DMAC_BUSY (1<<0) -- cgit v1.2.3 From c57c1cab789e4d54fd767fb844e3a309c754e6ed Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 17 May 2009 21:05:53 +0200 Subject: m68k/scsi: a3000 - Kill a3000_scsiregs typedef Acked-by: James Bottomley Signed-off-by: Geert Uytterhoeven --- drivers/scsi/a3000.c | 12 ++++++------ drivers/scsi/a3000.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c index eabc41b65dad..79a4a3c97474 100644 --- a/drivers/scsi/a3000.c +++ b/drivers/scsi/a3000.c @@ -27,7 +27,7 @@ static int a3000_release(struct Scsi_Host *instance); static irqreturn_t a3000_intr(int irq, void *data) { struct Scsi_Host *instance = data; - a3000_scsiregs *regs = (a3000_scsiregs *)(instance->base); + struct a3000_scsiregs *regs = (struct a3000_scsiregs *)(instance->base); unsigned int status = regs->ISTR; unsigned long flags; @@ -47,7 +47,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) { struct Scsi_Host *instance = cmd->device->host; struct WD33C93_hostdata *hdata = shost_priv(instance); - a3000_scsiregs *regs = (a3000_scsiregs *)(instance->base); + struct a3000_scsiregs *regs = (struct a3000_scsiregs *)(instance->base); unsigned short cntr = CNTR_PDMD | CNTR_INTEN; unsigned long addr = virt_to_bus(cmd->SCp.ptr); @@ -110,7 +110,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, int status) { struct WD33C93_hostdata *hdata = shost_priv(instance); - a3000_scsiregs *regs = (a3000_scsiregs *)(instance->base); + struct a3000_scsiregs *regs = (struct a3000_scsiregs *)(instance->base); /* disable SCSI interrupts */ unsigned short cntr = CNTR_PDMD; @@ -166,7 +166,7 @@ static int __init a3000_detect(struct scsi_host_template *tpnt) { struct Scsi_Host *instance; wd33c93_regs wdregs; - a3000_scsiregs *regs; + struct a3000_scsiregs *regs; struct WD33C93_hostdata *hdata; if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(A3000_SCSI)) @@ -183,7 +183,7 @@ static int __init a3000_detect(struct scsi_host_template *tpnt) instance->base = ZTWO_VADDR(0xDD0000); instance->irq = IRQ_AMIGA_PORTS; - regs = (a3000_scsiregs *)(instance->base); + regs = (struct a3000_scsiregs *)(instance->base); regs->DAWR = DAWR_A3000; wdregs.SASR = ®s->SASR; wdregs.SCMD = ®s->SCMD; @@ -243,7 +243,7 @@ static struct scsi_host_template driver_template = { static int a3000_release(struct Scsi_Host *instance) { - a3000_scsiregs *regs = (a3000_scsiregs *)(instance->base); + struct a3000_scsiregs *regs = (struct a3000_scsiregs *)(instance->base); regs->CNTR = 0; release_mem_region(0xDD0000, 256); diff --git a/drivers/scsi/a3000.h b/drivers/scsi/a3000.h index 684813ee378c..49db4a335aab 100644 --- a/drivers/scsi/a3000.h +++ b/drivers/scsi/a3000.h @@ -25,7 +25,7 @@ */ #define A3000_XFER_MASK (0x00000003) -typedef struct { +struct a3000_scsiregs { unsigned char pad1[2]; volatile unsigned short DAWR; volatile unsigned int WTC; @@ -46,7 +46,7 @@ typedef struct { volatile unsigned char SASR; unsigned char pad9; volatile unsigned char SCMD; -} a3000_scsiregs; +}; #define DAWR_A3000 (3) -- cgit v1.2.3 From 5d3f2c38603289fdaa60644ceb93307f0abc77de Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 18 Nov 2008 21:25:15 +0100 Subject: m68k/scsi: mvme147 - Kill obsolete HOSTS_C logic Kill the obsolete HOSTS_C define and the related double inclusion of mvme147.h Acked-by: James Bottomley Signed-off-by: Geert Uytterhoeven --- drivers/scsi/mvme147.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c index 1b6195b4717d..c29d0dbb9660 100644 --- a/drivers/scsi/mvme147.c +++ b/drivers/scsi/mvme147.c @@ -134,9 +134,6 @@ static int mvme147_bus_reset(struct scsi_cmnd *cmd) return SUCCESS; } -#define HOSTS_C - -#include "mvme147.h" static struct scsi_host_template driver_template = { .proc_name = "MVME147", -- cgit v1.2.3 From c737e22cde37e4e2ad126316e4aab7349a491ab3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 16 Aug 2009 11:17:35 +0200 Subject: m68k: amiga - A2091/A590 SCSI zorro_driver conversion Acked-by: James Bottomley Signed-off-by: Geert Uytterhoeven --- drivers/scsi/a2091.c | 186 ++++++++++++++++++++++++++++----------------------- 1 file changed, 102 insertions(+), 84 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c index 09b3d77db03f..fc4fce99528e 100644 --- a/drivers/scsi/a2091.c +++ b/drivers/scsi/a2091.c @@ -1,28 +1,20 @@ #include -#include -#include -#include #include #include +#include +#include +#include +#include -#include #include #include #include #include -#include -#include -#include #include "scsi.h" -#include #include "wd33c93.h" #include "a2091.h" -#include - - -static int a2091_release(struct Scsi_Host *instance); static irqreturn_t a2091_intr(int irq, void *data) { @@ -147,85 +139,27 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, } } -static int __init a2091_detect(struct scsi_host_template *tpnt) -{ - static unsigned char called = 0; - struct Scsi_Host *instance; - unsigned long address; - struct zorro_dev *z = NULL; - wd33c93_regs wdregs; - struct a2091_scsiregs *regs; - struct WD33C93_hostdata *hdata; - int num_a2091 = 0; - - if (!MACH_IS_AMIGA || called) - return 0; - called = 1; - - tpnt->proc_name = "A2091"; - tpnt->proc_info = &wd33c93_proc_info; - - while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { - if (z->id != ZORRO_PROD_CBM_A590_A2091_1 && - z->id != ZORRO_PROD_CBM_A590_A2091_2) - continue; - address = z->resource.start; - if (!request_mem_region(address, 256, "wd33c93")) - continue; - - instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata)); - if (instance == NULL) - goto release; - instance->base = ZTWO_VADDR(address); - instance->irq = IRQ_AMIGA_PORTS; - instance->unique_id = z->slotaddr; - regs = (struct a2091_scsiregs *)(instance->base); - regs->DAWR = DAWR_A2091; - wdregs.SASR = ®s->SASR; - wdregs.SCMD = ®s->SCMD; - hdata = shost_priv(instance); - hdata->no_sync = 0xff; - hdata->fast = 0; - hdata->dma_mode = CTRL_DMA; - wd33c93_init(instance, wdregs, dma_setup, dma_stop, - WD33C93_FS_8_10); - if (request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED, - "A2091 SCSI", instance)) - goto unregister; - regs->CNTR = CNTR_PDMD | CNTR_INTEN; - num_a2091++; - continue; - -unregister: - scsi_unregister(instance); -release: - release_mem_region(address, 256); - } - - return num_a2091; -} - static int a2091_bus_reset(struct scsi_cmnd *cmd) { + struct Scsi_Host *instance = cmd->device->host; + /* FIXME perform bus-specific reset */ /* FIXME 2: kill this function, and let midlayer fall back to the same action, calling wd33c93_host_reset() */ - spin_lock_irq(cmd->device->host->host_lock); + spin_lock_irq(instance->host_lock); wd33c93_host_reset(cmd); - spin_unlock_irq(cmd->device->host->host_lock); + spin_unlock_irq(instance->host_lock); return SUCCESS; } -#define HOSTS_C - -static struct scsi_host_template driver_template = { - .proc_name = "A2901", +static struct scsi_host_template a2091_scsi_template = { + .module = THIS_MODULE, .name = "Commodore A2091/A590 SCSI", - .detect = a2091_detect, - .release = a2091_release, + .proc_info = wd33c93_proc_info, + .proc_name = "A2901", .queuecommand = wd33c93_queuecommand, .eh_abort_handler = wd33c93_abort, .eh_bus_reset_handler = a2091_bus_reset, @@ -237,19 +171,103 @@ static struct scsi_host_template driver_template = { .use_clustering = DISABLE_CLUSTERING }; +static int __devinit a2091_probe(struct zorro_dev *z, + const struct zorro_device_id *ent) +{ + struct Scsi_Host *instance; + int error; + struct a2091_scsiregs *regs; + wd33c93_regs wdregs; + struct WD33C93_hostdata *hdata; + + if (!request_mem_region(z->resource.start, 256, "wd33c93")) + return -EBUSY; + + instance = scsi_host_alloc(&a2091_scsi_template, + sizeof(struct WD33C93_hostdata)); + if (!instance) { + error = -ENOMEM; + goto fail_alloc; + } + + instance->base = ZTWO_VADDR(z->resource.start); + instance->irq = IRQ_AMIGA_PORTS; + instance->unique_id = z->slotaddr; + + regs = (struct a2091_scsiregs *)(instance->base); + regs->DAWR = DAWR_A2091; + + wdregs.SASR = ®s->SASR; + wdregs.SCMD = ®s->SCMD; -#include "scsi_module.c" + hdata = shost_priv(instance); + hdata->no_sync = 0xff; + hdata->fast = 0; + hdata->dma_mode = CTRL_DMA; + + wd33c93_init(instance, wdregs, dma_setup, dma_stop, WD33C93_FS_8_10); + error = request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED, + "A2091 SCSI", instance); + if (error) + goto fail_irq; + + regs->CNTR = CNTR_PDMD | CNTR_INTEN; + + error = scsi_add_host(instance, NULL); + if (error) + goto fail_host; + + zorro_set_drvdata(z, instance); + + scsi_scan_host(instance); + return 0; -static int a2091_release(struct Scsi_Host *instance) +fail_host: + free_irq(IRQ_AMIGA_PORTS, instance); +fail_irq: + scsi_host_put(instance); +fail_alloc: + release_mem_region(z->resource.start, 256); + return error; +} + +static void __devexit a2091_remove(struct zorro_dev *z) { -#ifdef MODULE + struct Scsi_Host *instance = zorro_get_drvdata(z); struct a2091_scsiregs *regs = (struct a2091_scsiregs *)(instance->base); regs->CNTR = 0; - release_mem_region(ZTWO_PADDR(instance->base), 256); + scsi_remove_host(instance); free_irq(IRQ_AMIGA_PORTS, instance); -#endif - return 1; + scsi_host_put(instance); + release_mem_region(z->resource.start, 256); +} + +static struct zorro_device_id a2091_zorro_tbl[] __devinitdata = { + { ZORRO_PROD_CBM_A590_A2091_1 }, + { ZORRO_PROD_CBM_A590_A2091_2 }, + { 0 } +}; +MODULE_DEVICE_TABLE(zorro, a2091_zorro_tbl); + +static struct zorro_driver a2091_driver = { + .name = "a2091", + .id_table = a2091_zorro_tbl, + .probe = a2091_probe, + .remove = __devexit_p(a2091_remove), +}; + +static int __init a2091_init(void) +{ + return zorro_register_driver(&a2091_driver); +} +module_init(a2091_init); + +static void __exit a2091_exit(void) +{ + zorro_unregister_driver(&a2091_driver); } +module_exit(a2091_exit); +MODULE_DESCRIPTION("Commodore A2091/A590 SCSI"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 65c2784a24d8d0a67ba3a50029846e0b82bdc223 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 12 Apr 2010 21:55:03 +0200 Subject: m68k/scsi: a2091 - Do not use legacy Scsi_Host.base Acked-by: James Bottomley Signed-off-by: Geert Uytterhoeven --- drivers/scsi/a2091.c | 75 ++++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 34 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c index fc4fce99528e..1bb5d3f0e260 100644 --- a/drivers/scsi/a2091.c +++ b/drivers/scsi/a2091.c @@ -16,11 +16,16 @@ #include "a2091.h" +struct a2091_hostdata { + struct WD33C93_hostdata wh; + struct a2091_scsiregs *regs; +}; + static irqreturn_t a2091_intr(int irq, void *data) { struct Scsi_Host *instance = data; - struct a2091_scsiregs *regs = (struct a2091_scsiregs *)(instance->base); - unsigned int status = regs->ISTR; + struct a2091_hostdata *hdata = shost_priv(instance); + unsigned int status = hdata->regs->ISTR; unsigned long flags; if (!(status & (ISTR_INT_F | ISTR_INT_P)) || !(status & ISTR_INTS)) @@ -35,38 +40,39 @@ static irqreturn_t a2091_intr(int irq, void *data) static int dma_setup(struct scsi_cmnd *cmd, int dir_in) { struct Scsi_Host *instance = cmd->device->host; - struct WD33C93_hostdata *hdata = shost_priv(instance); - struct a2091_scsiregs *regs = (struct a2091_scsiregs *)(instance->base); + struct a2091_hostdata *hdata = shost_priv(instance); + struct WD33C93_hostdata *wh = &hdata->wh; + struct a2091_scsiregs *regs = hdata->regs; unsigned short cntr = CNTR_PDMD | CNTR_INTEN; unsigned long addr = virt_to_bus(cmd->SCp.ptr); /* don't allow DMA if the physical address is bad */ if (addr & A2091_XFER_MASK) { - hdata->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; - hdata->dma_bounce_buffer = kmalloc(hdata->dma_bounce_len, - GFP_KERNEL); + wh->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; + wh->dma_bounce_buffer = kmalloc(wh->dma_bounce_len, + GFP_KERNEL); /* can't allocate memory; use PIO */ - if (!hdata->dma_bounce_buffer) { - hdata->dma_bounce_len = 0; + if (!wh->dma_bounce_buffer) { + wh->dma_bounce_len = 0; return 1; } /* get the physical address of the bounce buffer */ - addr = virt_to_bus(hdata->dma_bounce_buffer); + addr = virt_to_bus(wh->dma_bounce_buffer); /* the bounce buffer may not be in the first 16M of physmem */ if (addr & A2091_XFER_MASK) { /* we could use chipmem... maybe later */ - kfree(hdata->dma_bounce_buffer); - hdata->dma_bounce_buffer = NULL; - hdata->dma_bounce_len = 0; + kfree(wh->dma_bounce_buffer); + wh->dma_bounce_buffer = NULL; + wh->dma_bounce_len = 0; return 1; } if (!dir_in) { /* copy to bounce buffer for a write */ - memcpy(hdata->dma_bounce_buffer, cmd->SCp.ptr, + memcpy(wh->dma_bounce_buffer, cmd->SCp.ptr, cmd->SCp.this_residual); } } @@ -76,7 +82,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) cntr |= CNTR_DDIR; /* remember direction */ - hdata->dma_dir = dir_in; + wh->dma_dir = dir_in; regs->CNTR = cntr; @@ -100,20 +106,21 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, int status) { - struct WD33C93_hostdata *hdata = shost_priv(instance); - struct a2091_scsiregs *regs = (struct a2091_scsiregs *)(instance->base); + struct a2091_hostdata *hdata = shost_priv(instance); + struct WD33C93_hostdata *wh = &hdata->wh; + struct a2091_scsiregs *regs = hdata->regs; /* disable SCSI interrupts */ unsigned short cntr = CNTR_PDMD; - if (!hdata->dma_dir) + if (!wh->dma_dir) cntr |= CNTR_DDIR; /* disable SCSI interrupts */ regs->CNTR = cntr; /* flush if we were reading */ - if (hdata->dma_dir) { + if (wh->dma_dir) { regs->FLUSH = 1; while (!(regs->ISTR & ISTR_FE_FLG)) ; @@ -129,13 +136,13 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, regs->CNTR = CNTR_PDMD | CNTR_INTEN; /* copy from a bounce buffer, if necessary */ - if (status && hdata->dma_bounce_buffer) { - if (hdata->dma_dir) - memcpy(SCpnt->SCp.ptr, hdata->dma_bounce_buffer, + if (status && wh->dma_bounce_buffer) { + if (wh->dma_dir) + memcpy(SCpnt->SCp.ptr, wh->dma_bounce_buffer, SCpnt->SCp.this_residual); - kfree(hdata->dma_bounce_buffer); - hdata->dma_bounce_buffer = NULL; - hdata->dma_bounce_len = 0; + kfree(wh->dma_bounce_buffer); + wh->dma_bounce_buffer = NULL; + wh->dma_bounce_len = 0; } } @@ -178,32 +185,32 @@ static int __devinit a2091_probe(struct zorro_dev *z, int error; struct a2091_scsiregs *regs; wd33c93_regs wdregs; - struct WD33C93_hostdata *hdata; + struct a2091_hostdata *hdata; if (!request_mem_region(z->resource.start, 256, "wd33c93")) return -EBUSY; instance = scsi_host_alloc(&a2091_scsi_template, - sizeof(struct WD33C93_hostdata)); + sizeof(struct a2091_hostdata)); if (!instance) { error = -ENOMEM; goto fail_alloc; } - instance->base = ZTWO_VADDR(z->resource.start); instance->irq = IRQ_AMIGA_PORTS; instance->unique_id = z->slotaddr; - regs = (struct a2091_scsiregs *)(instance->base); + regs = (struct a2091_scsiregs *)ZTWO_VADDR(z->resource.start); regs->DAWR = DAWR_A2091; wdregs.SASR = ®s->SASR; wdregs.SCMD = ®s->SCMD; hdata = shost_priv(instance); - hdata->no_sync = 0xff; - hdata->fast = 0; - hdata->dma_mode = CTRL_DMA; + hdata->wh.no_sync = 0xff; + hdata->wh.fast = 0; + hdata->wh.dma_mode = CTRL_DMA; + hdata->regs = regs; wd33c93_init(instance, wdregs, dma_setup, dma_stop, WD33C93_FS_8_10); error = request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED, @@ -234,9 +241,9 @@ fail_alloc: static void __devexit a2091_remove(struct zorro_dev *z) { struct Scsi_Host *instance = zorro_get_drvdata(z); - struct a2091_scsiregs *regs = (struct a2091_scsiregs *)(instance->base); + struct a2091_hostdata *hdata = shost_priv(instance); - regs->CNTR = 0; + hdata->regs->CNTR = 0; scsi_remove_host(instance); free_irq(IRQ_AMIGA_PORTS, instance); scsi_host_put(instance); -- cgit v1.2.3 From c1d288a58936cd0654844d807e53a203f4838fb4 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 16 Aug 2009 11:17:35 +0200 Subject: m68k: amiga - GVP Series II SCSI zorro_driver conversion Acked-by: James Bottomley Signed-off-by: Geert Uytterhoeven --- drivers/scsi/gvp11.c | 298 +++++++++++++++++++++++++++------------------------ drivers/scsi/gvp11.h | 7 -- 2 files changed, 156 insertions(+), 149 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index 874cbee1be23..4507a16ee1c6 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c @@ -1,26 +1,20 @@ #include -#include -#include -#include #include #include +#include +#include +#include +#include -#include #include #include #include #include -#include -#include -#include #include "scsi.h" -#include #include "wd33c93.h" #include "gvp11.h" -#include - #define CHECK_WD33C93 @@ -169,7 +163,40 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, } } -static int __init check_wd33c93(struct gvp11_scsiregs *regs) +static int gvp11_bus_reset(struct scsi_cmnd *cmd) +{ + struct Scsi_Host *instance = cmd->device->host; + + /* FIXME perform bus-specific reset */ + + /* FIXME 2: shouldn't we no-op this function (return + FAILED), and fall back to host reset function, + wd33c93_host_reset ? */ + + spin_lock_irq(instance->host_lock); + wd33c93_host_reset(cmd); + spin_unlock_irq(instance->host_lock); + + return SUCCESS; +} + +static struct scsi_host_template gvp11_scsi_template = { + .module = THIS_MODULE, + .name = "GVP Series II SCSI", + .proc_info = wd33c93_proc_info, + .proc_name = "GVP11", + .queuecommand = wd33c93_queuecommand, + .eh_abort_handler = wd33c93_abort, + .eh_bus_reset_handler = gvp11_bus_reset, + .eh_host_reset_handler = wd33c93_host_reset, + .can_queue = CAN_QUEUE, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = CMD_PER_LUN, + .use_clustering = DISABLE_CLUSTERING +}; + +static int __devinit check_wd33c93(struct gvp11_scsiregs *regs) { #ifdef CHECK_WD33C93 volatile unsigned char *sasr_3393, *scmd_3393; @@ -249,163 +276,150 @@ static int __init check_wd33c93(struct gvp11_scsiregs *regs) return 0; } -int __init gvp11_detect(struct scsi_host_template *tpnt) +static int __devinit gvp11_probe(struct zorro_dev *z, + const struct zorro_device_id *ent) { - static unsigned char called = 0; struct Scsi_Host *instance; unsigned long address; + int error; unsigned int epc; - struct zorro_dev *z = NULL; unsigned int default_dma_xfer_mask; struct WD33C93_hostdata *hdata; struct gvp11_scsiregs *regs; wd33c93_regs wdregs; - int num_gvp11 = 0; - - if (!MACH_IS_AMIGA || called) - return 0; - called = 1; - - tpnt->proc_name = "GVP11"; - tpnt->proc_info = &wd33c93_proc_info; - - while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { - /* - * This should (hopefully) be the correct way to identify - * all the different GVP SCSI controllers (except for the - * SERIES I though). - */ - - if (z->id == ZORRO_PROD_GVP_COMBO_030_R3_SCSI || - z->id == ZORRO_PROD_GVP_SERIES_II) - default_dma_xfer_mask = ~0x00ffffff; - else if (z->id == ZORRO_PROD_GVP_GFORCE_030_SCSI || - z->id == ZORRO_PROD_GVP_A530_SCSI || - z->id == ZORRO_PROD_GVP_COMBO_030_R4_SCSI) - default_dma_xfer_mask = ~0x01ffffff; - else if (z->id == ZORRO_PROD_GVP_A1291 || - z->id == ZORRO_PROD_GVP_GFORCE_040_SCSI_1) - default_dma_xfer_mask = ~0x07ffffff; - else - continue; - - /* - * Rumors state that some GVP ram boards use the same product - * code as the SCSI controllers. Therefore if the board-size - * is not 64KB we asume it is a ram board and bail out. - */ - if (z->resource.end - z->resource.start != 0xffff) - continue; - - address = z->resource.start; - if (!request_mem_region(address, 256, "wd33c93")) - continue; - - regs = (struct gvp11_scsiregs *)(ZTWO_VADDR(address)); - if (check_wd33c93(regs)) - goto release; - - instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata)); - if (instance == NULL) - goto release; - instance->base = ZTWO_VADDR(address); - instance->irq = IRQ_AMIGA_PORTS; - instance->unique_id = z->slotaddr; - - hdata = shost_priv(instance); - if (gvp11_xfer_mask) - hdata->dma_xfer_mask = gvp11_xfer_mask; - else - hdata->dma_xfer_mask = default_dma_xfer_mask; - - regs->secret2 = 1; - regs->secret1 = 0; - regs->secret3 = 15; - while (regs->CNTR & GVP11_DMAC_BUSY) - ; - regs->CNTR = 0; - - regs->BANK = 0; - - epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000); - - /* - * Check for 14MHz SCSI clock - */ - wdregs.SASR = ®s->SASR; - wdregs.SCMD = ®s->SCMD; - hdata->no_sync = 0xff; - hdata->fast = 0; - hdata->dma_mode = CTRL_DMA; - wd33c93_init(instance, wdregs, dma_setup, dma_stop, - (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10 - : WD33C93_FS_12_15); - - if (request_irq(IRQ_AMIGA_PORTS, gvp11_intr, IRQF_SHARED, - "GVP11 SCSI", instance)) - goto unregister; - regs->CNTR = GVP11_DMAC_INT_ENABLE; - num_gvp11++; - continue; - -unregister: - scsi_unregister(instance); -release: - release_mem_region(address, 256); + + default_dma_xfer_mask = ent->driver_data; + + /* + * Rumors state that some GVP ram boards use the same product + * code as the SCSI controllers. Therefore if the board-size + * is not 64KB we asume it is a ram board and bail out. + */ + if (zorro_resource_len(z) != 0x10000) + return -ENODEV; + + address = z->resource.start; + if (!request_mem_region(address, 256, "wd33c93")) + return -EBUSY; + + regs = (struct gvp11_scsiregs *)(ZTWO_VADDR(address)); + + error = check_wd33c93(regs); + if (error) + goto fail_check_or_alloc; + + instance = scsi_host_alloc(&gvp11_scsi_template, + sizeof(struct WD33C93_hostdata)); + if (!instance) { + error = -ENOMEM; + goto fail_check_or_alloc; } - return num_gvp11; -} + instance->base = (unsigned long)regs; + instance->irq = IRQ_AMIGA_PORTS; + instance->unique_id = z->slotaddr; -static int gvp11_bus_reset(struct scsi_cmnd *cmd) -{ - /* FIXME perform bus-specific reset */ + regs->secret2 = 1; + regs->secret1 = 0; + regs->secret3 = 15; + while (regs->CNTR & GVP11_DMAC_BUSY) + ; + regs->CNTR = 0; + regs->BANK = 0; - /* FIXME 2: shouldn't we no-op this function (return - FAILED), and fall back to host reset function, - wd33c93_host_reset ? */ + wdregs.SASR = ®s->SASR; + wdregs.SCMD = ®s->SCMD; - spin_lock_irq(cmd->device->host->host_lock); - wd33c93_host_reset(cmd); - spin_unlock_irq(cmd->device->host->host_lock); + hdata = shost_priv(instance); + if (gvp11_xfer_mask) + hdata->dma_xfer_mask = gvp11_xfer_mask; + else + hdata->dma_xfer_mask = default_dma_xfer_mask; - return SUCCESS; -} + hdata->no_sync = 0xff; + hdata->fast = 0; + hdata->dma_mode = CTRL_DMA; + /* + * Check for 14MHz SCSI clock + */ + epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000); + wd33c93_init(instance, wdregs, dma_setup, dma_stop, + (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10 + : WD33C93_FS_12_15); -#define HOSTS_C + error = request_irq(IRQ_AMIGA_PORTS, gvp11_intr, IRQF_SHARED, + "GVP11 SCSI", instance); + if (error) + goto fail_irq; -#include "gvp11.h" + regs->CNTR = GVP11_DMAC_INT_ENABLE; -static struct scsi_host_template driver_template = { - .proc_name = "GVP11", - .name = "GVP Series II SCSI", - .detect = gvp11_detect, - .release = gvp11_release, - .queuecommand = wd33c93_queuecommand, - .eh_abort_handler = wd33c93_abort, - .eh_bus_reset_handler = gvp11_bus_reset, - .eh_host_reset_handler = wd33c93_host_reset, - .can_queue = CAN_QUEUE, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = CMD_PER_LUN, - .use_clustering = DISABLE_CLUSTERING -}; + error = scsi_add_host(instance, NULL); + if (error) + goto fail_host; + zorro_set_drvdata(z, instance); + scsi_scan_host(instance); + return 0; -#include "scsi_module.c" +fail_host: + free_irq(IRQ_AMIGA_PORTS, instance); +fail_irq: + scsi_host_put(instance); +fail_check_or_alloc: + release_mem_region(address, 256); + return error; +} -int gvp11_release(struct Scsi_Host *instance) +static void __devexit gvp11_remove(struct zorro_dev *z) { -#ifdef MODULE + struct Scsi_Host *instance = zorro_get_drvdata(z); struct gvp11_scsiregs *regs = (struct gvp11_scsiregs *)(instance->base); regs->CNTR = 0; - release_mem_region(ZTWO_PADDR(instance->base), 256); + scsi_remove_host(instance); free_irq(IRQ_AMIGA_PORTS, instance); -#endif - return 1; + scsi_host_put(instance); + release_mem_region(z->resource.start, 256); +} + + /* + * This should (hopefully) be the correct way to identify + * all the different GVP SCSI controllers (except for the + * SERIES I though). + */ + +static struct zorro_device_id gvp11_zorro_tbl[] __devinitdata = { + { ZORRO_PROD_GVP_COMBO_030_R3_SCSI, ~0x00ffffff }, + { ZORRO_PROD_GVP_SERIES_II, ~0x00ffffff }, + { ZORRO_PROD_GVP_GFORCE_030_SCSI, ~0x01ffffff }, + { ZORRO_PROD_GVP_A530_SCSI, ~0x01ffffff }, + { ZORRO_PROD_GVP_COMBO_030_R4_SCSI, ~0x01ffffff }, + { ZORRO_PROD_GVP_A1291, ~0x07ffffff }, + { ZORRO_PROD_GVP_GFORCE_040_SCSI_1, ~0x07ffffff }, + { 0 } +}; +MODULE_DEVICE_TABLE(zorro, gvp11_zorro_tbl); + +static struct zorro_driver gvp11_driver = { + .name = "gvp11", + .id_table = gvp11_zorro_tbl, + .probe = gvp11_probe, + .remove = __devexit_p(gvp11_remove), +}; + +static int __init gvp11_init(void) +{ + return zorro_register_driver(&gvp11_driver); +} +module_init(gvp11_init); + +static void __exit gvp11_exit(void) +{ + zorro_unregister_driver(&gvp11_driver); } +module_exit(gvp11_exit); +MODULE_DESCRIPTION("GVP Series II SCSI"); MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/gvp11.h b/drivers/scsi/gvp11.h index b27a3ee3313e..852913cde5dd 100644 --- a/drivers/scsi/gvp11.h +++ b/drivers/scsi/gvp11.h @@ -11,9 +11,6 @@ #include -int gvp11_detect(struct scsi_host_template *); -int gvp11_release(struct Scsi_Host *); - #ifndef CMD_PER_LUN #define CMD_PER_LUN 2 #endif @@ -22,8 +19,6 @@ int gvp11_release(struct Scsi_Host *); #define CAN_QUEUE 16 #endif -#ifndef HOSTS_C - /* * if the transfer address ANDed with this results in a non-zero * result, then we can't use DMA. @@ -54,6 +49,4 @@ struct gvp11_scsiregs { #define GVP11_DMAC_INT_ENABLE (1<<3) #define GVP11_DMAC_DIR_WRITE (1<<4) -#endif /* else def HOSTS_C */ - #endif /* GVP11_H */ -- cgit v1.2.3 From cf2ed279f915f36c84ce21a5933ad4bba9f81de8 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 12 Apr 2010 21:55:25 +0200 Subject: m68k/scsi: gvp11 - Do not use legacy Scsi_Host.base Acked-by: James Bottomley Signed-off-by: Geert Uytterhoeven --- drivers/scsi/gvp11.c | 105 +++++++++++++++++++++++++++------------------------ 1 file changed, 56 insertions(+), 49 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index 4507a16ee1c6..2ce26eb7a1ec 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c @@ -18,11 +18,16 @@ #define CHECK_WD33C93 +struct gvp11_hostdata { + struct WD33C93_hostdata wh; + struct gvp11_scsiregs *regs; +}; + static irqreturn_t gvp11_intr(int irq, void *data) { struct Scsi_Host *instance = data; - struct gvp11_scsiregs *regs = (struct gvp11_scsiregs *)(instance->base); - unsigned int status = regs->CNTR; + struct gvp11_hostdata *hdata = shost_priv(instance); + unsigned int status = hdata->regs->CNTR; unsigned long flags; if (!(status & GVP11_DMAC_INT_PENDING)) @@ -44,65 +49,66 @@ void gvp11_setup(char *str, int *ints) static int dma_setup(struct scsi_cmnd *cmd, int dir_in) { struct Scsi_Host *instance = cmd->device->host; - struct WD33C93_hostdata *hdata = shost_priv(instance); - struct gvp11_scsiregs *regs = (struct gvp11_scsiregs *)(instance->base); + struct gvp11_hostdata *hdata = shost_priv(instance); + struct WD33C93_hostdata *wh = &hdata->wh; + struct gvp11_scsiregs *regs = hdata->regs; unsigned short cntr = GVP11_DMAC_INT_ENABLE; unsigned long addr = virt_to_bus(cmd->SCp.ptr); int bank_mask; static int scsi_alloc_out_of_range = 0; /* use bounce buffer if the physical address is bad */ - if (addr & hdata->dma_xfer_mask) { - hdata->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; + if (addr & wh->dma_xfer_mask) { + wh->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; if (!scsi_alloc_out_of_range) { - hdata->dma_bounce_buffer = - kmalloc(hdata->dma_bounce_len, GFP_KERNEL); - hdata->dma_buffer_pool = BUF_SCSI_ALLOCED; + wh->dma_bounce_buffer = + kmalloc(wh->dma_bounce_len, GFP_KERNEL); + wh->dma_buffer_pool = BUF_SCSI_ALLOCED; } if (scsi_alloc_out_of_range || - !hdata->dma_bounce_buffer) { - hdata->dma_bounce_buffer = - amiga_chip_alloc(hdata->dma_bounce_len, + !wh->dma_bounce_buffer) { + wh->dma_bounce_buffer = + amiga_chip_alloc(wh->dma_bounce_len, "GVP II SCSI Bounce Buffer"); - if (!hdata->dma_bounce_buffer) { - hdata->dma_bounce_len = 0; + if (!wh->dma_bounce_buffer) { + wh->dma_bounce_len = 0; return 1; } - hdata->dma_buffer_pool = BUF_CHIP_ALLOCED; + wh->dma_buffer_pool = BUF_CHIP_ALLOCED; } /* check if the address of the bounce buffer is OK */ - addr = virt_to_bus(hdata->dma_bounce_buffer); + addr = virt_to_bus(wh->dma_bounce_buffer); - if (addr & hdata->dma_xfer_mask) { + if (addr & wh->dma_xfer_mask) { /* fall back to Chip RAM if address out of range */ - if (hdata->dma_buffer_pool == BUF_SCSI_ALLOCED) { - kfree(hdata->dma_bounce_buffer); + if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED) { + kfree(wh->dma_bounce_buffer); scsi_alloc_out_of_range = 1; } else { - amiga_chip_free(hdata->dma_bounce_buffer); + amiga_chip_free(wh->dma_bounce_buffer); } - hdata->dma_bounce_buffer = - amiga_chip_alloc(hdata->dma_bounce_len, + wh->dma_bounce_buffer = + amiga_chip_alloc(wh->dma_bounce_len, "GVP II SCSI Bounce Buffer"); - if (!hdata->dma_bounce_buffer) { - hdata->dma_bounce_len = 0; + if (!wh->dma_bounce_buffer) { + wh->dma_bounce_len = 0; return 1; } - addr = virt_to_bus(hdata->dma_bounce_buffer); - hdata->dma_buffer_pool = BUF_CHIP_ALLOCED; + addr = virt_to_bus(wh->dma_bounce_buffer); + wh->dma_buffer_pool = BUF_CHIP_ALLOCED; } if (!dir_in) { /* copy to bounce buffer for a write */ - memcpy(hdata->dma_bounce_buffer, cmd->SCp.ptr, + memcpy(wh->dma_bounce_buffer, cmd->SCp.ptr, cmd->SCp.this_residual); } } @@ -111,7 +117,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) if (!dir_in) cntr |= GVP11_DMAC_DIR_WRITE; - hdata->dma_dir = dir_in; + wh->dma_dir = dir_in; regs->CNTR = cntr; /* setup DMA *physical* address */ @@ -125,7 +131,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) cache_push(addr, cmd->SCp.this_residual); } - bank_mask = (~hdata->dma_xfer_mask >> 18) & 0x01c0; + bank_mask = (~wh->dma_xfer_mask >> 18) & 0x01c0; if (bank_mask) regs->BANK = bank_mask & (addr >> 18); @@ -139,8 +145,9 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, int status) { - struct gvp11_scsiregs *regs = (struct gvp11_scsiregs *)(instance->base); - struct WD33C93_hostdata *hdata = shost_priv(instance); + struct gvp11_hostdata *hdata = shost_priv(instance); + struct WD33C93_hostdata *wh = &hdata->wh; + struct gvp11_scsiregs *regs = hdata->regs; /* stop DMA */ regs->SP_DMA = 1; @@ -148,18 +155,18 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, regs->CNTR = GVP11_DMAC_INT_ENABLE; /* copy from a bounce buffer, if necessary */ - if (status && hdata->dma_bounce_buffer) { - if (hdata->dma_dir && SCpnt) - memcpy(SCpnt->SCp.ptr, hdata->dma_bounce_buffer, + if (status && wh->dma_bounce_buffer) { + if (wh->dma_dir && SCpnt) + memcpy(SCpnt->SCp.ptr, wh->dma_bounce_buffer, SCpnt->SCp.this_residual); - if (hdata->dma_buffer_pool == BUF_SCSI_ALLOCED) - kfree(hdata->dma_bounce_buffer); + if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED) + kfree(wh->dma_bounce_buffer); else - amiga_chip_free(hdata->dma_bounce_buffer); + amiga_chip_free(wh->dma_bounce_buffer); - hdata->dma_bounce_buffer = NULL; - hdata->dma_bounce_len = 0; + wh->dma_bounce_buffer = NULL; + wh->dma_bounce_len = 0; } } @@ -284,7 +291,7 @@ static int __devinit gvp11_probe(struct zorro_dev *z, int error; unsigned int epc; unsigned int default_dma_xfer_mask; - struct WD33C93_hostdata *hdata; + struct gvp11_hostdata *hdata; struct gvp11_scsiregs *regs; wd33c93_regs wdregs; @@ -309,13 +316,12 @@ static int __devinit gvp11_probe(struct zorro_dev *z, goto fail_check_or_alloc; instance = scsi_host_alloc(&gvp11_scsi_template, - sizeof(struct WD33C93_hostdata)); + sizeof(struct gvp11_hostdata)); if (!instance) { error = -ENOMEM; goto fail_check_or_alloc; } - instance->base = (unsigned long)regs; instance->irq = IRQ_AMIGA_PORTS; instance->unique_id = z->slotaddr; @@ -332,13 +338,14 @@ static int __devinit gvp11_probe(struct zorro_dev *z, hdata = shost_priv(instance); if (gvp11_xfer_mask) - hdata->dma_xfer_mask = gvp11_xfer_mask; + hdata->wh.dma_xfer_mask = gvp11_xfer_mask; else - hdata->dma_xfer_mask = default_dma_xfer_mask; + hdata->wh.dma_xfer_mask = default_dma_xfer_mask; - hdata->no_sync = 0xff; - hdata->fast = 0; - hdata->dma_mode = CTRL_DMA; + hdata->wh.no_sync = 0xff; + hdata->wh.fast = 0; + hdata->wh.dma_mode = CTRL_DMA; + hdata->regs = regs; /* * Check for 14MHz SCSI clock @@ -375,9 +382,9 @@ fail_check_or_alloc: static void __devexit gvp11_remove(struct zorro_dev *z) { struct Scsi_Host *instance = zorro_get_drvdata(z); - struct gvp11_scsiregs *regs = (struct gvp11_scsiregs *)(instance->base); + struct gvp11_hostdata *hdata = shost_priv(instance); - regs->CNTR = 0; + hdata->regs->CNTR = 0; scsi_remove_host(instance); free_irq(IRQ_AMIGA_PORTS, instance); scsi_host_put(instance); -- cgit v1.2.3 From c2a24a4ca1137473971842461612e56a654e7edb Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 5 Apr 2009 13:02:45 +0200 Subject: m68k: amiga - A3000 SCSI platform device conversion Acked-by: James Bottomley Signed-off-by: Geert Uytterhoeven --- drivers/scsi/a3000.c | 164 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 100 insertions(+), 64 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c index 79a4a3c97474..7f09d89100a1 100644 --- a/drivers/scsi/a3000.c +++ b/drivers/scsi/a3000.c @@ -1,28 +1,21 @@ #include #include -#include -#include #include #include +#include #include #include +#include -#include #include #include #include #include -#include #include "scsi.h" -#include #include "wd33c93.h" #include "a3000.h" -#include - - -static int a3000_release(struct Scsi_Host *instance); static irqreturn_t a3000_intr(int irq, void *data) { @@ -39,7 +32,7 @@ static irqreturn_t a3000_intr(int irq, void *data) spin_unlock_irqrestore(instance->host_lock, flags); return IRQ_HANDLED; } - printk("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n", status); + pr_warning("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n", status); return IRQ_NONE; } @@ -162,93 +155,136 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, } } -static int __init a3000_detect(struct scsi_host_template *tpnt) +static int a3000_bus_reset(struct scsi_cmnd *cmd) +{ + struct Scsi_Host *instance = cmd->device->host; + + /* FIXME perform bus-specific reset */ + + /* FIXME 2: kill this entire function, which should + cause mid-layer to call wd33c93_host_reset anyway? */ + + spin_lock_irq(instance->host_lock); + wd33c93_host_reset(cmd); + spin_unlock_irq(instance->host_lock); + + return SUCCESS; +} + +static struct scsi_host_template amiga_a3000_scsi_template = { + .module = THIS_MODULE, + .name = "Amiga 3000 built-in SCSI", + .proc_info = wd33c93_proc_info, + .proc_name = "A3000", + .queuecommand = wd33c93_queuecommand, + .eh_abort_handler = wd33c93_abort, + .eh_bus_reset_handler = a3000_bus_reset, + .eh_host_reset_handler = wd33c93_host_reset, + .can_queue = CAN_QUEUE, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = CMD_PER_LUN, + .use_clustering = ENABLE_CLUSTERING +}; + +static int __init amiga_a3000_scsi_probe(struct platform_device *pdev) { + struct resource *res; struct Scsi_Host *instance; - wd33c93_regs wdregs; + int error; struct a3000_scsiregs *regs; + wd33c93_regs wdregs; struct WD33C93_hostdata *hdata; - if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(A3000_SCSI)) - return 0; - if (!request_mem_region(0xDD0000, 256, "wd33c93")) - return 0; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; - tpnt->proc_name = "A3000"; - tpnt->proc_info = &wd33c93_proc_info; + if (!request_mem_region(res->start, resource_size(res), "wd33c93")) + return -EBUSY; - instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata)); - if (instance == NULL) - goto fail_register; + instance = scsi_host_alloc(&amiga_a3000_scsi_template, + sizeof(struct WD33C93_hostdata)); + if (!instance) { + error = -ENOMEM; + goto fail_alloc; + } - instance->base = ZTWO_VADDR(0xDD0000); + instance->base = ZTWO_VADDR(res->start); instance->irq = IRQ_AMIGA_PORTS; + regs = (struct a3000_scsiregs *)(instance->base); regs->DAWR = DAWR_A3000; + wdregs.SASR = ®s->SASR; wdregs.SCMD = ®s->SCMD; + hdata = shost_priv(instance); hdata->no_sync = 0xff; hdata->fast = 0; hdata->dma_mode = CTRL_DMA; + wd33c93_init(instance, wdregs, dma_setup, dma_stop, WD33C93_FS_12_15); - if (request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, "A3000 SCSI", - instance)) + error = request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, + "A3000 SCSI", instance); + if (error) goto fail_irq; + regs->CNTR = CNTR_PDMD | CNTR_INTEN; - return 1; + error = scsi_add_host(instance, NULL); + if (error) + goto fail_host; -fail_irq: - scsi_unregister(instance); -fail_register: - release_mem_region(0xDD0000, 256); + platform_set_drvdata(pdev, instance); + + scsi_scan_host(instance); return 0; + +fail_host: + free_irq(IRQ_AMIGA_PORTS, instance); +fail_irq: + scsi_host_put(instance); +fail_alloc: + release_mem_region(res->start, resource_size(res)); + return error; } -static int a3000_bus_reset(struct scsi_cmnd *cmd) +static int __exit amiga_a3000_scsi_remove(struct platform_device *pdev) { - /* FIXME perform bus-specific reset */ - - /* FIXME 2: kill this entire function, which should - cause mid-layer to call wd33c93_host_reset anyway? */ - - spin_lock_irq(cmd->device->host->host_lock); - wd33c93_host_reset(cmd); - spin_unlock_irq(cmd->device->host->host_lock); + struct Scsi_Host *instance = platform_get_drvdata(pdev); + struct a3000_scsiregs *regs = (struct a3000_scsiregs *)(instance->base); + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - return SUCCESS; + regs->CNTR = 0; + scsi_remove_host(instance); + free_irq(IRQ_AMIGA_PORTS, instance); + scsi_host_put(instance); + release_mem_region(res->start, resource_size(res)); + return 0; } -#define HOSTS_C - -static struct scsi_host_template driver_template = { - .proc_name = "A3000", - .name = "Amiga 3000 built-in SCSI", - .detect = a3000_detect, - .release = a3000_release, - .queuecommand = wd33c93_queuecommand, - .eh_abort_handler = wd33c93_abort, - .eh_bus_reset_handler = a3000_bus_reset, - .eh_host_reset_handler = wd33c93_host_reset, - .can_queue = CAN_QUEUE, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = CMD_PER_LUN, - .use_clustering = ENABLE_CLUSTERING +static struct platform_driver amiga_a3000_scsi_driver = { + .remove = __exit_p(amiga_a3000_scsi_remove), + .driver = { + .name = "amiga-a3000-scsi", + .owner = THIS_MODULE, + }, }; - -#include "scsi_module.c" - -static int a3000_release(struct Scsi_Host *instance) +static int __init amiga_a3000_scsi_init(void) { - struct a3000_scsiregs *regs = (struct a3000_scsiregs *)(instance->base); + return platform_driver_probe(&amiga_a3000_scsi_driver, + amiga_a3000_scsi_probe); +} +module_init(amiga_a3000_scsi_init); - regs->CNTR = 0; - release_mem_region(0xDD0000, 256); - free_irq(IRQ_AMIGA_PORTS, a3000_intr); - return 1; +static void __exit amiga_a3000_scsi_exit(void) +{ + platform_driver_unregister(&amiga_a3000_scsi_driver); } +module_exit(amiga_a3000_scsi_exit); +MODULE_DESCRIPTION("Amiga 3000 built-in SCSI"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:amiga-a3000-scsi"); -- cgit v1.2.3 From 2b21d5e47bb9b07f90cf213c885867cf11f99976 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 12 Apr 2010 21:55:15 +0200 Subject: m68k/scsi: a3000 - Do not use legacy Scsi_Host.base Acked-by: James Bottomley Signed-off-by: Geert Uytterhoeven --- drivers/scsi/a3000.c | 76 ++++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 35 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c index 7f09d89100a1..d9468027fb61 100644 --- a/drivers/scsi/a3000.c +++ b/drivers/scsi/a3000.c @@ -17,11 +17,16 @@ #include "a3000.h" +struct a3000_hostdata { + struct WD33C93_hostdata wh; + struct a3000_scsiregs *regs; +}; + static irqreturn_t a3000_intr(int irq, void *data) { struct Scsi_Host *instance = data; - struct a3000_scsiregs *regs = (struct a3000_scsiregs *)(instance->base); - unsigned int status = regs->ISTR; + struct a3000_hostdata *hdata = shost_priv(instance); + unsigned int status = hdata->regs->ISTR; unsigned long flags; if (!(status & ISTR_INT_P)) @@ -39,8 +44,9 @@ static irqreturn_t a3000_intr(int irq, void *data) static int dma_setup(struct scsi_cmnd *cmd, int dir_in) { struct Scsi_Host *instance = cmd->device->host; - struct WD33C93_hostdata *hdata = shost_priv(instance); - struct a3000_scsiregs *regs = (struct a3000_scsiregs *)(instance->base); + struct a3000_hostdata *hdata = shost_priv(instance); + struct WD33C93_hostdata *wh = &hdata->wh; + struct a3000_scsiregs *regs = hdata->regs; unsigned short cntr = CNTR_PDMD | CNTR_INTEN; unsigned long addr = virt_to_bus(cmd->SCp.ptr); @@ -51,23 +57,23 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) * buffer */ if (addr & A3000_XFER_MASK) { - hdata->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; - hdata->dma_bounce_buffer = kmalloc(hdata->dma_bounce_len, - GFP_KERNEL); + wh->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; + wh->dma_bounce_buffer = kmalloc(wh->dma_bounce_len, + GFP_KERNEL); /* can't allocate memory; use PIO */ - if (!hdata->dma_bounce_buffer) { - hdata->dma_bounce_len = 0; + if (!wh->dma_bounce_buffer) { + wh->dma_bounce_len = 0; return 1; } if (!dir_in) { /* copy to bounce buffer for a write */ - memcpy(hdata->dma_bounce_buffer, cmd->SCp.ptr, + memcpy(wh->dma_bounce_buffer, cmd->SCp.ptr, cmd->SCp.this_residual); } - addr = virt_to_bus(hdata->dma_bounce_buffer); + addr = virt_to_bus(wh->dma_bounce_buffer); } /* setup dma direction */ @@ -75,7 +81,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) cntr |= CNTR_DDIR; /* remember direction */ - hdata->dma_dir = dir_in; + wh->dma_dir = dir_in; regs->CNTR = cntr; @@ -102,20 +108,21 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, int status) { - struct WD33C93_hostdata *hdata = shost_priv(instance); - struct a3000_scsiregs *regs = (struct a3000_scsiregs *)(instance->base); + struct a3000_hostdata *hdata = shost_priv(instance); + struct WD33C93_hostdata *wh = &hdata->wh; + struct a3000_scsiregs *regs = hdata->regs; /* disable SCSI interrupts */ unsigned short cntr = CNTR_PDMD; - if (!hdata->dma_dir) + if (!wh->dma_dir) cntr |= CNTR_DDIR; regs->CNTR = cntr; mb(); /* make sure CNTR is updated before next IO */ /* flush if we were reading */ - if (hdata->dma_dir) { + if (wh->dma_dir) { regs->FLUSH = 1; mb(); /* don't allow prefetch */ while (!(regs->ISTR & ISTR_FE_FLG)) @@ -138,19 +145,18 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, mb(); /* make sure CNTR is updated before next IO */ /* copy from a bounce buffer, if necessary */ - if (status && hdata->dma_bounce_buffer) { + if (status && wh->dma_bounce_buffer) { if (SCpnt) { - if (hdata->dma_dir && SCpnt) - memcpy(SCpnt->SCp.ptr, - hdata->dma_bounce_buffer, + if (wh->dma_dir && SCpnt) + memcpy(SCpnt->SCp.ptr, wh->dma_bounce_buffer, SCpnt->SCp.this_residual); - kfree(hdata->dma_bounce_buffer); - hdata->dma_bounce_buffer = NULL; - hdata->dma_bounce_len = 0; + kfree(wh->dma_bounce_buffer); + wh->dma_bounce_buffer = NULL; + wh->dma_bounce_len = 0; } else { - kfree(hdata->dma_bounce_buffer); - hdata->dma_bounce_buffer = NULL; - hdata->dma_bounce_len = 0; + kfree(wh->dma_bounce_buffer); + wh->dma_bounce_buffer = NULL; + wh->dma_bounce_len = 0; } } } @@ -194,7 +200,7 @@ static int __init amiga_a3000_scsi_probe(struct platform_device *pdev) int error; struct a3000_scsiregs *regs; wd33c93_regs wdregs; - struct WD33C93_hostdata *hdata; + struct a3000_hostdata *hdata; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) @@ -204,25 +210,25 @@ static int __init amiga_a3000_scsi_probe(struct platform_device *pdev) return -EBUSY; instance = scsi_host_alloc(&amiga_a3000_scsi_template, - sizeof(struct WD33C93_hostdata)); + sizeof(struct a3000_hostdata)); if (!instance) { error = -ENOMEM; goto fail_alloc; } - instance->base = ZTWO_VADDR(res->start); instance->irq = IRQ_AMIGA_PORTS; - regs = (struct a3000_scsiregs *)(instance->base); + regs = (struct a3000_scsiregs *)ZTWO_VADDR(res->start); regs->DAWR = DAWR_A3000; wdregs.SASR = ®s->SASR; wdregs.SCMD = ®s->SCMD; hdata = shost_priv(instance); - hdata->no_sync = 0xff; - hdata->fast = 0; - hdata->dma_mode = CTRL_DMA; + hdata->wh.no_sync = 0xff; + hdata->wh.fast = 0; + hdata->wh.dma_mode = CTRL_DMA; + hdata->regs = regs; wd33c93_init(instance, wdregs, dma_setup, dma_stop, WD33C93_FS_12_15); error = request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, @@ -253,10 +259,10 @@ fail_alloc: static int __exit amiga_a3000_scsi_remove(struct platform_device *pdev) { struct Scsi_Host *instance = platform_get_drvdata(pdev); - struct a3000_scsiregs *regs = (struct a3000_scsiregs *)(instance->base); + struct a3000_hostdata *hdata = shost_priv(instance); struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - regs->CNTR = 0; + hdata->regs->CNTR = 0; scsi_remove_host(instance); free_irq(IRQ_AMIGA_PORTS, instance); scsi_host_put(instance); -- cgit v1.2.3 From a24a6b22254bca8d54be6c8b7d8730d09f1058cc Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 5 Apr 2009 13:05:50 +0200 Subject: m68k: amiga - A4000T SCSI platform device conversion Acked-by: James Bottomley Signed-off-by: Geert Uytterhoeven --- drivers/scsi/a4000t.c | 101 +++++++++++++++++++++++--------------------------- 1 file changed, 46 insertions(+), 55 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c index 11ae6be8aeaf..23c76f41883c 100644 --- a/drivers/scsi/a4000t.c +++ b/drivers/scsi/a4000t.c @@ -20,10 +20,6 @@ #include "53c700.h" -MODULE_AUTHOR("Alan Hourihane / Kars de Jong "); -MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver"); -MODULE_LICENSE("GPL"); - static struct scsi_host_template a4000t_scsi_driver_template = { .name = "A4000T builtin SCSI", @@ -32,30 +28,35 @@ static struct scsi_host_template a4000t_scsi_driver_template = { .module = THIS_MODULE, }; -static struct platform_device *a4000t_scsi_device; -#define A4000T_SCSI_ADDR 0xdd0040 +#define A4000T_SCSI_OFFSET 0x40 -static int __devinit a4000t_probe(struct platform_device *dev) +static int __init amiga_a4000t_scsi_probe(struct platform_device *pdev) { - struct Scsi_Host *host; + struct resource *res; + phys_addr_t scsi_addr; struct NCR_700_Host_Parameters *hostdata; + struct Scsi_Host *host; - if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI))) - goto out; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; - if (!request_mem_region(A4000T_SCSI_ADDR, 0x1000, + if (!request_mem_region(res->start, resource_size(res), "A4000T builtin SCSI")) - goto out; + return -EBUSY; - hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); + hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), + GFP_KERNEL); if (!hostdata) { - printk(KERN_ERR "a4000t-scsi: Failed to allocate host data\n"); + dev_err(&pdev->dev, "Failed to allocate host data\n"); goto out_release; } + scsi_addr = res->start + A4000T_SCSI_OFFSET; + /* Fill in the required pieces of hostdata */ - hostdata->base = (void __iomem *)ZTWO_VADDR(A4000T_SCSI_ADDR); + hostdata->base = (void __iomem *)ZTWO_VADDR(scsi_addr); hostdata->clock = 50; hostdata->chip710 = 1; hostdata->dmode_extra = DMODE_FC2; @@ -63,26 +64,25 @@ static int __devinit a4000t_probe(struct platform_device *dev) /* and register the chip */ host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata, - &dev->dev); + &pdev->dev); if (!host) { - printk(KERN_ERR "a4000t-scsi: No host detected; " - "board configuration problem?\n"); + dev_err(&pdev->dev, + "No host detected; board configuration problem?\n"); goto out_free; } host->this_id = 7; - host->base = A4000T_SCSI_ADDR; + host->base = scsi_addr; host->irq = IRQ_AMIGA_PORTS; if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "a4000t-scsi", host)) { - printk(KERN_ERR "a4000t-scsi: request_irq failed\n"); + dev_err(&pdev->dev, "request_irq failed\n"); goto out_put_host; } - platform_set_drvdata(dev, host); + platform_set_drvdata(pdev, host); scsi_scan_host(host); - return 0; out_put_host: @@ -90,58 +90,49 @@ static int __devinit a4000t_probe(struct platform_device *dev) out_free: kfree(hostdata); out_release: - release_mem_region(A4000T_SCSI_ADDR, 0x1000); - out: + release_mem_region(res->start, resource_size(res)); return -ENODEV; } -static __devexit int a4000t_device_remove(struct platform_device *dev) +static int __exit amiga_a4000t_scsi_remove(struct platform_device *pdev) { - struct Scsi_Host *host = platform_get_drvdata(dev); + struct Scsi_Host *host = platform_get_drvdata(pdev); struct NCR_700_Host_Parameters *hostdata = shost_priv(host); + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); scsi_remove_host(host); - NCR_700_release(host); kfree(hostdata); free_irq(host->irq, host); - release_mem_region(A4000T_SCSI_ADDR, 0x1000); - + release_mem_region(res->start, resource_size(res)); return 0; } -static struct platform_driver a4000t_scsi_driver = { - .driver = { - .name = "a4000t-scsi", - .owner = THIS_MODULE, +static struct platform_driver amiga_a4000t_scsi_driver = { + .remove = __exit_p(amiga_a4000t_scsi_remove), + .driver = { + .name = "amiga-a4000t-scsi", + .owner = THIS_MODULE, }, - .probe = a4000t_probe, - .remove = __devexit_p(a4000t_device_remove), }; -static int __init a4000t_scsi_init(void) +static int __init amiga_a4000t_scsi_init(void) { - int err; - - err = platform_driver_register(&a4000t_scsi_driver); - if (err) - return err; - - a4000t_scsi_device = platform_device_register_simple("a4000t-scsi", - -1, NULL, 0); - if (IS_ERR(a4000t_scsi_device)) { - platform_driver_unregister(&a4000t_scsi_driver); - return PTR_ERR(a4000t_scsi_device); - } - - return err; + return platform_driver_probe(&amiga_a4000t_scsi_driver, + amiga_a4000t_scsi_probe); } -static void __exit a4000t_scsi_exit(void) +module_init(amiga_a4000t_scsi_init); + +static void __exit amiga_a4000t_scsi_exit(void) { - platform_device_unregister(a4000t_scsi_device); - platform_driver_unregister(&a4000t_scsi_driver); + platform_driver_unregister(&amiga_a4000t_scsi_driver); } -module_init(a4000t_scsi_init); -module_exit(a4000t_scsi_exit); +module_exit(amiga_a4000t_scsi_exit); + +MODULE_AUTHOR("Alan Hourihane / " + "Kars de Jong "); +MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:amiga-a4000t-scsi"); -- cgit v1.2.3 From e1c54b64027b52ba43b86fe6219910a9e9a88b73 Mon Sep 17 00:00:00 2001 From: Jan Blunck Date: Wed, 26 May 2010 14:44:44 -0700 Subject: osst: update ppos instead of using file->f_pos osst_read()/osst_write() modify file->f_pos directly instead of the ppos given to them. The VFS later updates the file->f_pos and overwrites it with the value of ppos. Signed-off-by: Jan Blunck Cc: Frederic Weisbecker Cc: Willem Riede Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/osst.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/scsi') diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 8dbf1c3afb7b..222f7f88e24a 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -3587,7 +3587,7 @@ if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name if (i == (-ENOSPC)) { transfer = STp->buffer->writing; /* FIXME -- check this logic */ if (transfer <= do_count) { - filp->f_pos += do_count - transfer; + *ppos += do_count - transfer; count -= do_count - transfer; if (STps->drv_block >= 0) { STps->drv_block += (do_count - transfer) / STp->block_size; @@ -3625,7 +3625,7 @@ if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name goto out; } - filp->f_pos += do_count; + *ppos += do_count; b_point += do_count; count -= do_count; if (STps->drv_block >= 0) { @@ -3647,7 +3647,7 @@ if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name if (STps->drv_block >= 0) { STps->drv_block += blks; } - filp->f_pos += count; + *ppos += count; count = 0; } @@ -3823,7 +3823,7 @@ static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, lo } STp->logical_blk_num += transfer / STp->block_size; STps->drv_block += transfer / STp->block_size; - filp->f_pos += transfer; + *ppos += transfer; buf += transfer; total += transfer; } -- cgit v1.2.3 From 889e5fbbc2da4f59d5f1e9b6172c5ff2b92d02c8 Mon Sep 17 00:00:00 2001 From: Jan Blunck Date: Wed, 26 May 2010 14:44:50 -0700 Subject: osst: use noop_llseek() instead of default_llseek() __os_scsi_tape_open() suggests that llseek() doesn't work: "We really want to do nonseekable_open(inode, filp); here, but some versions of tar incorrectly call lseek on tapes and bail out if that fails. So we disallow pread() and pwrite(), but permit lseeks." Instead of using the fallback default_llseek() the driver should use noop_llseek() which leaves the file->f_pos untouched but succeeds. Signed-off-by: Jan Blunck Cc: Frederic Weisbecker Cc: Willem Riede Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/osst.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 222f7f88e24a..d64b7178fa08 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -5626,6 +5626,7 @@ static const struct file_operations osst_fops = { .open = os_scsi_tape_open, .flush = os_scsi_tape_flush, .release = os_scsi_tape_close, + .llseek = noop_llseek, }; static int osst_supports(struct scsi_device * SDp) -- cgit v1.2.3 From b4d878e23c7f574490ee4d6fd59ebd6819781dd1 Mon Sep 17 00:00:00 2001 From: Jan Blunck Date: Wed, 26 May 2010 14:44:51 -0700 Subject: st: use noop_llseek() instead of default_llseek() st_open() suggests that llseek() doesn't work: "We really want to do nonseekable_open(inode, filp); here, but some versions of tar incorrectly call lseek on tapes and bail out if that fails. So we disallow pread() and pwrite(), but permit lseeks." Instead of using the fallback default_llseek() the driver should use noop_llseek() which leaves the file->f_pos untouched but succeeds. Signed-off-by: Jan Blunck Cc: Frederic Weisbecker Cc: Kai Makisara Cc: Willem Riede Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/st.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/scsi') diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 3ea1a713ef25..24211d0efa6d 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -3962,6 +3962,7 @@ static const struct file_operations st_fops = .open = st_open, .flush = st_flush, .release = st_release, + .llseek = noop_llseek, }; static int st_probe(struct device *dev) -- cgit v1.2.3