mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
Merge SCSI misc branch into isci-for-3.6 tag
This commit is contained in:
commit
fe709ed827
176 changed files with 13492 additions and 4460 deletions
|
|
@ -519,6 +519,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
|
|||
|
||||
rwlock_init(&port->unit_list_lock);
|
||||
INIT_LIST_HEAD(&port->unit_list);
|
||||
atomic_set(&port->units, 0);
|
||||
|
||||
INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup);
|
||||
INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work);
|
||||
|
|
|
|||
|
|
@ -39,19 +39,25 @@ void zfcp_ccw_adapter_put(struct zfcp_adapter *adapter)
|
|||
spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags);
|
||||
}
|
||||
|
||||
static int zfcp_ccw_activate(struct ccw_device *cdev)
|
||||
|
||||
/**
|
||||
* zfcp_ccw_activate - activate adapter and wait for it to finish
|
||||
* @cdev: pointer to belonging ccw device
|
||||
* @clear: Status flags to clear.
|
||||
* @tag: s390dbf trace record tag
|
||||
*/
|
||||
static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag)
|
||||
{
|
||||
struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
|
||||
|
||||
if (!adapter)
|
||||
return 0;
|
||||
|
||||
zfcp_erp_clear_adapter_status(adapter, clear);
|
||||
zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING);
|
||||
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED,
|
||||
"ccresu2");
|
||||
tag);
|
||||
zfcp_erp_wait(adapter);
|
||||
flush_work(&adapter->scan_work);
|
||||
flush_work(&adapter->scan_work); /* ok to call even if nothing queued */
|
||||
|
||||
zfcp_ccw_adapter_put(adapter);
|
||||
|
||||
|
|
@ -164,7 +170,36 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev)
|
|||
BUG_ON(!zfcp_reqlist_isempty(adapter->req_list));
|
||||
adapter->req_no = 0;
|
||||
|
||||
zfcp_ccw_activate(cdev);
|
||||
zfcp_ccw_activate(cdev, 0, "ccsonl1");
|
||||
/* scan for remote ports
|
||||
either at the end of any successful adapter recovery
|
||||
or only after the adapter recovery for setting a device online */
|
||||
zfcp_fc_inverse_conditional_port_scan(adapter);
|
||||
flush_work(&adapter->scan_work); /* ok to call even if nothing queued */
|
||||
zfcp_ccw_adapter_put(adapter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_ccw_offline_sync - shut down adapter and wait for it to finish
|
||||
* @cdev: pointer to belonging ccw device
|
||||
* @set: Status flags to set.
|
||||
* @tag: s390dbf trace record tag
|
||||
*
|
||||
* This function gets called by the common i/o layer and sets an adapter
|
||||
* into state offline.
|
||||
*/
|
||||
static int zfcp_ccw_offline_sync(struct ccw_device *cdev, int set, char *tag)
|
||||
{
|
||||
struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
|
||||
|
||||
if (!adapter)
|
||||
return 0;
|
||||
|
||||
zfcp_erp_set_adapter_status(adapter, set);
|
||||
zfcp_erp_adapter_shutdown(adapter, 0, tag);
|
||||
zfcp_erp_wait(adapter);
|
||||
|
||||
zfcp_ccw_adapter_put(adapter);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -178,16 +213,7 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev)
|
|||
*/
|
||||
static int zfcp_ccw_set_offline(struct ccw_device *cdev)
|
||||
{
|
||||
struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev);
|
||||
|
||||
if (!adapter)
|
||||
return 0;
|
||||
|
||||
zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1");
|
||||
zfcp_erp_wait(adapter);
|
||||
|
||||
zfcp_ccw_adapter_put(adapter);
|
||||
return 0;
|
||||
return zfcp_ccw_offline_sync(cdev, 0, "ccsoff1");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -207,6 +233,11 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event)
|
|||
|
||||
switch (event) {
|
||||
case CIO_GONE:
|
||||
if (atomic_read(&adapter->status) &
|
||||
ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */
|
||||
zfcp_dbf_hba_basic("ccnigo1", adapter);
|
||||
break;
|
||||
}
|
||||
dev_warn(&cdev->dev, "The FCP device has been detached\n");
|
||||
zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1");
|
||||
break;
|
||||
|
|
@ -216,6 +247,11 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event)
|
|||
zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2");
|
||||
break;
|
||||
case CIO_OPER:
|
||||
if (atomic_read(&adapter->status) &
|
||||
ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */
|
||||
zfcp_dbf_hba_basic("ccniop1", adapter);
|
||||
break;
|
||||
}
|
||||
dev_info(&cdev->dev, "The FCP device is operational again\n");
|
||||
zfcp_erp_set_adapter_status(adapter,
|
||||
ZFCP_STATUS_COMMON_RUNNING);
|
||||
|
|
@ -251,6 +287,28 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev)
|
|||
zfcp_ccw_adapter_put(adapter);
|
||||
}
|
||||
|
||||
static int zfcp_ccw_suspend(struct ccw_device *cdev)
|
||||
{
|
||||
zfcp_ccw_offline_sync(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccsusp1");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zfcp_ccw_thaw(struct ccw_device *cdev)
|
||||
{
|
||||
/* trace records for thaw and final shutdown during suspend
|
||||
can only be found in system dump until the end of suspend
|
||||
but not after resume because it's based on the memory image
|
||||
right after the very first suspend (freeze) callback */
|
||||
zfcp_ccw_activate(cdev, 0, "ccthaw1");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zfcp_ccw_resume(struct ccw_device *cdev)
|
||||
{
|
||||
zfcp_ccw_activate(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccresu1");
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ccw_driver zfcp_ccw_driver = {
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
|
|
@ -263,7 +321,7 @@ struct ccw_driver zfcp_ccw_driver = {
|
|||
.set_offline = zfcp_ccw_set_offline,
|
||||
.notify = zfcp_ccw_notify,
|
||||
.shutdown = zfcp_ccw_shutdown,
|
||||
.freeze = zfcp_ccw_set_offline,
|
||||
.thaw = zfcp_ccw_activate,
|
||||
.restore = zfcp_ccw_activate,
|
||||
.freeze = zfcp_ccw_suspend,
|
||||
.thaw = zfcp_ccw_thaw,
|
||||
.restore = zfcp_ccw_resume,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -293,7 +293,7 @@ void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *adapter)
|
|||
}
|
||||
read_unlock_irqrestore(&adapter->port_list_lock, flags);
|
||||
|
||||
shost_for_each_device(sdev, port->adapter->scsi_host) {
|
||||
shost_for_each_device(sdev, adapter->scsi_host) {
|
||||
zfcp_sdev = sdev_to_zfcp(sdev);
|
||||
status = atomic_read(&zfcp_sdev->status);
|
||||
if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) ||
|
||||
|
|
|
|||
|
|
@ -191,7 +191,7 @@ void zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter, u64 req_id, u16 scount,
|
|||
length = min((u16)sizeof(struct qdio_buffer),
|
||||
(u16)ZFCP_DBF_PAY_MAX_REC);
|
||||
|
||||
while ((char *)pl[payload->counter] && payload->counter < scount) {
|
||||
while (payload->counter < scount && (char *)pl[payload->counter]) {
|
||||
memcpy(payload->data, (char *)pl[payload->counter], length);
|
||||
debug_event(dbf->pay, 1, payload, zfcp_dbf_plen(length));
|
||||
payload->counter++;
|
||||
|
|
@ -200,6 +200,26 @@ void zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter, u64 req_id, u16 scount,
|
|||
spin_unlock_irqrestore(&dbf->pay_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_dbf_hba_basic - trace event for basic adapter events
|
||||
* @adapter: pointer to struct zfcp_adapter
|
||||
*/
|
||||
void zfcp_dbf_hba_basic(char *tag, struct zfcp_adapter *adapter)
|
||||
{
|
||||
struct zfcp_dbf *dbf = adapter->dbf;
|
||||
struct zfcp_dbf_hba *rec = &dbf->hba_buf;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dbf->hba_lock, flags);
|
||||
memset(rec, 0, sizeof(*rec));
|
||||
|
||||
memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN);
|
||||
rec->id = ZFCP_DBF_HBA_BASIC;
|
||||
|
||||
debug_event(dbf->hba, 1, rec, sizeof(*rec));
|
||||
spin_unlock_irqrestore(&dbf->hba_lock, flags);
|
||||
}
|
||||
|
||||
static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec,
|
||||
struct zfcp_adapter *adapter,
|
||||
struct zfcp_port *port,
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ enum zfcp_dbf_hba_id {
|
|||
ZFCP_DBF_HBA_RES = 1,
|
||||
ZFCP_DBF_HBA_USS = 2,
|
||||
ZFCP_DBF_HBA_BIT = 3,
|
||||
ZFCP_DBF_HBA_BASIC = 4,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ struct zfcp_reqlist;
|
|||
#define ZFCP_STATUS_ADAPTER_SIOSL_ISSUED 0x00000004
|
||||
#define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008
|
||||
#define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010
|
||||
#define ZFCP_STATUS_ADAPTER_SUSPENDED 0x00000040
|
||||
#define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100
|
||||
#define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200
|
||||
#define ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED 0x00000400
|
||||
|
|
@ -204,6 +205,7 @@ struct zfcp_port {
|
|||
struct zfcp_adapter *adapter; /* adapter used to access port */
|
||||
struct list_head unit_list; /* head of logical unit list */
|
||||
rwlock_t unit_list_lock; /* unit list lock */
|
||||
atomic_t units; /* zfcp_unit count */
|
||||
atomic_t status; /* status of this remote port */
|
||||
u64 wwnn; /* WWNN if known */
|
||||
u64 wwpn; /* WWPN */
|
||||
|
|
|
|||
|
|
@ -1230,7 +1230,7 @@ static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
|
|||
case ZFCP_ERP_ACTION_REOPEN_ADAPTER:
|
||||
if (result == ZFCP_ERP_SUCCEEDED) {
|
||||
register_service_level(&adapter->service_level);
|
||||
queue_work(adapter->work_queue, &adapter->scan_work);
|
||||
zfcp_fc_conditional_port_scan(adapter);
|
||||
queue_work(adapter->work_queue, &adapter->ns_up_work);
|
||||
} else
|
||||
unregister_service_level(&adapter->service_level);
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ extern void zfcp_dbf_hba_fsf_res(char *, struct zfcp_fsf_req *);
|
|||
extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *);
|
||||
extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *);
|
||||
extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **);
|
||||
extern void zfcp_dbf_hba_basic(char *, struct zfcp_adapter *);
|
||||
extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32);
|
||||
extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *);
|
||||
extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *);
|
||||
|
|
@ -98,6 +99,8 @@ extern void zfcp_fc_gs_destroy(struct zfcp_adapter *);
|
|||
extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *);
|
||||
extern int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *);
|
||||
extern void zfcp_fc_sym_name_update(struct work_struct *);
|
||||
extern void zfcp_fc_conditional_port_scan(struct zfcp_adapter *);
|
||||
extern void zfcp_fc_inverse_conditional_port_scan(struct zfcp_adapter *);
|
||||
|
||||
/* zfcp_fsf.c */
|
||||
extern struct kmem_cache *zfcp_fsf_qtcb_cache;
|
||||
|
|
@ -158,6 +161,7 @@ extern void zfcp_scsi_dif_sense_error(struct scsi_cmnd *, int);
|
|||
extern struct attribute_group zfcp_sysfs_unit_attrs;
|
||||
extern struct attribute_group zfcp_sysfs_adapter_attrs;
|
||||
extern struct attribute_group zfcp_sysfs_port_attrs;
|
||||
extern struct mutex zfcp_sysfs_port_units_mutex;
|
||||
extern struct device_attribute *zfcp_sysfs_sdev_attrs[];
|
||||
extern struct device_attribute *zfcp_sysfs_shost_attrs[];
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,27 @@ static u32 zfcp_fc_rscn_range_mask[] = {
|
|||
[ELS_ADDR_FMT_FAB] = 0x000000,
|
||||
};
|
||||
|
||||
static bool no_auto_port_rescan;
|
||||
module_param_named(no_auto_port_rescan, no_auto_port_rescan, bool, 0600);
|
||||
MODULE_PARM_DESC(no_auto_port_rescan,
|
||||
"no automatic port_rescan (default off)");
|
||||
|
||||
void zfcp_fc_conditional_port_scan(struct zfcp_adapter *adapter)
|
||||
{
|
||||
if (no_auto_port_rescan)
|
||||
return;
|
||||
|
||||
queue_work(adapter->work_queue, &adapter->scan_work);
|
||||
}
|
||||
|
||||
void zfcp_fc_inverse_conditional_port_scan(struct zfcp_adapter *adapter)
|
||||
{
|
||||
if (!no_auto_port_rescan)
|
||||
return;
|
||||
|
||||
queue_work(adapter->work_queue, &adapter->scan_work);
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_fc_post_event - post event to userspace via fc_transport
|
||||
* @work: work struct with enqueued events
|
||||
|
|
@ -206,7 +227,7 @@ static void zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req)
|
|||
zfcp_fc_enqueue_event(fsf_req->adapter, FCH_EVT_RSCN,
|
||||
*(u32 *)page);
|
||||
}
|
||||
queue_work(fsf_req->adapter->work_queue, &fsf_req->adapter->scan_work);
|
||||
zfcp_fc_conditional_port_scan(fsf_req->adapter);
|
||||
}
|
||||
|
||||
static void zfcp_fc_incoming_wwpn(struct zfcp_fsf_req *req, u64 wwpn)
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
|
|||
return;
|
||||
}
|
||||
|
||||
zfcp_dbf_hba_fsf_uss("fssrh_2", req);
|
||||
zfcp_dbf_hba_fsf_uss("fssrh_4", req);
|
||||
|
||||
switch (sr_buf->status_type) {
|
||||
case FSF_STATUS_READ_PORT_CLOSED:
|
||||
|
|
@ -257,7 +257,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req)
|
|||
if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_ACT_UPDATED)
|
||||
zfcp_cfdc_adapter_access_changed(adapter);
|
||||
if (sr_buf->status_subtype & FSF_STATUS_READ_SUB_INCOMING_ELS)
|
||||
queue_work(adapter->work_queue, &adapter->scan_work);
|
||||
zfcp_fc_conditional_port_scan(adapter);
|
||||
break;
|
||||
case FSF_STATUS_READ_CFDC_UPDATED:
|
||||
zfcp_cfdc_adapter_access_changed(adapter);
|
||||
|
|
@ -437,6 +437,34 @@ void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
|
|||
}
|
||||
}
|
||||
|
||||
#define ZFCP_FSF_PORTSPEED_1GBIT (1 << 0)
|
||||
#define ZFCP_FSF_PORTSPEED_2GBIT (1 << 1)
|
||||
#define ZFCP_FSF_PORTSPEED_4GBIT (1 << 2)
|
||||
#define ZFCP_FSF_PORTSPEED_10GBIT (1 << 3)
|
||||
#define ZFCP_FSF_PORTSPEED_8GBIT (1 << 4)
|
||||
#define ZFCP_FSF_PORTSPEED_16GBIT (1 << 5)
|
||||
#define ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED (1 << 15)
|
||||
|
||||
static u32 zfcp_fsf_convert_portspeed(u32 fsf_speed)
|
||||
{
|
||||
u32 fdmi_speed = 0;
|
||||
if (fsf_speed & ZFCP_FSF_PORTSPEED_1GBIT)
|
||||
fdmi_speed |= FC_PORTSPEED_1GBIT;
|
||||
if (fsf_speed & ZFCP_FSF_PORTSPEED_2GBIT)
|
||||
fdmi_speed |= FC_PORTSPEED_2GBIT;
|
||||
if (fsf_speed & ZFCP_FSF_PORTSPEED_4GBIT)
|
||||
fdmi_speed |= FC_PORTSPEED_4GBIT;
|
||||
if (fsf_speed & ZFCP_FSF_PORTSPEED_10GBIT)
|
||||
fdmi_speed |= FC_PORTSPEED_10GBIT;
|
||||
if (fsf_speed & ZFCP_FSF_PORTSPEED_8GBIT)
|
||||
fdmi_speed |= FC_PORTSPEED_8GBIT;
|
||||
if (fsf_speed & ZFCP_FSF_PORTSPEED_16GBIT)
|
||||
fdmi_speed |= FC_PORTSPEED_16GBIT;
|
||||
if (fsf_speed & ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED)
|
||||
fdmi_speed |= FC_PORTSPEED_NOT_NEGOTIATED;
|
||||
return fdmi_speed;
|
||||
}
|
||||
|
||||
static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
|
||||
{
|
||||
struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config;
|
||||
|
|
@ -456,7 +484,8 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req)
|
|||
fc_host_port_name(shost) = nsp->fl_wwpn;
|
||||
fc_host_node_name(shost) = nsp->fl_wwnn;
|
||||
fc_host_port_id(shost) = ntoh24(bottom->s_id);
|
||||
fc_host_speed(shost) = bottom->fc_link_speed;
|
||||
fc_host_speed(shost) =
|
||||
zfcp_fsf_convert_portspeed(bottom->fc_link_speed);
|
||||
fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
|
||||
|
||||
adapter->hydra_version = bottom->adapter_type;
|
||||
|
|
@ -580,7 +609,8 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req)
|
|||
} else
|
||||
fc_host_permanent_port_name(shost) = fc_host_port_name(shost);
|
||||
fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
|
||||
fc_host_supported_speeds(shost) = bottom->supported_speed;
|
||||
fc_host_supported_speeds(shost) =
|
||||
zfcp_fsf_convert_portspeed(bottom->supported_speed);
|
||||
memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types,
|
||||
FC_FC4_LIST_SIZE);
|
||||
memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types,
|
||||
|
|
@ -771,12 +801,14 @@ out:
|
|||
static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req)
|
||||
{
|
||||
struct scsi_device *sdev = req->data;
|
||||
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
|
||||
struct zfcp_scsi_dev *zfcp_sdev;
|
||||
union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual;
|
||||
|
||||
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
|
||||
return;
|
||||
|
||||
zfcp_sdev = sdev_to_zfcp(sdev);
|
||||
|
||||
switch (req->qtcb->header.fsf_status) {
|
||||
case FSF_PORT_HANDLE_NOT_VALID:
|
||||
if (fsq->word[0] == fsq->word[1]) {
|
||||
|
|
@ -885,7 +917,7 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req)
|
|||
|
||||
switch (header->fsf_status) {
|
||||
case FSF_GOOD:
|
||||
zfcp_dbf_san_res("fsscth1", req);
|
||||
zfcp_dbf_san_res("fsscth2", req);
|
||||
ct->status = 0;
|
||||
break;
|
||||
case FSF_SERVICE_CLASS_NOT_SUPPORTED:
|
||||
|
|
@ -1739,13 +1771,15 @@ static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req)
|
|||
{
|
||||
struct zfcp_adapter *adapter = req->adapter;
|
||||
struct scsi_device *sdev = req->data;
|
||||
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
|
||||
struct zfcp_scsi_dev *zfcp_sdev;
|
||||
struct fsf_qtcb_header *header = &req->qtcb->header;
|
||||
struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support;
|
||||
|
||||
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
|
||||
return;
|
||||
|
||||
zfcp_sdev = sdev_to_zfcp(sdev);
|
||||
|
||||
atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
|
||||
ZFCP_STATUS_COMMON_ACCESS_BOXED |
|
||||
ZFCP_STATUS_LUN_SHARED |
|
||||
|
|
@ -1856,11 +1890,13 @@ out:
|
|||
static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req)
|
||||
{
|
||||
struct scsi_device *sdev = req->data;
|
||||
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
|
||||
struct zfcp_scsi_dev *zfcp_sdev;
|
||||
|
||||
if (req->status & ZFCP_STATUS_FSFREQ_ERROR)
|
||||
return;
|
||||
|
||||
zfcp_sdev = sdev_to_zfcp(sdev);
|
||||
|
||||
switch (req->qtcb->header.fsf_status) {
|
||||
case FSF_PORT_HANDLE_NOT_VALID:
|
||||
zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1");
|
||||
|
|
@ -1950,7 +1986,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
|
|||
{
|
||||
struct fsf_qual_latency_info *lat_in;
|
||||
struct latency_cont *lat = NULL;
|
||||
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scsi->device);
|
||||
struct zfcp_scsi_dev *zfcp_sdev;
|
||||
struct zfcp_blk_drv_data blktrc;
|
||||
int ticks = req->adapter->timer_ticks;
|
||||
|
||||
|
|
@ -1965,6 +2001,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi)
|
|||
|
||||
if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA &&
|
||||
!(req->status & ZFCP_STATUS_FSFREQ_ERROR)) {
|
||||
zfcp_sdev = sdev_to_zfcp(scsi->device);
|
||||
blktrc.flags |= ZFCP_BLK_LAT_VALID;
|
||||
blktrc.channel_lat = lat_in->channel_lat * ticks;
|
||||
blktrc.fabric_lat = lat_in->fabric_lat * ticks;
|
||||
|
|
@ -2002,12 +2039,14 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req)
|
|||
{
|
||||
struct scsi_cmnd *scmnd = req->data;
|
||||
struct scsi_device *sdev = scmnd->device;
|
||||
struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev);
|
||||
struct zfcp_scsi_dev *zfcp_sdev;
|
||||
struct fsf_qtcb_header *header = &req->qtcb->header;
|
||||
|
||||
if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR))
|
||||
return;
|
||||
|
||||
zfcp_sdev = sdev_to_zfcp(sdev);
|
||||
|
||||
switch (header->fsf_status) {
|
||||
case FSF_HANDLE_MISMATCH:
|
||||
case FSF_PORT_HANDLE_NOT_VALID:
|
||||
|
|
|
|||
|
|
@ -102,18 +102,22 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err,
|
|||
{
|
||||
struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm;
|
||||
struct zfcp_adapter *adapter = qdio->adapter;
|
||||
struct qdio_buffer_element *sbale;
|
||||
int sbal_no, sbal_idx;
|
||||
void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1];
|
||||
u64 req_id;
|
||||
u8 scount;
|
||||
|
||||
if (unlikely(qdio_err)) {
|
||||
memset(pl, 0, ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *));
|
||||
if (zfcp_adapter_multi_buffer_active(adapter)) {
|
||||
void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1];
|
||||
struct qdio_buffer_element *sbale;
|
||||
u64 req_id;
|
||||
u8 scount;
|
||||
|
||||
memset(pl, 0,
|
||||
ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *));
|
||||
sbale = qdio->res_q[idx]->element;
|
||||
req_id = (u64) sbale->addr;
|
||||
scount = sbale->scount + 1; /* incl. signaling SBAL */
|
||||
scount = min(sbale->scount + 1,
|
||||
ZFCP_QDIO_MAX_SBALS_PER_REQ + 1);
|
||||
/* incl. signaling SBAL */
|
||||
|
||||
for (sbal_no = 0; sbal_no < scount; sbal_no++) {
|
||||
sbal_idx = (idx + sbal_no) %
|
||||
|
|
|
|||
|
|
@ -227,6 +227,8 @@ static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev,
|
|||
static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL,
|
||||
zfcp_sysfs_port_rescan_store);
|
||||
|
||||
DEFINE_MUTEX(zfcp_sysfs_port_units_mutex);
|
||||
|
||||
static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
|
|
@ -249,6 +251,16 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
|
|||
else
|
||||
retval = 0;
|
||||
|
||||
mutex_lock(&zfcp_sysfs_port_units_mutex);
|
||||
if (atomic_read(&port->units) > 0) {
|
||||
retval = -EBUSY;
|
||||
mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
||||
goto out;
|
||||
}
|
||||
/* port is about to be removed, so no more unit_add */
|
||||
atomic_set(&port->units, -1);
|
||||
mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
||||
|
||||
write_lock_irq(&adapter->port_list_lock);
|
||||
list_del(&port->list);
|
||||
write_unlock_irq(&adapter->port_list_lock);
|
||||
|
|
@ -289,12 +301,14 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
|
|||
{
|
||||
struct zfcp_port *port = container_of(dev, struct zfcp_port, dev);
|
||||
u64 fcp_lun;
|
||||
int retval;
|
||||
|
||||
if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun))
|
||||
return -EINVAL;
|
||||
|
||||
if (zfcp_unit_add(port, fcp_lun))
|
||||
return -EINVAL;
|
||||
retval = zfcp_unit_add(port, fcp_lun);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ static void zfcp_unit_release(struct device *dev)
|
|||
{
|
||||
struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev);
|
||||
|
||||
put_device(&unit->port->dev);
|
||||
atomic_dec(&unit->port->units);
|
||||
kfree(unit);
|
||||
}
|
||||
|
||||
|
|
@ -119,16 +119,27 @@ static void zfcp_unit_release(struct device *dev)
|
|||
int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
|
||||
{
|
||||
struct zfcp_unit *unit;
|
||||
int retval = 0;
|
||||
|
||||
mutex_lock(&zfcp_sysfs_port_units_mutex);
|
||||
if (atomic_read(&port->units) == -1) {
|
||||
/* port is already gone */
|
||||
retval = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
unit = zfcp_unit_find(port, fcp_lun);
|
||||
if (unit) {
|
||||
put_device(&unit->dev);
|
||||
return -EEXIST;
|
||||
retval = -EEXIST;
|
||||
goto out;
|
||||
}
|
||||
|
||||
unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL);
|
||||
if (!unit)
|
||||
return -ENOMEM;
|
||||
if (!unit) {
|
||||
retval = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
unit->port = port;
|
||||
unit->fcp_lun = fcp_lun;
|
||||
|
|
@ -139,28 +150,33 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun)
|
|||
if (dev_set_name(&unit->dev, "0x%016llx",
|
||||
(unsigned long long) fcp_lun)) {
|
||||
kfree(unit);
|
||||
return -ENOMEM;
|
||||
retval = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
get_device(&port->dev);
|
||||
|
||||
if (device_register(&unit->dev)) {
|
||||
put_device(&unit->dev);
|
||||
return -ENOMEM;
|
||||
retval = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) {
|
||||
device_unregister(&unit->dev);
|
||||
return -EINVAL;
|
||||
retval = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
atomic_inc(&port->units); /* under zfcp_sysfs_port_units_mutex ! */
|
||||
|
||||
write_lock_irq(&port->unit_list_lock);
|
||||
list_add_tail(&unit->list, &port->unit_list);
|
||||
write_unlock_irq(&port->unit_list_lock);
|
||||
|
||||
zfcp_unit_scsi_scan(unit);
|
||||
|
||||
return 0;
|
||||
out:
|
||||
mutex_unlock(&zfcp_sysfs_port_units_mutex);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue