Skip to content

Commit

Permalink
[SCSI] zfcp: improve management of request IDs
Browse files Browse the repository at this point in the history
Improve request handling. Use hash table to manage request IDs.

Signed-off-by: Volker Sameske <sameske@de.ibm.com>
Signed-off-by: Andreas Herrmann <aherrman@de.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
  • Loading branch information
Volker Sameske authored and James Bottomley committed Aug 6, 2006
1 parent c2602c4 commit fea9d6c
Show file tree
Hide file tree
Showing 7 changed files with 231 additions and 128 deletions.
120 changes: 111 additions & 9 deletions drivers/s390/scsi/zfcp_aux.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,105 @@ _zfcp_hex_dump(char *addr, int count)
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 *************************/
/****************************************************************/
Expand Down Expand Up @@ -961,8 +1060,12 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
INIT_LIST_HEAD(&adapter->port_remove_lh);

/* initialize list of fsf requests */
spin_lock_init(&adapter->fsf_req_list_lock);
INIT_LIST_HEAD(&adapter->fsf_req_list_head);
spin_lock_init(&adapter->req_list_lock);
retval = zfcp_reqlist_init(adapter);
if (retval) {
ZFCP_LOG_INFO("request list initialization failed\n");
goto failed_low_mem_buffers;
}

/* initialize debug locks */

Expand Down Expand Up @@ -1041,8 +1144,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
* !0 - struct zfcp_adapter data structure could not be removed
* (e.g. still used)
* 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
zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
Expand All @@ -1054,14 +1155,14 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
dev_set_drvdata(&adapter->ccw_device->dev, NULL);
/* sanity check: no pending FSF requests */
spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
retval = !list_empty(&adapter->fsf_req_list_head);
spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
if (retval) {
spin_lock_irqsave(&adapter->req_list_lock, flags);
retval = zfcp_reqlist_isempty(adapter);
spin_unlock_irqrestore(&adapter->req_list_lock, flags);
if (!retval) {
ZFCP_LOG_NORMAL("bug: adapter %s (%p) still in use, "
"%i requests outstanding\n",
zfcp_get_busid_by_adapter(adapter), adapter,
atomic_read(&adapter->fsf_reqs_active));
atomic_read(&adapter->reqs_active));
retval = -EBUSY;
goto out;
}
Expand All @@ -1087,6 +1188,7 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
zfcp_free_low_mem_buffers(adapter);
/* free memory of adapter data structure and queues */
zfcp_qdio_free_queues(adapter);
zfcp_reqlist_free(adapter);
kfree(adapter->fc_stats);
kfree(adapter->stats_reset_data);
ZFCP_LOG_TRACE("freeing adapter structure\n");
Expand Down
5 changes: 5 additions & 0 deletions drivers/s390/scsi/zfcp_ccw.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device)
retval = zfcp_adapter_scsi_register(adapter);
if (retval)
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_SET);
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
Expand Down
11 changes: 6 additions & 5 deletions drivers/s390/scsi/zfcp_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -886,11 +886,11 @@ struct zfcp_adapter {
struct list_head port_remove_lh; /* head of ports to be
removed */
u32 ports; /* number of remote ports */
struct timer_list scsi_er_timer; /* SCSI err recovery watch */
struct list_head fsf_req_list_head; /* head of FSF req list */
spinlock_t fsf_req_list_lock; /* lock for ops on list of
FSF requests */
atomic_t fsf_reqs_active; /* # active FSF reqs */
struct timer_list scsi_er_timer; /* SCSI err recovery watch */
atomic_t reqs_active; /* # active FSF reqs */
unsigned long req_no; /* unique FSF req number */
struct list_head *req_list; /* list of pending reqs */
spinlock_t req_list_lock; /* request list lock */
struct zfcp_qdio_queue request_queue; /* request queue */
u32 fsf_req_seq_no; /* FSF cmnd seq number */
wait_queue_head_t request_wq; /* can be used to wait for
Expand Down Expand Up @@ -986,6 +986,7 @@ struct zfcp_unit {
/* FSF request */
struct zfcp_fsf_req {
struct list_head list; /* list of FSF requests */
unsigned long req_id; /* unique request ID */
struct zfcp_adapter *adapter; /* adapter request belongs to */
u8 sbal_number; /* nr of SBALs free for use */
u8 sbal_first; /* first SBAL for this request */
Expand Down
16 changes: 7 additions & 9 deletions drivers/s390/scsi/zfcp_erp.c
Original file line number Diff line number Diff line change
Expand Up @@ -848,18 +848,16 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
struct zfcp_adapter *adapter = erp_action->adapter;

if (erp_action->fsf_req) {
/* take lock to ensure that request is not being deleted meanwhile */
spin_lock(&adapter->fsf_req_list_lock);
/* check whether fsf req does still exist */
list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list)
if (fsf_req == erp_action->fsf_req)
break;
if (fsf_req && (fsf_req->erp_action == erp_action)) {
/* take lock to ensure that request is not deleted meanwhile */
spin_lock(&adapter->req_list_lock);
if ((!zfcp_reqlist_ismember(adapter,
erp_action->fsf_req->req_id)) &&
(fsf_req->erp_action == erp_action)) {
/* fsf_req still exists */
debug_text_event(adapter->erp_dbf, 3, "a_ca_req");
debug_event(adapter->erp_dbf, 3, &fsf_req,
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 |
ZFCP_STATUS_ERP_TIMEDOUT)) {
debug_text_event(adapter->erp_dbf, 3,
Expand Down Expand Up @@ -892,7 +890,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
*/
erp_action->fsf_req = NULL;
}
spin_unlock(&adapter->fsf_req_list_lock);
spin_unlock(&adapter->req_list_lock);
} else
debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq");

Expand Down
6 changes: 5 additions & 1 deletion drivers/s390/scsi/zfcp_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ extern int zfcp_qdio_allocate_queues(struct zfcp_adapter *);
extern void zfcp_qdio_free_queues(struct zfcp_adapter *);
extern int zfcp_qdio_determine_pci(struct zfcp_qdio_queue *,
struct zfcp_fsf_req *);
extern int zfcp_qdio_reqid_check(struct zfcp_adapter *, void *);

extern volatile struct qdio_buffer_element *zfcp_qdio_sbale_req
(struct zfcp_fsf_req *, int, int);
Expand Down Expand Up @@ -190,5 +189,10 @@ extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *,
struct zfcp_fsf_req *);
extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
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 */
Loading

0 comments on commit fea9d6c

Please sign in to comment.