zfcp updates for 2.6.36 merge window
Subsystems (4)
cover zfcp updates for 2.6.36 merge window
James,
here is the series of zfcp updates for the 2.6.36 merge window. The changes include code simplifications, cleanup, FC transport events, experimental DIF/DIX support and logging improvements on errors.
The patches apply cleanly on top of the last series of fixes, i sent last week:
http://marc.info/?l=linux-scsi&m=127857607617662&w=2
The last patch in the series "zfcp: Trigger logging in the FCP channel on qdio error conditions" depends on the patch "[S390] cio: CHSC SIOSL Support" that is already part of the linux-next tree:
http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git;a=commit;h=c5a0bc55f25e0002aaed211aef533e86c9aaff2a
Christof
PATCH 1/10 zfcp: Use memdup_user and kstrdup
From: Christof Schmitt <[email protected]>
Use the functions memdup_user and kstrdup to allocate memory and copy the data in one step, saving some lines of code.
---
drivers/s390/scsi/zfcp_aux.c | 4 +--- drivers/s390/scsi/zfcp_cfdc.c | 12 +++--------- 2 files changed, 4 insertions(+), 12 deletions(-)
drivers/s390/scsi/zfcp_aux.c +1 -3
@@ -98,13 +98,11 @@ static void __init zfcp_init_device_setuu64 wwpn, lun;/* duplicate devstr and keep the original for sysfs presentation*/ - str_saved =kmalloc (strlen (devstr) +1 ,GFP_KERNEL ); + str_saved =kstrdup (devstr,GFP_KERNEL ); str = str_saved;if (!str)return ; -strcpy (str, devstr); - token =strsep (&str,"," );if (!token ||strlen (token) >=ZFCP_BUS_ID_SIZE ) goto err_out;
drivers/s390/scsi/zfcp_cfdc.c +3 -9
@@ -189,18 +189,12 @@ static long zfcp_cfdc_dev_ioctl(struct fif (!fsf_cfdc)return -ENOMEM ; - data =kmalloc (sizeof (struct zfcp_cfdc_data ),GFP_KERNEL ); -if (!data) { - retval = -ENOMEM ; + data =memdup_user (data_user,sizeof (*data_user)); +if (IS_ERR (data)) { + retval =PTR_ERR (data); goto no_mem_sense; } - retval =copy_from_user (data, data_user,sizeof (*data)); -if (retval) { - retval = -EFAULT ; - goto free_buffer; - } -if (data->signature !=0xCFDCACDF ) { retval = -EINVAL ; goto free_buffer;
PATCH 2/10 zfcp: Remove SCSI device when removing unit
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
Configuring a LUN in zfcp, also creates a SCSI device. For consistency, it makes sense to remove the SCSI device when the LUN is deconfigured. Replace the flush_work with the call toscsi_remove_device: scsi_remove_device also takes the scan_mutex that synchronizes itself with any long running device discovery.
---
drivers/s390/scsi/zfcp_def.h | 1 + drivers/s390/scsi/zfcp_scsi.c | 1 + drivers/s390/scsi/zfcp_sysfs.c | 10 ++++++++-- 3 files changed, 10 insertions(+), 2 deletions(-)
drivers/s390/scsi/zfcp_def.h +1 -0
@@ -212,6 +212,7 @@ struct zfcp_port {struct work_struct test_link_work;struct work_struct rport_work;enum {RPORT_NONE ,RPORT_ADD ,RPORT_DEL } rport_task; +unsigned int starget_id; };struct zfcp_unit {
drivers/s390/scsi/zfcp_scsi.c +1 -0
@@ -564,6 +564,7 @@ static void zfcp_scsi_rport_register(str rport->maxframe_size = port->maxframe_size; rport->supported_classes = port->supported_classes; port->rport = rport; + port->starget_id = rport->scsi_target_id;zfcp_scsi_queue_unit_register (port); }
drivers/s390/scsi/zfcp_sysfs.c +8 -2
@@ -290,6 +290,7 @@ static ssize_t zfcp_sysfs_unit_remove_ststruct zfcp_unit *unit;u64 fcp_lun;int retval = -EINVAL ; +struct scsi_device *sdev;if (!(port &&get_device (&port->dev)))return -EBUSY ;
@@ -303,8 +304,13 @@ static ssize_t zfcp_sysfs_unit_remove_stelse retval =0 ; -/* wait for possible timeout during SCSI probe */ -flush_work (&unit->scsi_work); + sdev =scsi_device_lookup (port->adapter->scsi_host,0 , + port->starget_id, +scsilun_to_int ((struct scsi_lun *)&fcp_lun)); +if (sdev) { +scsi_remove_device (sdev); +scsi_device_put (sdev); + }write_lock_irq (&port->unit_list_lock);list_del (&unit->list);
Re: [patch 02/10] zfcp: Remove SCSI device when removing unit
Quoted 8 lines · Christof Schmitt
plain text document attachment (705-zfcp-unit-removal.diff)
From: Christof Schmitt <[email protected]>Configuring a LUN in zfcp, also creates a SCSI device. For consistency, it makes sense to remove the SCSI device when the LUN is deconfigured. Replace the
flush_workwith the call toscsi_remove_device:scsi_remove_devicealso takes thescan_mutexthat synchronizes itself with any long running device discovery.
This one's rejecting:
jejb@mulgrave:~/git/scsi-misc-2.6> patch -p1 < ~/tmp/tmp/02 patching file drivers/s390/scsi/zfcp_def.h patching file drivers/s390/scsi/zfcp_scsi.c
Hunk #1 FAILED at 564.
1 out of 1 hunk FAILED -- saving rejects to file drivers/s390/scsi/zfcp_scsi.c.rej
It looks like a missing patch somewhere.
Could you check the current state of scsi-misc-2.6 (it includes scsi-rc-fixes-2.6) and see if I've lost something?
Thanks,
James
Re: [patch 02/10] zfcp: Remove SCSI device when removing unit
Quoted 19 lines · James Bottomley
Quoted 8 lines · Christof Schmitt
plain text document attachment (705-zfcp-unit-removal.diff)
From: Christof Schmitt <[email protected]>Configuring a LUN in zfcp, also creates a SCSI device. For consistency, it makes sense to remove the SCSI device when the LUN is deconfigured. Replace the
flush_workwith the call toscsi_remove_device:scsi_remove_devicealso takes thescan_mutexthat synchronizes itself with any long running device discovery.This one's rejecting:
jejb@mulgrave:~/git/scsi-misc-2.6> patch -p1 < ~/tmp/tmp/02 patching file
drivers/s390/scsi/zfcp_def.hpatching filedrivers/s390/scsi/zfcp_scsi.c
Hunk #1 FAILED at 564.
1 out of 1 hunk FAILED -- saving rejects to filedrivers/s390/scsi/zfcp_scsi.c.rej
Quoted 4 lines
It looks like a missing patch somewhere.
Could you check the current state of scsi-misc-2.6 (it includes scsi-rc-fixes-2.6) and see if I've lost something?
scsi-misc and scsi-rc-fixes have the three fixes i sent for 2.6.35. I sent them again with six additional fixes here:
http://marc.info/?l=linux-scsi&m=127857607617662&w=2
The six additional patches are missing and this seems to cause the reject. On top of scsi-misc, these patches apply cleanly in this order:
From http://marc.info/?l=linux-scsi&m=127857607617662&w=2
zfcp: Do not unblock rport from REOPEN_PORT_FORCED
zfcp: Do not try "forced close" when port is already closed
zfcp: Register SCSI devices after successful fc_remote_port_add
zfcp: Use forced_reopen in terminate_rport_io callback
zfcp: Fail erp after timeout
zfcp: Fix retry after failed "open port" erp action
From http://marc.info/?l=linux-scsi&m=127928780100336&w=2
zfcp: Use memdup_user and kstrdup
zfcp: Remove SCSI device when removing unit
zfcp: Use correct width for timer_interval field
zfcp: Cleanup function parameters for sbal value.
zfcp: Cleanup QDIO attachment and improve processing.
zfcp: Post events through FC transport class
zfcp: Prevent access on uninitialized memory.
zfcp: Enable data division support for FCP devices
zfcp: Introduce experimental support for DIF/DIX
zfcp: Trigger logging in the FCP channel on qdio error conditions
I can also resend them in one series if this makes things easier.
Christof
PATCH 3/10 zfcp: Use correct width for timer_interval field
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
The timer_interval is 14 bits in width. Introduce a define for properly masking the value.
---
drivers/s390/scsi/zfcp_fsf.c | 2 +- drivers/s390/scsi/zfcp_fsf.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-)
drivers/s390/scsi/zfcp_fsf.c +1 -1
@@ -495,7 +495,7 @@ static int zfcp_fsf_exchange_config_evalfc_host_supported_classes (shost) =FC_COS_CLASS2 |FC_COS_CLASS3 ; adapter->hydra_version = bottom->adapter_type; - adapter->timer_ticks = bottom->timer_interval; + adapter->timer_ticks = bottom->timer_interval &ZFCP_FSF_TIMER_INT_MASK ; adapter->stat_read_buf_num =max (bottom->status_read_buf_num, (u16 )FSF_STATUS_READS_RECOM );
drivers/s390/scsi/zfcp_fsf.h +2 -0
@@ -352,6 +352,8 @@ struct fsf_qtcb_bottom_support {u8 els[256 ]; } __attribute__ ((packed)); +#define ZFCP_FSF_TIMER_INT_MASK 0x3FFF +struct fsf_qtcb_bottom_config {u32 lic_version;u32 feature_selection;
PATCH 4/10 zfcp: Cleanup function parameters for sbal value.
In reply to Christof SchmittFrom: Swen Schillig <[email protected]>
A lot of functions require the amount of SBALs as one of their parameter which is most times invariable. Therefore remove this parameter and set the SBAL value explicitly if a non standard value is required. In addition the warning message "oversized data" is replaced with a BUG_ON() statement assuring the limits defined and requested by zfcp.
---
drivers/s390/scsi/zfcp_ext.h | 2 +- drivers/s390/scsi/zfcp_fsf.c | 40 ++++++++++++++-------------------------- drivers/s390/scsi/zfcp_fsf.h | 8 -------- drivers/s390/scsi/zfcp_qdio.c | 15 ++------------- drivers/s390/scsi/zfcp_qdio.h | 28 ++++++++++++++++++++++++++++ drivers/s390/scsi/zfcp_scsi.c | 4 ++-- 6 files changed, 47 insertions(+), 50 deletions(-)
drivers/s390/scsi/zfcp_ext.h +1 -1
@@ -146,7 +146,7 @@ extern void zfcp_qdio_destroy(struct zfcextern int zfcp_qdio_sbal_get (struct zfcp_qdio *);extern int zfcp_qdio_send (struct zfcp_qdio *,struct zfcp_qdio_req *);extern int zfcp_qdio_sbals_from_sg (struct zfcp_qdio *,struct zfcp_qdio_req *, -struct scatterlist *,int ); +struct scatterlist *);extern int zfcp_qdio_open (struct zfcp_qdio *);extern void zfcp_qdio_close (struct zfcp_qdio *);
drivers/s390/scsi/zfcp_fsf.c +14 -26
@@ -959,8 +959,7 @@ static void zfcp_fsf_setup_ct_els_unchaistatic int zfcp_fsf_setup_ct_els_sbals (struct zfcp_fsf_req *req,struct scatterlist *sg_req, -struct scatterlist *sg_resp, -int max_sbals) +struct scatterlist *sg_resp) {struct zfcp_adapter *adapter = req->adapter;u32 feat = adapter->adapter_features;
@@ -983,15 +982,14 @@ static int zfcp_fsf_setup_ct_els_sbals(sreturn 0 ; } - bytes =zfcp_qdio_sbals_from_sg (adapter->qdio, &req->qdio_req, - sg_req, max_sbals); + bytes =zfcp_qdio_sbals_from_sg (adapter->qdio, &req->qdio_req, sg_req);if (bytes <=0 )return -EIO ; req->qtcb->bottom.support.req_buf_length = bytes;zfcp_qdio_skip_to_last_sbale (&req->qdio_req); bytes =zfcp_qdio_sbals_from_sg (adapter->qdio, &req->qdio_req, - sg_resp, max_sbals); + sg_resp); req->qtcb->bottom.support.resp_buf_length = bytes;if (bytes <=0 )return -EIO ;
@@ -1002,11 +1000,11 @@ static int zfcp_fsf_setup_ct_els_sbals(sstatic int zfcp_fsf_setup_ct_els (struct zfcp_fsf_req *req,struct scatterlist *sg_req,struct scatterlist *sg_resp, -int max_sbals,unsigned int timeout) +unsigned int timeout) {int ret; - ret =zfcp_fsf_setup_ct_els_sbals (req, sg_req, sg_resp, max_sbals); + ret =zfcp_fsf_setup_ct_els_sbals (req, sg_req, sg_resp);if (ret)return ret;
@@ -1046,8 +1044,7 @@ int zfcp_fsf_send_ct(struct zfcp_fc_wka_ } req->status |=ZFCP_STATUS_FSFREQ_CLEANUP ; - ret =zfcp_fsf_setup_ct_els (req, ct->req, ct->resp, -ZFCP_FSF_MAX_SBALS_PER_REQ , timeout); + ret =zfcp_fsf_setup_ct_els (req, ct->req, ct->resp, timeout);if (ret) goto failed_send;
@@ -1143,7 +1140,10 @@ int zfcp_fsf_send_els(struct zfcp_adapte } req->status |=ZFCP_STATUS_FSFREQ_CLEANUP ; - ret =zfcp_fsf_setup_ct_els (req, els->req, els->resp,2 , timeout); + +zfcp_qdio_sbal_limit (qdio, &req->qdio_req,2 ); + + ret =zfcp_fsf_setup_ct_els (req, els->req, els->resp, timeout);if (ret) goto failed_send;
@@ -2259,20 +2259,9 @@ int zfcp_fsf_send_fcp_command_task(struczfcp_fc_scsi_to_fcp (fcp_cmnd, scsi_cmnd); real_bytes =zfcp_qdio_sbals_from_sg (qdio, &req->qdio_req, -scsi_sglist (scsi_cmnd), -ZFCP_FSF_MAX_SBALS_PER_REQ ); -if (unlikely (real_bytes <0 )) { -if (req->qdio_req.sbal_number >=ZFCP_FSF_MAX_SBALS_PER_REQ ) { -dev_err (&adapter->ccw_device->dev, -"Oversize data package, unit 0x%016Lx " -"on port 0x%016Lx closed\n" , - (unsigned long long )unit->fcp_lun, - (unsigned long long )unit->port->wwpn); -zfcp_erp_unit_shutdown (unit,0 ,"fssfct1" , req); - retval = -EINVAL ; - } +scsi_sglist (scsi_cmnd)); +if (unlikely (real_bytes <0 )) goto failed_scsi_cmnd; - } retval =zfcp_fsf_req_send (req);if (unlikely (retval))
@@ -2391,9 +2380,8 @@ struct zfcp_fsf_req *zfcp_fsf_control_fi bottom->operation_subtype =FSF_CFDC_OPERATION_SUBTYPE ; bottom->option = fsf_cfdc->option; - bytes =zfcp_qdio_sbals_from_sg (qdio, &req->qdio_req, - fsf_cfdc->sg, -ZFCP_FSF_MAX_SBALS_PER_REQ ); + bytes =zfcp_qdio_sbals_from_sg (qdio, &req->qdio_req, fsf_cfdc->sg); +if (bytes !=ZFCP_CFDC_MAX_SIZE ) {zfcp_fsf_req_free (req); goto out;
drivers/s390/scsi/zfcp_fsf.h +0 -8
@@ -151,14 +151,6 @@/* fc service class */ #define FSF_CLASS_3 0x00000003 -/* SBAL chaining */ -#define ZFCP_FSF_MAX_SBALS_PER_REQ 36 - -/* max. number of (data buffer) SBALEs in largest SBAL chain -* request ID + QTCB in SBALE 0 + 1 of first SBAL in chain */ -#define ZFCP_FSF_MAX_SBALES_PER_REQ \ - (ZFCP_FSF_MAX_SBALS_PER_REQ * ZFCP_QDIO_MAX_SBALES_PER_SBAL - 2) -/* logging space behind QTCB */ #define FSF_QTCB_LOG_SIZE 1024
drivers/s390/scsi/zfcp_qdio.c +2 -13
@@ -141,15 +141,6 @@ static void zfcp_qdio_int_resp(struct cczfcp_qdio_resp_put_back (qdio, count); } -static void zfcp_qdio_sbal_limit (struct zfcp_qdio *qdio, -struct zfcp_qdio_req *q_req,int max_sbals) -{ -int count =atomic_read (&qdio->req_q.count); - count =min (count, max_sbals); - q_req->sbal_limit = (q_req->sbal_first + count -1 ) - %QDIO_MAX_BUFFERS_PER_Q ; -} -static struct qdio_buffer_element *zfcp_qdio_sbal_chain (struct zfcp_qdio *qdio,struct zfcp_qdio_req *q_req) {
@@ -173,6 +164,7 @@ zfcp_qdio_sbal_chain(struct zfcp_qdio *q/* keep this requests number of SBALs up-to-date */ q_req->sbal_number++; +BUG_ON (q_req->sbal_number >ZFCP_QDIO_MAX_SBALS_PER_REQ );/* start at first SBALE of new SBAL */ q_req->sbale_curr =0 ;
@@ -213,14 +205,11 @@ static void zfcp_qdio_undo_sbals(struct* Returns: number of bytes, or error (negativ) */ int zfcp_qdio_sbals_from_sg (struct zfcp_qdio *qdio,struct zfcp_qdio_req *q_req, -struct scatterlist *sg,int max_sbals) +struct scatterlist *sg) {struct qdio_buffer_element *sbale;int bytes =0 ; -/* figure out last allowed SBAL */ -zfcp_qdio_sbal_limit (qdio, q_req, max_sbals); -/* set storage-block type for this request */ sbale =zfcp_qdio_sbale_req (qdio, q_req); sbale->flags |= q_req->sbtype;
drivers/s390/scsi/zfcp_qdio.h +28 -0
@@ -19,6 +19,14 @@/* index of last SBALE (with respect to DMQ bug workaround) */ #define ZFCP_QDIO_LAST_SBALE_PER_SBAL (ZFCP_QDIO_MAX_SBALES_PER_SBAL - 1) +/* Max SBALS for chaining */ +#define ZFCP_QDIO_MAX_SBALS_PER_REQ 36 + +/* max. number of (data buffer) SBALEs in largest SBAL chain +* request ID + QTCB in SBALE 0 + 1 of first SBAL in chain */ +#define ZFCP_QDIO_MAX_SBALES_PER_REQ \ + (ZFCP_QDIO_MAX_SBALS_PER_REQ * ZFCP_QDIO_MAX_SBALES_PER_SBAL - 2) +/** * struct zfcp_qdio_queue - qdio queue buffer, zfcp index and free count * @sbal: qdio buffers
@@ -134,10 +142,14 @@ void zfcp_qdio_req_init(struct zfcp_qdio unsigned long req_id, u32 sbtype, void *data, u32 len) { struct qdio_buffer_element *sbale; +int count =min (atomic_read (&qdio->req_q.count), +ZFCP_QDIO_MAX_SBALS_PER_REQ ); q_req->sbal_first = q_req->sbal_last = qdio->req_q.first; q_req->sbal_number =1 ; q_req->sbtype = sbtype; + q_req->sbal_limit = (q_req->sbal_first + count -1 ) + %QDIO_MAX_BUFFERS_PER_Q ; sbale =zfcp_qdio_sbale_req (qdio, q_req); sbale->addr = (void *) req_id;
@@ -210,4 +222,20 @@ void zfcp_qdio_skip_to_last_sbale(struct q_req->sbale_curr = ZFCP_QDIO_LAST_SBALE_PER_SBAL; } +/** +* zfcp_qdio_sbal_limit - set the sbal limit for a request in q_req +* @qdio: pointer to struct zfcp_qdio +* @q_req: The current zfcp_qdio_req +* @max_sbals: maximum number of SBALs allowed +*/ +static inline +void zfcp_qdio_sbal_limit (struct zfcp_qdio *qdio, +struct zfcp_qdio_req *q_req,int max_sbals) +{ +int count =min (atomic_read (&qdio->req_q.count), max_sbals); + + q_req->sbal_limit = (q_req->sbal_first + count -1 ) % +QDIO_MAX_BUFFERS_PER_Q ; +} +#endif /* ZFCP_QDIO_H */
drivers/s390/scsi/zfcp_scsi.c +2 -2
@@ -701,11 +701,11 @@ struct zfcp_data zfcp_data = { .eh_host_reset_handler = zfcp_scsi_eh_host_reset_handler, .can_queue = 4096, .this_id = -1, - .sg_tablesize = ZFCP_FSF_MAX_SBALES_PER_REQ, + .sg_tablesize = ZFCP_QDIO_MAX_SBALES_PER_REQ, .cmd_per_lun = 1, .use_clustering = 1, .sdev_attrs = zfcp_sysfs_sdev_attrs, - .max_sectors = (ZFCP_FSF_MAX_SBALES_PER_REQ * 8), + .max_sectors = (ZFCP_QDIO_MAX_SBALES_PER_REQ * 8), .dma_boundary = ZFCP_QDIO_SBALE_LEN - 1, .shost_attrs = zfcp_sysfs_shost_attrs, },
PATCH 5/10 zfcp: Cleanup QDIO attachment and improve processing.
In reply to Christof SchmittFrom: Swen Schillig <[email protected]>
Some definitions and structures in the zfcp QDIO processing are improved by the removal of not required variables and processing steps. I addition the naming of some variables is changed to make their purpose more clear.
---
drivers/s390/scsi/zfcp_fsf.c | 10 +- drivers/s390/scsi/zfcp_qdio.c | 141 ++++++++++++++---------------------------- drivers/s390/scsi/zfcp_qdio.h | 57 +++++----------- 3 files changed, 69 insertions(+), 139 deletions(-)
drivers/s390/scsi/zfcp_fsf.c +4 -6
@@ -732,7 +732,7 @@ static int zfcp_fsf_req_send(struct zfcpzfcp_reqlist_add (adapter->req_list, req); - req->qdio_req.qdio_outb_usage =atomic_read (&qdio->req_q.count); + req->qdio_req.qdio_outb_usage =atomic_read (&qdio->req_q_free); req->issued =get_clock ();if (zfcp_qdio_send (qdio, &req->qdio_req)) {del_timer (&req->timer);
@@ -2025,7 +2025,7 @@ static void zfcp_fsf_req_trace(struct zf blktrc.magic =ZFCP_BLK_DRV_DATA_MAGIC ;if (req->status &ZFCP_STATUS_FSFREQ_ERROR ) blktrc.flags |=ZFCP_BLK_REQ_ERROR ; - blktrc.inb_usage = req->qdio_req.qdio_inb_usage; + blktrc.inb_usage =0 ; blktrc.outb_usage = req->qdio_req.qdio_outb_usage; if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA &&
@@ -2207,7 +2207,7 @@ int zfcp_fsf_send_fcp_command_task(strucreturn -EBUSY ;spin_lock (&qdio->req_q_lock); -if (atomic_read (&qdio->req_q.count) <=0 ) { +if (atomic_read (&qdio->req_q_free) <=0 ) {atomic_inc (&qdio->req_q_full); goto out; }
@@ -2407,7 +2407,7 @@ out:void zfcp_fsf_reqid_check (struct zfcp_qdio *qdio,int sbal_idx) {struct zfcp_adapter *adapter = qdio->adapter; -struct qdio_buffer *sbal = qdio->resp_q.sbal[sbal_idx]; +struct qdio_buffer *sbal = qdio->res_q[sbal_idx];struct qdio_buffer_element *sbale;struct zfcp_fsf_req *fsf_req;unsigned long req_id;
@@ -2428,8 +2428,6 @@ void zfcp_fsf_reqid_check(struct zfcp_qd req_id, dev_name(&adapter->ccw_device->dev)); fsf_req->qdio_req.sbal_response = sbal_idx; - fsf_req->qdio_req.qdio_inb_usage = -atomic_read (&qdio->resp_q.count);zfcp_fsf_req_complete (fsf_req);if (likely (sbale->flags &SBAL_FLAGS_LAST_ENTRY ))
drivers/s390/scsi/zfcp_qdio.c +48 -93
292 lines not on this page · raw message
drivers/s390/scsi/zfcp_qdio.h +17 -40
122 lines not on this page · raw message
PATCH 6/10 zfcp: Post events through FC transport class
In reply to Christof SchmittFrom: Sven Schuetz <[email protected]>
Post FC transport class netlink events for usage in the userspace, e.g. for HBAAPI. Supported events are those required for the polled events in HBAAPI.
- link up
- link down
- incoming RSCN
(events related to FC-AL are not supported, as zfcp has no support for FC-AL)
---
drivers/s390/scsi/zfcp_aux.c | 4 +++ drivers/s390/scsi/zfcp_def.h | 2 + drivers/s390/scsi/zfcp_ext.h | 3 ++ drivers/s390/scsi/zfcp_fc.c | 54 +++++++++++++++++++++++++++++++++++++++++++ drivers/s390/scsi/zfcp_fc.h | 24 +++++++++++++++++++ drivers/s390/scsi/zfcp_fsf.c | 3 ++ 6 files changed, 90 insertions(+)
drivers/s390/scsi/zfcp_aux.c +4 -0
@@ -524,6 +524,10 @@ struct zfcp_adapter *zfcp_adapter_enqueurwlock_init (&adapter->port_list_lock);INIT_LIST_HEAD (&adapter->port_list); +INIT_LIST_HEAD (&adapter->events.list); +INIT_WORK (&adapter->events.work, zfcp_fc_post_event); +spin_lock_init (&adapter->events.list_lock); +init_waitqueue_head (&adapter->erp_ready_wq);init_waitqueue_head (&adapter->erp_done_wqh);
drivers/s390/scsi/zfcp_def.h +2 -0
@@ -37,6 +37,7 @@#include <asm/ebcdic.h> #include <asm/sysinfo.h> #include "zfcp_fsf.h" +#include "zfcp_fc.h" #include "zfcp_qdio.h" struct zfcp_reqlist ;
@@ -190,6 +191,7 @@ struct zfcp_adapter {struct service_level service_level;struct workqueue_struct *work_queue;struct device_dma_parameters dma_parms; +struct zfcp_fc_events events; };struct zfcp_port {
drivers/s390/scsi/zfcp_ext.h +3 -0
@@ -96,6 +96,9 @@ extern void zfcp_erp_adapter_access_chanextern void zfcp_erp_timeout_handler (unsigned long );/* zfcp_fc.c */ +extern void zfcp_fc_enqueue_event (struct zfcp_adapter *, +enum fc_host_event_code event_code,u32 ); +extern void zfcp_fc_post_event (struct work_struct *);extern void zfcp_fc_scan_ports (struct work_struct *);extern void zfcp_fc_incoming_els (struct zfcp_fsf_req *);extern void zfcp_fc_port_did_lookup (struct work_struct *);
drivers/s390/scsi/zfcp_fc.c +54 -0
66 lines not on this page · raw message
drivers/s390/scsi/zfcp_fc.h +24 -0
@@ -30,6 +30,30 @@#define ZFCP_FC_CTELS_TMO (2 * FC_DEF_R_A_TOV / 1000)/** +* struct zfcp_fc_event - FC HBAAPI event for internal queueing from irq context +* @code: Event code +* @data: Event data +* @list: list_head for zfcp_fc_events list +*/ +struct zfcp_fc_event { +enum fc_host_event_code code; +u32 data; +struct list_head list; +}; + +/** +* struct zfcp_fc_events - Infrastructure for posting FC events from irq context +* @list: List for queueing of events from irq context to workqueue +* @list_lock: Lock for event list +* @work: work_struct for forwarding events in workqueue +*/ +struct zfcp_fc_events { +struct list_head list; +spinlock_t list_lock; +struct work_struct work; +}; + +/** * struct zfcp_fc_gid_pn_req - container for ct header plus gid_pn request * @ct_hdr: FC GS common transport header * @gid_pn: GID_PN request
drivers/s390/scsi/zfcp_fsf.c +3 -0
@@ -274,6 +274,7 @@ static void zfcp_fsf_status_read_handlerbreak ;case FSF_STATUS_READ_LINK_DOWN :zfcp_fsf_status_read_link_down (req); +zfcp_fc_enqueue_event (adapter,FCH_EVT_LINKDOWN ,0 );break ;case FSF_STATUS_READ_LINK_UP : dev_info(&adapter->ccw_device->dev,
@@ -286,6 +287,8 @@ static void zfcp_fsf_status_read_handlerZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |ZFCP_STATUS_COMMON_ERP_FAILED , "fssrh_2", req); +zfcp_fc_enqueue_event (adapter,FCH_EVT_LINKUP ,0 ); +break ;case FSF_STATUS_READ_NOTIFICATION_LOST :if (sr_buf->status_subtype &FSF_STATUS_READ_SUB_ACT_UPDATED )
PATCH 7/10 zfcp: Prevent access on uninitialized memory.
In reply to Christof SchmittFrom: Swen Schillig <[email protected]>
Initialize allocated memory to zero to prevent access on error. This prevents a possible error in the error handling path.
---
drivers/s390/scsi/zfcp_dbf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/s390/scsi/zfcp_dbf.c +1 -1
@@ -1005,7 +1005,7 @@ int zfcp_dbf_adapter_register(struct zfcchar dbf_name[DEBUG_MAX_NAME_LEN ];struct zfcp_dbf *dbf; - dbf =kmalloc (sizeof (struct zfcp_dbf ),GFP_KERNEL ); + dbf =kzalloc (sizeof (struct zfcp_dbf ),GFP_KERNEL );if (!dbf)return -ENOMEM ;
PATCH 8/10 zfcp: Enable data division support for FCP devices
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
Try to enable data division support for FCP devices and indicate in the adapter status flag if it succeeded.
--- arch/s390/include/asm/qdio.h | 6 ++++++ drivers/s390/cio/qdio_setup.c | 2 ++ drivers/s390/scsi/zfcp_def.h | 1 + drivers/s390/scsi/zfcp_qdio.c | 11 ++++++++++- 4 files changed, 19 insertions(+), 1 deletion(-)
arch/s390/include/asm/qdio.h +6 -0
@@ -84,6 +84,7 @@ struct qdr {#define QIB_AC_OUTBOUND_PCI_SUPPORTED 0x40#define QIB_RFLAGS_ENABLE_QEBSM 0x80 +#define QIB_RFLAGS_ENABLE_DATA_DIV 0x02/** * struct qib - queue information block (QIB)
@@ -284,6 +285,9 @@ struct slsb {u8 val[QDIO_MAX_BUFFERS_PER_Q ]; } __attribute__ ((packed, aligned(256))); +#define CHSC_AC2_DATA_DIV_AVAILABLE 0x0010 +#define CHSC_AC2_DATA_DIV_ENABLED 0x0002 +struct qdio_ssqd_desc {u8 flags; u8:8;
@@ -332,6 +336,7 @@ typedef void qdio_handler_t(struct ccw_d* @adapter_name: name for the adapter * @qib_param_field_format: format for qib_parm_field * @qib_param_field: pointer to 128 bytes or NULL, if no param field +* @qib_rflags: rflags to set * @input_slib_elements: pointer to no_input_qs * 128 words of data or NULL * @output_slib_elements: pointer to no_output_qs * 128 words of data or NULL * @no_input_qs: number of input queues
@@ -348,6 +353,7 @@ struct qdio_initialize {unsigned char adapter_name[8 ];unsigned int qib_param_field_format;unsigned char *qib_param_field; +unsigned char qib_rflags;unsigned long *input_slib_elements;unsigned long *output_slib_elements;unsigned int no_input_qs;
drivers/s390/cio/qdio_setup.c +2 -0
@@ -368,6 +368,8 @@ static void setup_qib(struct qdio_irq *iif (qebsm_possible ()) irq_ptr->qib.rflags |=QIB_RFLAGS_ENABLE_QEBSM ; + irq_ptr->qib.rflags |= init_data->qib_rflags; + irq_ptr->qib.qfmt = init_data->q_format;if (init_data->no_input_qs) irq_ptr->qib.isliba =
drivers/s390/scsi/zfcp_def.h +1 -0
@@ -77,6 +77,7 @@ struct zfcp_reqlist;#define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010#define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100#define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 +#define ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED 0x00000400/* remote port status */ #define ZFCP_STATUS_PORT_PHYS_OPEN 0x00000001
drivers/s390/scsi/zfcp_qdio.c +10 -1
@@ -283,6 +283,7 @@ static void zfcp_qdio_setup_init_data(st id->q_format =QDIO_ZFCP_QFMT ;memcpy (id->adapter_name,dev_name (&id->cdev->dev),8 );ASCEBC (id->adapter_name,8 ); + id->qib_rflags =QIB_RFLAGS_ENABLE_DATA_DIV ; id->qib_param_field_format =0 ; id->qib_param_field =NULL ; id->input_slib_elements =NULL ;
@@ -294,8 +295,8 @@ static void zfcp_qdio_setup_init_data(st id->int_parm = (unsigned long ) qdio; id->input_sbal_addr_array = (void **) (qdio->res_q); id->output_sbal_addr_array = (void **) (qdio->req_q); - } +/** * zfcp_qdio_allocate - allocate queue memory and initialize QDIO data * @adapter: pointer to struct zfcp_adapter
@@ -358,6 +359,7 @@ int zfcp_qdio_open(struct zfcp_qdio *qdistruct qdio_initialize init_data;struct zfcp_adapter *adapter = qdio->adapter;struct ccw_device *cdev = adapter->ccw_device; +struct qdio_ssqd_desc ssqd;int cc;if (atomic_read (&adapter->status) &ZFCP_STATUS_ADAPTER_QDIOUP )
@@ -368,6 +370,13 @@ int zfcp_qdio_open(struct zfcp_qdio *qdiif (qdio_establish (&init_data)) goto failed_establish; +if (qdio_get_ssqd_desc (init_data.cdev, &ssqd)) + goto failed_qdio; + +if (ssqd.qdioac2 &CHSC_AC2_DATA_DIV_ENABLED ) +atomic_set_mask (ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED , + &qdio->adapter->status); +if (qdio_activate (cdev)) goto failed_qdio;
PATCH 9/10 zfcp: Introduce experimental support for DIF/DIX
In reply to Christof SchmittFrom: Felix Beck <[email protected]>
Introduce support for DIF/DIX in zfcp: Report the capabilities for the Scsi_host, map the protection data when issuing I/O requests and handle the new error codes. Also add the fsf data_direction field to the hba trace, it is useful information for debugging in that area. This is an EXPERIMENTAL feature for now.
--- drivers/s390/scsi/zfcp_dbf.c | 3 + drivers/s390/scsi/zfcp_dbf.h | 1 drivers/s390/scsi/zfcp_ext.h | 2 drivers/s390/scsi/zfcp_fc.h | 3 + drivers/s390/scsi/zfcp_fsf.c | 109 +++++++++++++++++++++++++++++++++--------- drivers/s390/scsi/zfcp_fsf.h | 24 ++++++++- drivers/s390/scsi/zfcp_qdio.c | 4 - drivers/s390/scsi/zfcp_qdio.h | 16 ++++++ drivers/s390/scsi/zfcp_scsi.c | 53 ++++++++++++++++++++ drivers/scsi/Kconfig | 4 + 10 files changed, 189 insertions(+), 30 deletions(-)
drivers/s390/scsi/zfcp_dbf.c +3 -0
@@ -155,6 +155,8 @@ void _zfcp_dbf_hba_fsf_response(const chif (scsi_cmnd) { response->u.fcp.cmnd = (unsigned long )scsi_cmnd; response->u.fcp.serial = scsi_cmnd->serial_number; + response->u.fcp.data_dir = + qtcb->bottom.io.data_direction; }break ;
@@ -326,6 +328,7 @@ static void zfcp_dbf_hba_view_response(ccase FSF_QTCB_FCP_CMND :if (r->fsf_req_status &ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT )break ; +zfcp_dbf_out (p,"data_direction" ,"0x%04x" , r->u.fcp.data_dir);zfcp_dbf_out (p,"scsi_cmnd" ,"0x%0Lx" , r->u.fcp.cmnd);zfcp_dbf_out (p,"scsi_serial" ,"0x%016Lx" , r->u.fcp.serial); *p +=sprintf (*p,"\n" );
drivers/s390/scsi/zfcp_dbf.h +1 -0
@@ -111,6 +111,7 @@ struct zfcp_dbf_hba_record_response {struct {u64 cmnd;u64 serial; +u32 data_dir; } fcp;struct {u64 wwpn;
drivers/s390/scsi/zfcp_ext.h +2 -0
@@ -164,6 +164,8 @@ extern void zfcp_scsi_schedule_rport_bloextern void zfcp_scsi_schedule_rports_block (struct zfcp_adapter *);extern void zfcp_scsi_scan (struct zfcp_unit *);extern void zfcp_scsi_scan_work (struct work_struct *); +extern void zfcp_scsi_set_prot (struct zfcp_adapter *); +extern void zfcp_scsi_dif_sense_error (struct scsi_cmnd *,int );/* zfcp_sysfs.c */ extern struct attribute_group zfcp_sysfs_unit_attrs;
drivers/s390/scsi/zfcp_fc.h +3 -0
@@ -220,6 +220,9 @@ void zfcp_fc_scsi_to_fcp(struct fcp_cmndmemcpy (fcp->fc_cdb, scsi->cmnd, scsi->cmd_len); fcp->fc_dl =scsi_bufflen (scsi); + +if (scsi_get_prot_type (scsi) ==SCSI_PROT_DIF_TYPE1 ) + fcp->fc_dl += fcp->fc_dl / scsi->device->sector_size *8 ; }/**
drivers/s390/scsi/zfcp_fsf.c +86 -23
186 lines not on this page · raw message
drivers/s390/scsi/zfcp_fsf.h +21 -3
@@ -80,11 +80,15 @@#define FSF_REQUEST_SIZE_TOO_LARGE 0x00000061#define FSF_RESPONSE_SIZE_TOO_LARGE 0x00000062#define FSF_SBAL_MISMATCH 0x00000063 +#define FSF_INCONSISTENT_PROT_DATA 0x00000070 +#define FSF_INVALID_PROT_PARM 0x00000071 +#define FSF_BLOCK_GUARD_CHECK_FAILURE 0x00000081 +#define FSF_APP_TAG_CHECK_FAILURE 0x00000082 +#define FSF_REF_TAG_CHECK_FAILURE 0x00000083#define FSF_ADAPTER_STATUS_AVAILABLE 0x000000AD#define FSF_UNKNOWN_COMMAND 0x000000E2#define FSF_UNKNOWN_OP_SUBTYPE 0x000000E3#define FSF_INVALID_COMMAND_OPTION 0x000000E5 -/* #define FSF_ERROR 0x000000FF */ #define FSF_PROT_STATUS_QUAL_SIZE 16#define FSF_STATUS_QUALIFIER_SIZE 16
@@ -147,6 +151,13 @@#define FSF_DATADIR_WRITE 0x00000001#define FSF_DATADIR_READ 0x00000002#define FSF_DATADIR_CMND 0x00000004 +#define FSF_DATADIR_DIF_WRITE_INSERT 0x00000009 +#define FSF_DATADIR_DIF_READ_STRIP 0x0000000a +#define FSF_DATADIR_DIF_WRITE_CONVERT 0x0000000b +#define FSF_DATADIR_DIF_READ_CONVERT 0X0000000c + +/* data protection control flags */ +#define FSF_APP_TAG_CHECK_ENABLE 0x10/* fc service class */ #define FSF_CLASS_3 0x00000003
@@ -162,6 +173,8 @@#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020#define FSF_FEATURE_UPDATE_ALERT 0x00000100#define FSF_FEATURE_MEASUREMENT_DATA 0x00000200 +#define FSF_FEATURE_DIF_PROT_TYPE1 0x00010000 +#define FSF_FEATURE_DIX_PROT_TCPIP 0x00020000/* host connection features */ #define FSF_FEATURE_NPIV_MODE 0x00000001
@@ -316,9 +329,14 @@ struct fsf_qtcb_header {struct fsf_qtcb_bottom_io {u32 data_direction;u32 service_class; -u8 res1[8 ]; +u8 res1; +u8 data_prot_flags; +u16 app_tag_value; +u32 ref_tag_value;u32 fcp_cmnd_length; -u8 res2[12 ]; +u32 data_block_length; +u32 prot_data_length; +u8 res2[4 ];u8 fcp_cmnd[FSF_FCP_CMND_SIZE ];u8 fcp_rsp[FSF_FCP_RSP_SIZE ];u8 res3[64 ];
drivers/s390/scsi/zfcp_qdio.c +0 -4
@@ -193,10 +193,6 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_ bytes += sg->length; } -/* assume that no other SBALEs are to follow in the same SBAL */ - sbale =zfcp_qdio_sbale_curr (qdio, q_req); - sbale->flags |=SBAL_FLAGS_LAST_ENTRY ; -return bytes; }
drivers/s390/scsi/zfcp_qdio.h +16 -0
@@ -215,4 +215,20 @@ void zfcp_qdio_sbal_limit(struct zfcp_qd QDIO_MAX_BUFFERS_PER_Q; } +/** +* zfcp_qdio_set_data_div - set data division count +* @qdio: pointer to struct zfcp_qdio +* @q_req: The current zfcp_qdio_req +* @count: The data division count +*/ +static inline +void zfcp_qdio_set_data_div (struct zfcp_qdio *qdio, +struct zfcp_qdio_req *q_req,u32 count) +{ +struct qdio_buffer_element *sbale; + + sbale = &qdio->req_q[q_req->sbal_first]->element[0 ]; + sbale->length = count; +} +#endif /* ZFCP_QDIO_H */
drivers/s390/scsi/zfcp_scsi.c +53 -0
71 lines not on this page · raw message
drivers/scsi/Kconfig +4 -0
@@ -1847,6 +1847,10 @@ config ZFCP called zfcp. If you want to compile it as a module, say M here and read <file:Documentation/kbuild/modules.txt>. +config ZFCP_DIF + tristate "T10 DIF/DIX support for the zfcp driver (EXPERIMENTAL)" + depends on ZFCP && EXPERIMENTAL + config SCSI_PMCRAID tristate "PMC SIERRA Linux MaxRAID adapter support" depends on PCI && SCSI
PATCH 10/10 zfcp: Trigger logging in the FCP channel on qdio error conditions
In reply to Christof SchmittFrom: Christof Schmitt <[email protected]>
Exploit the cio siosl function to trigger logging in the FCP channel on qdio error conditions. Add a helper function in zfcp_qdio to ensure that tracing is only triggered once before calling qdio_shutdown.
Trigger in zfcp for hardware logs are:
- timeout for FSF requests to the FCP channel
- "no recommendation" status from FCP channel
- invalid FSF protocol status
- stalled outbound queue
- unknown request id on inbound queue
- QDIO_ERROR_SLSB_STATE
All of the above triggers run from the Linux qdio softirq context, so no additional synchronization is necessary for the handling of the ZFCP_STATUS_ADAPTER_SIOSL_ISSUED flag.
---
drivers/s390/scsi/zfcp_def.h | 1 + drivers/s390/scsi/zfcp_ext.h | 1 + drivers/s390/scsi/zfcp_fsf.c | 7 ++++++- drivers/s390/scsi/zfcp_qdio.c | 35 ++++++++++++++++++++++++++++++++--- 4 files changed, 40 insertions(+), 4 deletions(-)
drivers/s390/scsi/zfcp_def.h +1 -0
@@ -73,6 +73,7 @@ struct zfcp_reqlist;/* adapter status */ #define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002 +#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_ERP_PENDING 0x00000100
drivers/s390/scsi/zfcp_ext.h +1 -0
@@ -152,6 +152,7 @@ extern int zfcp_qdio_sbals_from_sg(struc struct scatterlist *);extern int zfcp_qdio_open (struct zfcp_qdio *);extern void zfcp_qdio_close (struct zfcp_qdio *); +extern void zfcp_qdio_siosl (struct zfcp_adapter *);/* zfcp_scsi.c */ extern struct zfcp_data zfcp_data;
drivers/s390/scsi/zfcp_fsf.c +6 -1
@@ -21,6 +21,7 @@static void zfcp_fsf_request_timeout_handler (unsigned long data) {struct zfcp_adapter *adapter = (struct zfcp_adapter *) data; +zfcp_qdio_siosl (adapter);zfcp_erp_adapter_reopen (adapter,ZFCP_STATUS_COMMON_ERP_FAILED ,"fsrth_1" ,NULL ); }
@@ -326,6 +327,7 @@ static void zfcp_fsf_fsfstatus_qual_evaldev_err (&req->adapter->ccw_device->dev,"The FCP adapter reported a problem " "that cannot be recovered\n" ); +zfcp_qdio_siosl (req->adapter);zfcp_erp_adapter_shutdown (req->adapter,0 ,"fsfsqe1" , req);break ; }
@@ -416,6 +418,7 @@ static void zfcp_fsf_protstatus_eval(strdev_err (&adapter->ccw_device->dev,"0x%x is not a valid transfer protocol status\n" , qtcb->prefix.prot_status); +zfcp_qdio_siosl (adapter);zfcp_erp_adapter_shutdown (adapter,0 ,"fspse_9" , req); } req->status |=ZFCP_STATUS_FSFREQ_ERROR ;
@@ -2485,13 +2488,15 @@ void zfcp_fsf_reqid_check(struct zfcp_qd req_id = (unsigned long ) sbale->addr; fsf_req =zfcp_reqlist_find_rm (adapter->req_list, req_id); -if (!fsf_req) +if (!fsf_req) {/* * Unknown request means that we have potentially memory * corruption and must stop the machine immediately. */ +zfcp_qdio_siosl (adapter);panic ("error: unknown req_id (%lx) on adapter %s.\n" , req_id,dev_name (&adapter->ccw_device->dev)); + } fsf_req->qdio_req.sbal_response = sbal_idx;zfcp_fsf_req_complete (fsf_req);
drivers/s390/scsi/zfcp_qdio.c +32 -3
@@ -30,12 +30,15 @@ static int zfcp_qdio_buffers_enqueue(strreturn 0 ; } -static void zfcp_qdio_handler_error (struct zfcp_qdio *qdio,char *id) +static void zfcp_qdio_handler_error (struct zfcp_qdio *qdio,char *id, +unsigned int qdio_err) {struct zfcp_adapter *adapter = qdio->adapter;dev_warn (&adapter->ccw_device->dev,"A QDIO problem occurred\n" ); +if (qdio_err &QDIO_ERROR_SLSB_STATE ) +zfcp_qdio_siosl (adapter);zfcp_erp_adapter_reopen (adapter,ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |ZFCP_STATUS_COMMON_ERP_FAILED , id,NULL );
@@ -74,7 +77,7 @@ static void zfcp_qdio_int_req(struct ccwif (unlikely (qdio_err)) {zfcp_dbf_hba_qdio (qdio->adapter->dbf, qdio_err, idx, count); -zfcp_qdio_handler_error (qdio,"qdireq1" ); +zfcp_qdio_handler_error (qdio,"qdireq1" , qdio_err);return ; }
@@ -95,7 +98,7 @@ static void zfcp_qdio_int_resp(struct ccif (unlikely (qdio_err)) {zfcp_dbf_hba_qdio (qdio->adapter->dbf, qdio_err, idx, count); -zfcp_qdio_handler_error (qdio,"qdires1" ); +zfcp_qdio_handler_error (qdio,"qdires1" , qdio_err);return ; }
@@ -361,6 +364,9 @@ int zfcp_qdio_open(struct zfcp_qdio *qdiif (atomic_read (&adapter->status) &ZFCP_STATUS_ADAPTER_QDIOUP )return -EIO ; +atomic_clear_mask (ZFCP_STATUS_ADAPTER_SIOSL_ISSUED , + &qdio->adapter->status); +zfcp_qdio_setup_init_data (&init_data, qdio);if (qdio_establish (&init_data))
@@ -440,3 +446,26 @@ int zfcp_qdio_setup(struct zfcp_adapterreturn 0 ; } +/** +* zfcp_qdio_siosl - Trigger logging in FCP channel +* @adapter: The zfcp_adapter where to trigger logging +* +* Call the cio siosl function to trigger hardware logging. This +* wrapper function sets a flag to ensure hardware logging is only +* triggered once before going through qdio shutdown. +* +* The triggers are always run from qdio tasklet context, so no +* additional synchronization is necessary. +*/ +void zfcp_qdio_siosl (struct zfcp_adapter *adapter) +{ +int rc; + +if (atomic_read (&adapter->status) &ZFCP_STATUS_ADAPTER_SIOSL_ISSUED ) +return ; + + rc =ccw_device_siosl (adapter->ccw_device); +if (!rc) +atomic_set_mask (ZFCP_STATUS_ADAPTER_SIOSL_ISSUED , + &adapter->status); +}