X-Git-Url: https://git.openpandora.org/cgi-bin/gitweb.cgi?p=pandora-kernel.git;a=blobdiff_plain;f=drivers%2Fs390%2Fscsi%2Fzfcp_scsi.c;h=1bb55086db9f423ca8ab76849e57f24791c16106;hp=9f6b4d7a46f3342a2b853ee0d501b37e46b3b846;hb=9129d6ea475b7e9f216c8324ea05b7a0d8aba540;hpb=ab479995b191b4256183956c13caabb86331af8e diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 9f6b4d7a46f3..1bb55086db9f 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -1,18 +1,8 @@ /* - * - * linux/drivers/s390/scsi/zfcp_scsi.c - * - * FCP adapter driver for IBM eServer zSeries - * - * (C) Copyright IBM Corp. 2002, 2004 + * This file is part of the zfcp device driver for + * FCP adapters for IBM System z9 and zSeries. * - * Author(s): Martin Peschke - * Raimund Schroeder - * Aron Zeh - * Wolfgang Taphorn - * Stefan Bader - * Heiko Carstens - * Andreas Herrmann + * (C) Copyright IBM Corp. 2002, 2006 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,13 +30,12 @@ static int zfcp_scsi_queuecommand(struct scsi_cmnd *, void (*done) (struct scsi_cmnd *)); static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *); static int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *); -static int zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *); static int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *); static int zfcp_task_management_function(struct zfcp_unit *, u8, struct scsi_cmnd *); -static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t, - scsi_lun_t); +static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, + unsigned int, unsigned int); static struct device_attribute *zfcp_sysfs_sdev_attrs[]; @@ -54,33 +43,24 @@ struct scsi_transport_template *zfcp_transport_template; struct zfcp_data zfcp_data = { .scsi_host_template = { - name: ZFCP_NAME, - proc_name: "zfcp", - proc_info: NULL, - detect: NULL, - slave_alloc: zfcp_scsi_slave_alloc, - slave_configure: zfcp_scsi_slave_configure, - slave_destroy: zfcp_scsi_slave_destroy, - queuecommand: zfcp_scsi_queuecommand, - eh_abort_handler: zfcp_scsi_eh_abort_handler, - eh_device_reset_handler: zfcp_scsi_eh_device_reset_handler, - eh_bus_reset_handler: zfcp_scsi_eh_bus_reset_handler, - eh_host_reset_handler: zfcp_scsi_eh_host_reset_handler, - /* FIXME(openfcp): Tune */ - can_queue: 4096, - this_id: 0, - /* - * FIXME: - * one less? can zfcp_create_sbale cope with it? - */ - sg_tablesize: ZFCP_MAX_SBALES_PER_REQ, - cmd_per_lun: 1, - unchecked_isa_dma: 0, - use_clustering: 1, - sdev_attrs: zfcp_sysfs_sdev_attrs, + .name = ZFCP_NAME, + .proc_name = "zfcp", + .slave_alloc = zfcp_scsi_slave_alloc, + .slave_configure = zfcp_scsi_slave_configure, + .slave_destroy = zfcp_scsi_slave_destroy, + .queuecommand = zfcp_scsi_queuecommand, + .eh_abort_handler = zfcp_scsi_eh_abort_handler, + .eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler, + .eh_bus_reset_handler = zfcp_scsi_eh_host_reset_handler, + .eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler, + .can_queue = 4096, + .this_id = -1, + .sg_tablesize = ZFCP_MAX_SBALES_PER_REQ, + .cmd_per_lun = 1, + .use_clustering = 1, + .sdev_attrs = zfcp_sysfs_sdev_attrs, }, .driver_version = ZFCP_VERSION, - /* rest initialised with zeros */ }; /* Find start of Response Information in FCP response unit*/ @@ -161,14 +141,6 @@ set_driver_byte(u32 * result, char status) set_byte(result, status, 3); } -/* - * function: zfcp_scsi_slave_alloc - * - * purpose: - * - * returns: - */ - static int zfcp_scsi_slave_alloc(struct scsi_device *sdp) { @@ -183,7 +155,8 @@ zfcp_scsi_slave_alloc(struct scsi_device *sdp) read_lock_irqsave(&zfcp_data.config_lock, flags); unit = zfcp_unit_lookup(adapter, sdp->channel, sdp->id, sdp->lun); - if (unit) { + if (unit && atomic_test_mask(ZFCP_STATUS_UNIT_REGISTERED, + &unit->status)) { sdp->hostdata = unit; unit->device = sdp; zfcp_unit_get(unit); @@ -194,22 +167,22 @@ zfcp_scsi_slave_alloc(struct scsi_device *sdp) return retval; } -/* - * function: zfcp_scsi_slave_destroy - * - * purpose: +/** + * zfcp_scsi_slave_destroy - called when scsi device is removed * - * returns: + * Remove reference to associated scsi device for an zfcp_unit. + * Mark zfcp_unit as failed. The scsi device might be deleted via sysfs + * or a scan for this device might have failed. */ - -static void -zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) +static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) { struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata; if (unit) { + atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status); sdpnt->hostdata = NULL; unit->device = NULL; + zfcp_erp_unit_failed(unit); zfcp_unit_put(unit); } else { ZFCP_LOG_NORMAL("bug: no unit associated with SCSI device at " @@ -291,7 +264,7 @@ zfcp_scsi_command_async(struct zfcp_adapter *adapter, struct zfcp_unit *unit, "on port 0x%016Lx in recovery\n", zfcp_get_busid_by_unit(unit), unit->fcp_lun, unit->port->wwpn); - retval = SCSI_MLQUEUE_DEVICE_BUSY; + zfcp_scsi_command_fail(scpnt, DID_NO_CONNECT); goto out; } @@ -372,18 +345,9 @@ zfcp_scsi_queuecommand(struct scsi_cmnd *scpnt, return zfcp_scsi_command_async(adapter, unit, scpnt, NULL); } -/* - * function: zfcp_unit_lookup - * - * purpose: - * - * returns: - * - * context: - */ static struct zfcp_unit * -zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id, - scsi_lun_t lun) +zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, unsigned int id, + unsigned int lun) { struct zfcp_port *port; struct zfcp_unit *unit, *retval = NULL; @@ -489,13 +453,6 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt) return retval; } -/* - * function: zfcp_scsi_eh_device_reset_handler - * - * purpose: - * - * returns: - */ int zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt) { @@ -590,46 +547,42 @@ zfcp_task_management_function(struct zfcp_unit *unit, u8 tm_flags, } /** - * zfcp_scsi_eh_bus_reset_handler - reset bus (reopen adapter) + * zfcp_scsi_eh_host_reset_handler - handler for host and bus reset + * + * If ERP is already running it will be stopped. */ -int -zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt) +int zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) { - struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata; - struct zfcp_adapter *adapter = unit->port->adapter; - - ZFCP_LOG_NORMAL("bus reset because of problems with " - "unit 0x%016Lx\n", unit->fcp_lun); - zfcp_erp_adapter_reopen(adapter, 0); - zfcp_erp_wait(adapter); - - return SUCCESS; -} + struct zfcp_unit *unit; + struct zfcp_adapter *adapter; + unsigned long flags; -/** - * zfcp_scsi_eh_host_reset_handler - reset host (reopen adapter) - */ -int -zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt) -{ - struct zfcp_unit *unit = (struct zfcp_unit*) scpnt->device->hostdata; - struct zfcp_adapter *adapter = unit->port->adapter; + unit = (struct zfcp_unit*) scpnt->device->hostdata; + adapter = unit->port->adapter; - ZFCP_LOG_NORMAL("host reset because of problems with " + ZFCP_LOG_NORMAL("host/bus reset because of problems with " "unit 0x%016Lx\n", unit->fcp_lun); - zfcp_erp_adapter_reopen(adapter, 0); - zfcp_erp_wait(adapter); + + write_lock_irqsave(&adapter->erp_lock, flags); + if (atomic_test_mask(ZFCP_STATUS_ADAPTER_ERP_PENDING, + &adapter->status)) { + zfcp_erp_modify_adapter_status(adapter, + ZFCP_STATUS_COMMON_UNBLOCKED|ZFCP_STATUS_COMMON_OPEN, + ZFCP_CLEAR); + zfcp_erp_action_dismiss_adapter(adapter); + write_unlock_irqrestore(&adapter->erp_lock, flags); + zfcp_fsf_req_dismiss_all(adapter); + adapter->fsf_req_seq_no = 0; + zfcp_erp_adapter_reopen(adapter, 0); + } else { + write_unlock_irqrestore(&adapter->erp_lock, flags); + zfcp_erp_adapter_reopen(adapter, 0); + zfcp_erp_wait(adapter); + } return SUCCESS; } -/* - * function: - * - * purpose: - * - * returns: - */ int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) { @@ -655,10 +608,6 @@ zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) adapter->scsi_host->unique_id = unique_id++; /* FIXME */ adapter->scsi_host->max_cmd_len = ZFCP_MAX_SCSI_CMND_LENGTH; adapter->scsi_host->transportt = zfcp_transport_template; - /* - * Reverse mapping of the host number to avoid race condition - */ - adapter->scsi_host_no = adapter->scsi_host->host_no; /* * save a pointer to our own adapter data structure within @@ -676,13 +625,6 @@ zfcp_adapter_scsi_register(struct zfcp_adapter *adapter) return retval; } -/* - * function: - * - * purpose: - * - * returns: - */ void zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter) { @@ -701,7 +643,6 @@ zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter) scsi_remove_host(shost); scsi_host_put(shost); adapter->scsi_host = NULL; - adapter->scsi_host_no = 0; atomic_clear_mask(ZFCP_STATUS_ADAPTER_REGISTERED, &adapter->status); return; @@ -815,10 +756,9 @@ zfcp_get_fc_host_stats(struct Scsi_Host *shost) if (!fc_stats) return NULL; - data = kmalloc(sizeof(*data), GFP_KERNEL); + data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return NULL; - memset(data, 0, sizeof(*data)); ret = zfcp_fsf_exchange_port_data(NULL, adapter, data); if (ret) { @@ -846,10 +786,9 @@ zfcp_reset_fc_host_stats(struct Scsi_Host *shost) int ret; adapter = (struct zfcp_adapter *)shost->hostdata[0]; - data = kmalloc(sizeof(*data), GFP_KERNEL); + data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return; - memset(data, 0, sizeof(*data)); ret = zfcp_fsf_exchange_port_data(NULL, adapter, data); if (ret == 0) { @@ -861,11 +800,18 @@ zfcp_reset_fc_host_stats(struct Scsi_Host *shost) } } +static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout) +{ + rport->dev_loss_tmo = timeout; +} + struct fc_function_template zfcp_transport_functions = { .show_starget_port_id = 1, .show_starget_port_name = 1, .show_starget_node_name = 1, .show_rport_supported_classes = 1, + .show_rport_maxframe_size = 1, + .show_rport_dev_loss_tmo = 1, .show_host_node_name = 1, .show_host_port_name = 1, .show_host_permanent_port_name = 1, @@ -875,6 +821,7 @@ struct fc_function_template zfcp_transport_functions = { .show_host_serial_number = 1, .get_fc_host_stats = zfcp_get_fc_host_stats, .reset_fc_host_stats = zfcp_reset_fc_host_stats, + .set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo, /* no functions registered for following dynamic attributes but directly set by LLDD */ .show_host_port_type = 1,