#ifndef SCSI_TRANSPORT_SRP_H #define SCSI_TRANSPORT_SRP_H #include #include #include #define SRP_RPORT_ROLE_INITIATOR 0 #define SRP_RPORT_ROLE_TARGET 1 struct srp_rport_identifiers { u8 port_id[16]; u8 roles; }; /** * enum srp_rport_state - SRP transport layer state * @SRP_RPORT_RUNNING: Transport layer operational. * @SRP_RPORT_BLOCKED: Transport layer not operational; fast I/O fail timer * is running and I/O has been blocked. * @SRP_RPORT_FAIL_FAST: Fast I/O fail timer has expired; fail I/O fast. * @SRP_RPORT_LOST: Port is being removed. */ enum srp_rport_state { SRP_RPORT_RUNNING, SRP_RPORT_BLOCKED, SRP_RPORT_FAIL_FAST, SRP_RPORT_LOST, }; /** * struct srp_rport - SRP initiator or target port * * Fields that are relevant for SRP initiator and SRP target drivers: * @dev: Device associated with this rport. * @port_id: 16-byte port identifier. * @roles: Role of this port - initiator or target. * * Fields that are only relevant for SRP initiator drivers: * @lld_data: LLD private data. * @mutex: Protects against concurrent rport reconnect / * fast_io_fail / dev_loss_tmo activity. * @state: rport state. * @reconnect_delay: Reconnect delay in seconds. * @failed_reconnects: Number of failed reconnect attempts. * @reconnect_work: Work structure used for scheduling reconnect attempts. * @fast_io_fail_tmo: Fast I/O fail timeout in seconds. * @dev_loss_tmo: Device loss timeout in seconds. * @fast_io_fail_work: Work structure used for scheduling fast I/O fail work. * @dev_loss_work: Work structure used for scheduling device loss work. */ struct srp_rport { /* for initiator and target drivers */ struct device dev; u8 port_id[16]; u8 roles; /* for initiator drivers */ void *lld_data; struct mutex mutex; enum srp_rport_state state; int reconnect_delay; int failed_reconnects; struct delayed_work reconnect_work; int fast_io_fail_tmo; int dev_loss_tmo; struct delayed_work fast_io_fail_work; struct delayed_work dev_loss_work; }; /** * struct srp_function_template * * Fields that are only relevant for SRP initiator drivers: * @has_rport_state: Whether or not to create the state, fast_io_fail_tmo and * dev_loss_tmo sysfs attribute for an rport. * @reset_timer_if_blocked: Whether or srp_timed_out() should reset the command * timer if the device on which it has been queued is blocked. * @reconnect_delay: If not NULL, points to the default reconnect_delay value. * @fast_io_fail_tmo: If not NULL, points to the default fast_io_fail_tmo value. * @dev_loss_tmo: If not NULL, points to the default dev_loss_tmo value. * @reconnect: Callback function for reconnecting to the target. See also * srp_reconnect_rport(). * @terminate_rport_io: Callback function for terminating all outstanding I/O * requests for an rport. * @rport_delete: Callback function that deletes an rport. * * Fields that are only relevant for SRP target drivers: * @tsk_mgmt_response: Callback function for sending a task management response. * @it_nexus_response: Callback function for processing an IT nexus response. */ struct srp_function_template { /* for initiator drivers */ bool has_rport_state; bool reset_timer_if_blocked; int *reconnect_delay; int *fast_io_fail_tmo; int *dev_loss_tmo; int (*reconnect)(struct srp_rport *rport); void (*terminate_rport_io)(struct srp_rport *rport); void (*rport_delete)(struct srp_rport *rport); /* for target drivers */ int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int); int (* it_nexus_response)(struct Scsi_Host *, u64, int); }; extern struct scsi_transport_template * srp_attach_transport(struct srp_function_template *); extern void srp_release_transport(struct scsi_transport_template *); extern void srp_rport_get(struct srp_rport *rport); extern void srp_rport_put(struct srp_rport *rport); extern struct srp_rport *srp_rport_add(struct Scsi_Host *, struct srp_rport_identifiers *); extern void srp_rport_del(struct srp_rport *); extern int srp_tmo_valid(int reconnect_delay, int fast_io_fail_tmo, int dev_loss_tmo); int srp_parse_tmo(int *tmo, const char *buf); extern int srp_reconnect_rport(struct srp_rport *rport); extern void srp_start_tl_fail_timers(struct srp_rport *rport); extern void srp_remove_host(struct Scsi_Host *); extern void srp_stop_rport_timers(struct srp_rport *rport); /** * srp_chkready() - evaluate the transport layer state before I/O * @rport: SRP target port pointer. * * Returns a SCSI result code that can be returned by the LLD queuecommand() * implementation. The role of this function is similar to that of * fc_remote_port_chkready(). */ static inline int srp_chkready(struct srp_rport *rport) { switch (rport->state) { case SRP_RPORT_RUNNING: case SRP_RPORT_BLOCKED: default: return 0; case SRP_RPORT_FAIL_FAST: return DID_TRANSPORT_FAILFAST << 16; case SRP_RPORT_LOST: return DID_NO_CONNECT << 16; } } #endif ndings/clock/rk3066a-cru.h?id=91539eb1fda2d530d3b268eef542c5414e54bf1a'>91539eb1fda2d530d3b268eef542c5414e54bf1a (patch) tree960f5ca6342ad20837aff18aad6e8ecd7da32fd6 /include/dt-bindings/clock/rk3066a-cru.h parent6610d0edf6dc7ee97e46ab3a538a565c79d26199 (diff)
dmaengine: pl330: fix double lock
The static bug finder EBA (http://www.iagoabal.eu/eba/) reported the following double-lock bug: Double lock: 1. spin_lock_irqsave(pch->lock, flags) at pl330_free_chan_resources:2236; 2. call to function `pl330_release_channel' immediately after; 3. call to function `dma_pl330_rqcb' in line 1753; 4. spin_lock_irqsave(pch->lock, flags) at dma_pl330_rqcb:1505. I have fixed it as suggested by Marek Szyprowski. First, I have replaced `pch->lock' with `pl330->lock' in functions `pl330_alloc_chan_resources' and `pl330_free_chan_resources'. This avoids the double-lock by acquiring a different lock than `dma_pl330_rqcb'. NOTE that, as a result, `pl330_free_chan_resources' executes `list_splice_tail_init' on `pch->work_list' under lock `pl330->lock', whereas in the rest of the code `pch->work_list' is protected by `pch->lock'. I don't know if this may cause race conditions. Similarly `pch->cyclic' is written by `pl330_alloc_chan_resources' under `pl330->lock' but read by `pl330_tx_submit' under `pch->lock'. Second, I have removed locking from `pl330_request_channel' and `pl330_release_channel' functions. Function `pl330_request_channel' is only called from `pl330_alloc_chan_resources', so the lock is already held. Function `pl330_release_channel' is called from `pl330_free_chan_resources', which already holds the lock, and from `pl330_del'. Function `pl330_del' is called in an error path of `pl330_probe' and at the end of `pl330_remove', but I assume that there cannot be concurrent accesses to the protected data at those points. Signed-off-by: Iago Abal <mail@iagoabal.eu> Reviewed-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'include/dt-bindings/clock/rk3066a-cru.h')