Commit fea9d6c7 authored by Volker Sameske's avatar Volker Sameske Committed by James Bottomley

[SCSI] zfcp: improve management of request IDs

Improve request handling. Use hash table to manage request IDs.
Signed-off-by: default avatarVolker Sameske <sameske@de.ibm.com>
Signed-off-by: default avatarAndreas Herrmann <aherrman@de.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent c2602c48
...@@ -112,6 +112,105 @@ _zfcp_hex_dump(char *addr, int count) ...@@ -112,6 +112,105 @@ _zfcp_hex_dump(char *addr, int count)
printk("\n"); printk("\n");
} }
/****************************************************************/
/****** Functions to handle the request ID hash table ********/
/****************************************************************/
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_FSF
static int zfcp_reqlist_init(struct zfcp_adapter *adapter)
{
int i;
adapter->req_list = kcalloc(REQUEST_LIST_SIZE, sizeof(struct list_head),
GFP_KERNEL);
if (!adapter->req_list)
return -ENOMEM;
for (i=0; i<REQUEST_LIST_SIZE; i++)
INIT_LIST_HEAD(&adapter->req_list[i]);
return 0;
}
static void zfcp_reqlist_free(struct zfcp_adapter *adapter)
{
struct zfcp_fsf_req *request, *tmp;
unsigned int i;
for (i=0; i<REQUEST_LIST_SIZE; i++) {
if (list_empty(&adapter->req_list[i]))
continue;
list_for_each_entry_safe(request, tmp,
&adapter->req_list[i], list)
list_del(&request->list);
}
kfree(adapter->req_list);
}
void zfcp_reqlist_add(struct zfcp_adapter *adapter,
struct zfcp_fsf_req *fsf_req)
{
unsigned int i;
i = fsf_req->req_id % REQUEST_LIST_SIZE;
list_add_tail(&fsf_req->list, &adapter->req_list[i]);
}
void zfcp_reqlist_remove(struct zfcp_adapter *adapter, unsigned long req_id)
{
struct zfcp_fsf_req *request, *tmp;
unsigned int i, counter;
u64 dbg_tmp[2];
i = req_id % REQUEST_LIST_SIZE;
BUG_ON(list_empty(&adapter->req_list[i]));
counter = 0;
list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list) {
if (request->req_id == req_id) {
dbg_tmp[0] = (u64) atomic_read(&adapter->reqs_active);
dbg_tmp[1] = (u64) counter;
debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16);
list_del(&request->list);
break;
}
counter++;
}
}
struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *adapter,
unsigned long req_id)
{
struct zfcp_fsf_req *request, *tmp;
unsigned int i;
i = req_id % REQUEST_LIST_SIZE;
list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list)
if (request->req_id == req_id)
return request;
return NULL;
}
int zfcp_reqlist_isempty(struct zfcp_adapter *adapter)
{
unsigned int i;
for (i=0; i<REQUEST_LIST_SIZE; i++)
if (!list_empty(&adapter->req_list[i]))
return 0;
return 1;
}
#undef ZFCP_LOG_AREA
/****************************************************************/ /****************************************************************/
/************** Uncategorised Functions *************************/ /************** Uncategorised Functions *************************/
/****************************************************************/ /****************************************************************/
...@@ -961,8 +1060,12 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) ...@@ -961,8 +1060,12 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
INIT_LIST_HEAD(&adapter->port_remove_lh); INIT_LIST_HEAD(&adapter->port_remove_lh);
/* initialize list of fsf requests */ /* initialize list of fsf requests */
spin_lock_init(&adapter->fsf_req_list_lock); spin_lock_init(&adapter->req_list_lock);
INIT_LIST_HEAD(&adapter->fsf_req_list_head); retval = zfcp_reqlist_init(adapter);
if (retval) {
ZFCP_LOG_INFO("request list initialization failed\n");
goto failed_low_mem_buffers;
}
/* initialize debug locks */ /* initialize debug locks */
...@@ -1041,8 +1144,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) ...@@ -1041,8 +1144,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
* !0 - struct zfcp_adapter data structure could not be removed * !0 - struct zfcp_adapter data structure could not be removed
* (e.g. still used) * (e.g. still used)
* locks: adapter list write lock is assumed to be held by caller * locks: adapter list write lock is assumed to be held by caller
* adapter->fsf_req_list_lock is taken and released within this
* function and must not be held on entry
*/ */
void void
zfcp_adapter_dequeue(struct zfcp_adapter *adapter) zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
...@@ -1054,14 +1155,14 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter) ...@@ -1054,14 +1155,14 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev); zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
dev_set_drvdata(&adapter->ccw_device->dev, NULL); dev_set_drvdata(&adapter->ccw_device->dev, NULL);
/* sanity check: no pending FSF requests */ /* sanity check: no pending FSF requests */
spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); spin_lock_irqsave(&adapter->req_list_lock, flags);
retval = !list_empty(&adapter->fsf_req_list_head); retval = zfcp_reqlist_isempty(adapter);
spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); spin_unlock_irqrestore(&adapter->req_list_lock, flags);
if (retval) { if (!retval) {
ZFCP_LOG_NORMAL("bug: adapter %s (%p) still in use, " ZFCP_LOG_NORMAL("bug: adapter %s (%p) still in use, "
"%i requests outstanding\n", "%i requests outstanding\n",
zfcp_get_busid_by_adapter(adapter), adapter, zfcp_get_busid_by_adapter(adapter), adapter,
atomic_read(&adapter->fsf_reqs_active)); atomic_read(&adapter->reqs_active));
retval = -EBUSY; retval = -EBUSY;
goto out; goto out;
} }
...@@ -1087,6 +1188,7 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter) ...@@ -1087,6 +1188,7 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
zfcp_free_low_mem_buffers(adapter); zfcp_free_low_mem_buffers(adapter);
/* free memory of adapter data structure and queues */ /* free memory of adapter data structure and queues */
zfcp_qdio_free_queues(adapter); zfcp_qdio_free_queues(adapter);
zfcp_reqlist_free(adapter);
kfree(adapter->fc_stats); kfree(adapter->fc_stats);
kfree(adapter->stats_reset_data); kfree(adapter->stats_reset_data);
ZFCP_LOG_TRACE("freeing adapter structure\n"); ZFCP_LOG_TRACE("freeing adapter structure\n");
......
...@@ -164,6 +164,11 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device) ...@@ -164,6 +164,11 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device)
retval = zfcp_adapter_scsi_register(adapter); retval = zfcp_adapter_scsi_register(adapter);
if (retval) if (retval)
goto out_scsi_register; goto out_scsi_register;
/* initialize request counter */
BUG_ON(!zfcp_reqlist_isempty(adapter));
adapter->req_no = 0;
zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING, zfcp_erp_modify_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING,
ZFCP_SET); ZFCP_SET);
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
......
...@@ -886,11 +886,11 @@ struct zfcp_adapter { ...@@ -886,11 +886,11 @@ struct zfcp_adapter {
struct list_head port_remove_lh; /* head of ports to be struct list_head port_remove_lh; /* head of ports to be
removed */ removed */
u32 ports; /* number of remote ports */ u32 ports; /* number of remote ports */
struct timer_list scsi_er_timer; /* SCSI err recovery watch */ struct timer_list scsi_er_timer; /* SCSI err recovery watch */
struct list_head fsf_req_list_head; /* head of FSF req list */ atomic_t reqs_active; /* # active FSF reqs */
spinlock_t fsf_req_list_lock; /* lock for ops on list of unsigned long req_no; /* unique FSF req number */
FSF requests */ struct list_head *req_list; /* list of pending reqs */
atomic_t fsf_reqs_active; /* # active FSF reqs */ spinlock_t req_list_lock; /* request list lock */
struct zfcp_qdio_queue request_queue; /* request queue */ struct zfcp_qdio_queue request_queue; /* request queue */
u32 fsf_req_seq_no; /* FSF cmnd seq number */ u32 fsf_req_seq_no; /* FSF cmnd seq number */
wait_queue_head_t request_wq; /* can be used to wait for wait_queue_head_t request_wq; /* can be used to wait for
...@@ -986,6 +986,7 @@ struct zfcp_unit { ...@@ -986,6 +986,7 @@ struct zfcp_unit {
/* FSF request */ /* FSF request */
struct zfcp_fsf_req { struct zfcp_fsf_req {
struct list_head list; /* list of FSF requests */ struct list_head list; /* list of FSF requests */
unsigned long req_id; /* unique request ID */
struct zfcp_adapter *adapter; /* adapter request belongs to */ struct zfcp_adapter *adapter; /* adapter request belongs to */
u8 sbal_number; /* nr of SBALs free for use */ u8 sbal_number; /* nr of SBALs free for use */
u8 sbal_first; /* first SBAL for this request */ u8 sbal_first; /* first SBAL for this request */
......
...@@ -848,18 +848,16 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) ...@@ -848,18 +848,16 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
struct zfcp_adapter *adapter = erp_action->adapter; struct zfcp_adapter *adapter = erp_action->adapter;
if (erp_action->fsf_req) { if (erp_action->fsf_req) {
/* take lock to ensure that request is not being deleted meanwhile */ /* take lock to ensure that request is not deleted meanwhile */
spin_lock(&adapter->fsf_req_list_lock); spin_lock(&adapter->req_list_lock);
/* check whether fsf req does still exist */ if ((!zfcp_reqlist_ismember(adapter,
list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list) erp_action->fsf_req->req_id)) &&
if (fsf_req == erp_action->fsf_req) (fsf_req->erp_action == erp_action)) {
break;
if (fsf_req && (fsf_req->erp_action == erp_action)) {
/* fsf_req still exists */ /* fsf_req still exists */
debug_text_event(adapter->erp_dbf, 3, "a_ca_req"); debug_text_event(adapter->erp_dbf, 3, "a_ca_req");
debug_event(adapter->erp_dbf, 3, &fsf_req, debug_event(adapter->erp_dbf, 3, &fsf_req,
sizeof (unsigned long)); sizeof (unsigned long));
/* dismiss fsf_req of timed out or dismissed erp_action */ /* dismiss fsf_req of timed out/dismissed erp_action */
if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED | if (erp_action->status & (ZFCP_STATUS_ERP_DISMISSED |
ZFCP_STATUS_ERP_TIMEDOUT)) { ZFCP_STATUS_ERP_TIMEDOUT)) {
debug_text_event(adapter->erp_dbf, 3, debug_text_event(adapter->erp_dbf, 3,
...@@ -892,7 +890,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action) ...@@ -892,7 +890,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
*/ */
erp_action->fsf_req = NULL; erp_action->fsf_req = NULL;
} }
spin_unlock(&adapter->fsf_req_list_lock); spin_unlock(&adapter->req_list_lock);
} else } else
debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq"); debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq");
......
...@@ -63,7 +63,6 @@ extern int zfcp_qdio_allocate_queues(struct zfcp_adapter *); ...@@ -63,7 +63,6 @@ extern int zfcp_qdio_allocate_queues(struct zfcp_adapter *);
extern void zfcp_qdio_free_queues(struct zfcp_adapter *); extern void zfcp_qdio_free_queues(struct zfcp_adapter *);
extern int zfcp_qdio_determine_pci(struct zfcp_qdio_queue *, extern int zfcp_qdio_determine_pci(struct zfcp_qdio_queue *,
struct zfcp_fsf_req *); struct zfcp_fsf_req *);
extern int zfcp_qdio_reqid_check(struct zfcp_adapter *, void *);
extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_req extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_req
(struct zfcp_fsf_req *, int, int); (struct zfcp_fsf_req *, int, int);
...@@ -190,5 +189,10 @@ extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *, ...@@ -190,5 +189,10 @@ extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *,
struct zfcp_fsf_req *); struct zfcp_fsf_req *);
extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *, extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
struct scsi_cmnd *); struct scsi_cmnd *);
extern void zfcp_reqlist_add(struct zfcp_adapter *, struct zfcp_fsf_req *);
extern void zfcp_reqlist_remove(struct zfcp_adapter *, unsigned long);
extern struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *,
unsigned long);
extern int zfcp_reqlist_isempty(struct zfcp_adapter *);
#endif /* ZFCP_EXT_H */ #endif /* ZFCP_EXT_H */
...@@ -49,7 +49,6 @@ static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *); ...@@ -49,7 +49,6 @@ static int zfcp_fsf_fsfstatus_qual_eval(struct zfcp_fsf_req *);
static void zfcp_fsf_link_down_info_eval(struct zfcp_adapter *, static void zfcp_fsf_link_down_info_eval(struct zfcp_adapter *,
struct fsf_link_down_info *); struct fsf_link_down_info *);
static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *); static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *);
static void zfcp_fsf_req_dismiss(struct zfcp_fsf_req *);
/* association between FSF command and FSF QTCB type */ /* association between FSF command and FSF QTCB type */
static u32 fsf_qtcb_type[] = { static u32 fsf_qtcb_type[] = {
...@@ -146,47 +145,48 @@ zfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req) ...@@ -146,47 +145,48 @@ zfcp_fsf_req_free(struct zfcp_fsf_req *fsf_req)
kfree(fsf_req); kfree(fsf_req);
} }
/* /**
* function: * zfcp_fsf_req_dismiss - dismiss a single fsf request
*
* purpose:
*
* returns:
*
* note: qdio queues shall be down (no ongoing inbound processing)
*/ */
int static void zfcp_fsf_req_dismiss(struct zfcp_adapter *adapter,
zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) struct zfcp_fsf_req *fsf_req,
unsigned int counter)
{ {
struct zfcp_fsf_req *fsf_req, *tmp; u64 dbg_tmp[2];
unsigned long flags;
LIST_HEAD(remove_queue);
spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); dbg_tmp[0] = (u64) atomic_read(&adapter->reqs_active);
list_splice_init(&adapter->fsf_req_list_head, &remove_queue); dbg_tmp[1] = (u64) counter;
atomic_set(&adapter->fsf_reqs_active, 0); debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16);
spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); list_del(&fsf_req->list);
fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED;
list_for_each_entry_safe(fsf_req, tmp, &remove_queue, list) { zfcp_fsf_req_complete(fsf_req);
list_del(&fsf_req->list);
zfcp_fsf_req_dismiss(fsf_req);
}
return 0;
} }
/* /**
* function: * zfcp_fsf_req_dismiss_all - dismiss all remaining fsf requests
*
* purpose:
*
* returns:
*/ */
static void int zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter)
zfcp_fsf_req_dismiss(struct zfcp_fsf_req *fsf_req)
{ {
fsf_req->status |= ZFCP_STATUS_FSFREQ_DISMISSED; struct zfcp_fsf_req *request, *tmp;
zfcp_fsf_req_complete(fsf_req); unsigned long flags;
unsigned int i, counter;
spin_lock_irqsave(&adapter->req_list_lock, flags);
atomic_set(&adapter->reqs_active, 0);
for (i=0; i<REQUEST_LIST_SIZE; i++) {
if (list_empty(&adapter->req_list[i]))
continue;
counter = 0;
list_for_each_entry_safe(request, tmp,
&adapter->req_list[i], list) {
zfcp_fsf_req_dismiss(adapter, request, counter);
counter++;
}
}
spin_unlock_irqrestore(&adapter->req_list_lock, flags);
return 0;
} }
/* /*
...@@ -4592,12 +4592,14 @@ static inline void ...@@ -4592,12 +4592,14 @@ static inline void
zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req) zfcp_fsf_req_qtcb_init(struct zfcp_fsf_req *fsf_req)
{ {
if (likely(fsf_req->qtcb != NULL)) { if (likely(fsf_req->qtcb != NULL)) {
fsf_req->qtcb->prefix.req_seq_no = fsf_req->adapter->fsf_req_seq_no; fsf_req->qtcb->prefix.req_seq_no =
fsf_req->qtcb->prefix.req_id = (unsigned long)fsf_req; fsf_req->adapter->fsf_req_seq_no;
fsf_req->qtcb->prefix.req_id = fsf_req->req_id;
fsf_req->qtcb->prefix.ulp_info = ZFCP_ULP_INFO_VERSION; fsf_req->qtcb->prefix.ulp_info = ZFCP_ULP_INFO_VERSION;
fsf_req->qtcb->prefix.qtcb_type = fsf_qtcb_type[fsf_req->fsf_command]; fsf_req->qtcb->prefix.qtcb_type =
fsf_qtcb_type[fsf_req->fsf_command];
fsf_req->qtcb->prefix.qtcb_version = ZFCP_QTCB_VERSION; fsf_req->qtcb->prefix.qtcb_version = ZFCP_QTCB_VERSION;
fsf_req->qtcb->header.req_handle = (unsigned long)fsf_req; fsf_req->qtcb->header.req_handle = fsf_req->req_id;
fsf_req->qtcb->header.fsf_command = fsf_req->fsf_command; fsf_req->qtcb->header.fsf_command = fsf_req->fsf_command;
} }
} }
...@@ -4654,6 +4656,7 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, ...@@ -4654,6 +4656,7 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
{ {
volatile struct qdio_buffer_element *sbale; volatile struct qdio_buffer_element *sbale;
struct zfcp_fsf_req *fsf_req = NULL; struct zfcp_fsf_req *fsf_req = NULL;
unsigned long flags;
int ret = 0; int ret = 0;
struct zfcp_qdio_queue *req_queue = &adapter->request_queue; struct zfcp_qdio_queue *req_queue = &adapter->request_queue;
...@@ -4668,6 +4671,12 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, ...@@ -4668,6 +4671,12 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
fsf_req->adapter = adapter; fsf_req->adapter = adapter;
fsf_req->fsf_command = fsf_cmd; fsf_req->fsf_command = fsf_cmd;
INIT_LIST_HEAD(&fsf_req->list);
/* unique request id */
spin_lock_irqsave(&adapter->req_list_lock, flags);
fsf_req->req_id = adapter->req_no++;
spin_unlock_irqrestore(&adapter->req_list_lock, flags);
zfcp_fsf_req_qtcb_init(fsf_req); zfcp_fsf_req_qtcb_init(fsf_req);
...@@ -4707,7 +4716,7 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, ...@@ -4707,7 +4716,7 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0);
/* setup common SBALE fields */ /* setup common SBALE fields */
sbale[0].addr = fsf_req; sbale[0].addr = (void *) fsf_req->req_id;
sbale[0].flags |= SBAL_FLAGS0_COMMAND; sbale[0].flags |= SBAL_FLAGS0_COMMAND;
if (likely(fsf_req->qtcb != NULL)) { if (likely(fsf_req->qtcb != NULL)) {
sbale[1].addr = (void *) fsf_req->qtcb; sbale[1].addr = (void *) fsf_req->qtcb;
...@@ -4747,7 +4756,7 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) ...@@ -4747,7 +4756,7 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
volatile struct qdio_buffer_element *sbale; volatile struct qdio_buffer_element *sbale;
int inc_seq_no; int inc_seq_no;
int new_distance_from_int; int new_distance_from_int;
unsigned long flags; u64 dbg_tmp[2];
int retval = 0; int retval = 0;
adapter = fsf_req->adapter; adapter = fsf_req->adapter;
...@@ -4761,10 +4770,10 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) ...@@ -4761,10 +4770,10 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) sbale[1].addr, ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) sbale[1].addr,
sbale[1].length); sbale[1].length);
/* put allocated FSF request at list tail */ /* put allocated FSF request into hash table */
spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); spin_lock(&adapter->req_list_lock);
list_add_tail(&fsf_req->list, &adapter->fsf_req_list_head); zfcp_reqlist_add(adapter, fsf_req);
spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); spin_unlock(&adapter->req_list_lock);
inc_seq_no = (fsf_req->qtcb != NULL); inc_seq_no = (fsf_req->qtcb != NULL);
...@@ -4803,6 +4812,10 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) ...@@ -4803,6 +4812,10 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
QDIO_FLAG_SYNC_OUTPUT, QDIO_FLAG_SYNC_OUTPUT,
0, fsf_req->sbal_first, fsf_req->sbal_number, NULL); 0, fsf_req->sbal_first, fsf_req->sbal_number, NULL);
dbg_tmp[0] = (unsigned long) sbale[0].addr;
dbg_tmp[1] = (u64) retval;
debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16);
if (unlikely(retval)) { if (unlikely(retval)) {
/* Queues are down..... */ /* Queues are down..... */
retval = -EIO; retval = -EIO;
...@@ -4812,22 +4825,17 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) ...@@ -4812,22 +4825,17 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
*/ */
if (timer) if (timer)
del_timer(timer); del_timer(timer);
spin_lock_irqsave(&adapter->fsf_req_list_lock, flags); spin_lock(&adapter->req_list_lock);
list_del(&fsf_req->list); zfcp_reqlist_remove(adapter, fsf_req->req_id);
spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags); spin_unlock(&adapter->req_list_lock);
/* /* undo changes in request queue made for this request */
* adjust the number of free SBALs in request queue as well as
* position of first one
*/
zfcp_qdio_zero_sbals(req_queue->buffer, zfcp_qdio_zero_sbals(req_queue->buffer,
fsf_req->sbal_first, fsf_req->sbal_number); fsf_req->sbal_first, fsf_req->sbal_number);
atomic_add(fsf_req->sbal_number, &req_queue->free_count); atomic_add(fsf_req->sbal_number, &req_queue->free_count);
req_queue->free_index -= fsf_req->sbal_number; /* increase */ req_queue->free_index -= fsf_req->sbal_number;
req_queue->free_index += QDIO_MAX_BUFFERS_PER_Q; req_queue->free_index += QDIO_MAX_BUFFERS_PER_Q;
req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */ req_queue->free_index %= QDIO_MAX_BUFFERS_PER_Q; /* wrap */
ZFCP_LOG_DEBUG zfcp_erp_adapter_reopen(adapter, 0);
("error: do_QDIO failed. Buffers could not be enqueued "
"to request queue.\n");
} else { } else {
req_queue->distance_from_int = new_distance_from_int; req_queue->distance_from_int = new_distance_from_int;
/* /*
...@@ -4843,7 +4851,7 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer) ...@@ -4843,7 +4851,7 @@ zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req, struct timer_list *timer)
adapter->fsf_req_seq_no++; adapter->fsf_req_seq_no++;
/* count FSF requests pending */ /* count FSF requests pending */
atomic_inc(&adapter->fsf_reqs_active); atomic_inc(&adapter->reqs_active);
} }
return retval; return retval;
} }
......
...@@ -282,6 +282,37 @@ zfcp_qdio_request_handler(struct ccw_device *ccw_device, ...@@ -282,6 +282,37 @@ zfcp_qdio_request_handler(struct ccw_device *ccw_device,
return; return;
} }
/**
* zfcp_qdio_reqid_check - checks for valid reqids or unsolicited status
*/
static int zfcp_qdio_reqid_check(struct zfcp_adapter *adapter,
unsigned long req_id)
{
struct zfcp_fsf_req *fsf_req;
unsigned long flags;
debug_long_event(adapter->erp_dbf, 4, req_id);
spin_lock_irqsave(&adapter->req_list_lock, flags);
fsf_req = zfcp_reqlist_ismember(adapter, req_id);
if (!fsf_req) {
spin_unlock_irqrestore(&adapter->req_list_lock, flags);
ZFCP_LOG_NORMAL("error: unknown request id (%ld).\n", req_id);
zfcp_erp_adapter_reopen(adapter, 0);
return -EINVAL;
}
zfcp_reqlist_remove(adapter, req_id);
atomic_dec(&adapter->reqs_active);
spin_unlock_irqrestore(&adapter->req_list_lock, flags);
/* finish the FSF request */
zfcp_fsf_req_complete(fsf_req);
return 0;
}
/* /*
* function: zfcp_qdio_response_handler * function: zfcp_qdio_response_handler
* *
...@@ -344,7 +375,7 @@ zfcp_qdio_response_handler(struct ccw_device *ccw_device, ...@@ -344,7 +375,7 @@ zfcp_qdio_response_handler(struct ccw_device *ccw_device,
/* look for QDIO request identifiers in SB */ /* look for QDIO request identifiers in SB */
buffere = &buffer->element[buffere_index]; buffere = &buffer->element[buffere_index];
retval = zfcp_qdio_reqid_check(adapter, retval = zfcp_qdio_reqid_check(adapter,
(void *) buffere->addr); (unsigned long) buffere->addr);
if (retval) { if (retval) {
ZFCP_LOG_NORMAL("bug: unexpected inbound " ZFCP_LOG_NORMAL("bug: unexpected inbound "
...@@ -415,52 +446,6 @@ zfcp_qdio_response_handler(struct ccw_device *ccw_device, ...@@ -415,52 +446,6 @@ zfcp_qdio_response_handler(struct ccw_device *ccw_device,
return; return;
} }
/*
* function: zfcp_qdio_reqid_check
*
* purpose: checks for valid reqids or unsolicited status
*
* returns: 0 - valid request id or unsolicited status
* !0 - otherwise
*/
int
zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr)
{
struct zfcp_fsf_req *fsf_req;
unsigned long flags;
/* invalid (per convention used in this driver) */
if (unlikely(!sbale_addr)) {
ZFCP_LOG_NORMAL("bug: invalid reqid\n");
return -EINVAL;
}
/* valid request id and thus (hopefully :) valid fsf_req address */
fsf_req = (struct zfcp_fsf_req *) sbale_addr;
/* serialize with zfcp_fsf_req_dismiss_all */
spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
if (list_empty(&adapter->fsf_req_list_head)) {
spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
return 0;
}
list_del(&fsf_req->list);
atomic_dec(&adapter->fsf_reqs_active);
spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
if (unlikely(adapter != fsf_req->adapter)) {
ZFCP_LOG_NORMAL("bug: invalid reqid (fsf_req=%p, "
"fsf_req->adapter=%p, adapter=%p)\n",
fsf_req, fsf_req->adapter, adapter);
return -EINVAL;
}
/* finish the FSF request */
zfcp_fsf_req_complete(fsf_req);
return 0;
}
/** /**
* zfcp_qdio_sbale_get - return pointer to SBALE of qdio_queue * zfcp_qdio_sbale_get - return pointer to SBALE of qdio_queue
* @queue: queue from which SBALE should be returned * @queue: queue from which SBALE should be returned
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment