-/*
+/*
* This file is part of the zfcp device driver for
* FCP adapters for IBM System z9 and zSeries.
*
* (C) Copyright IBM Corp. 2002, 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
#ifndef ZFCP_DEF_H
#define ZFCP_DEF_H
#include <linux/slab.h>
#include <linux/mempool.h>
#include <linux/syscalls.h>
+#include <linux/scatterlist.h>
#include <linux/ioctl.h>
#include <scsi/scsi.h>
#include <scsi/scsi_tcq.h>
static inline void *
zfcp_sg_to_address(struct scatterlist *list)
{
- return (void *) (page_address(list->page) + list->offset);
+ return sg_virt(list);
}
/**
static inline void
zfcp_address_to_sg(void *address, struct scatterlist *list)
{
- list->page = virt_to_page(address);
+ sg_set_page(list, virt_to_page(address));
list->offset = ((unsigned long) address) & (PAGE_SIZE - 1);
}
#define ZFCP_DEVICE_TYPE 0x1732
#define ZFCP_DEVICE_MODEL 0x03
#define ZFCP_DEVICE_MODEL_PRIV 0x04
-
+
/* allow as many chained SBALs as are supported by hardware */
#define ZFCP_MAX_SBALS_PER_REQ FSF_MAX_SBALS_PER_REQ
#define ZFCP_MAX_SBALS_PER_CT_REQ FSF_MAX_SBALS_PER_REQ
(ZFCP_MAX_SBALS_PER_REQ * ZFCP_MAX_SBALES_PER_SBAL - 2)
/* request ID + QTCB in SBALE 0 + 1 of first SBAL in chain */
+#define ZFCP_MAX_SECTORS (ZFCP_MAX_SBALES_PER_REQ * 8)
+ /* max. number of (data buffer) SBALEs in largest SBAL chain
+ multiplied with number of sectors per 4k block */
+
/* FIXME(tune): free space should be one max. SBAL chain plus what? */
#define ZFCP_QDIO_PCI_INTERVAL (QDIO_MAX_BUFFERS_PER_Q \
- (ZFCP_MAX_SBALS_PER_REQ + 4))
#define ZFCP_MIN_OUTPUT_THRESHOLD 1 /* ignored by QDIO layer */
#define QDIO_SCSI_QFMT 1 /* 1 for FSF */
+#define QBUFF_PER_PAGE (PAGE_SIZE / sizeof(struct qdio_buffer))
/********************* FSF SPECIFIC DEFINES *********************************/
/*
* this allows removal of logging code by the preprocessor
- * (the most detailed log level still to be compiled in is specified,
+ * (the most detailed log level still to be compiled in is specified,
* higher log levels are removed)
*/
#define ZFCP_LOG_LEVEL_LIMIT ZFCP_LOG_LEVEL_TRACE
if (ZFCP_LOG_CHECK(level)) \
_ZFCP_LOG(fmt, ##args); \
} while (0)
-
+
#if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_NORMAL
# define ZFCP_LOG_NORMAL(fmt, args...) do { } while (0)
#else
/*************** ADAPTER/PORT/UNIT AND FSF_REQ STATUS FLAGS ******************/
-/*
- * Note, the leftmost status byte is common among adapter, port
+/*
+ * Note, the leftmost status byte is common among adapter, port
* and unit
*/
#define ZFCP_COMMON_FLAGS 0xfff00000
#define ZFCP_STATUS_UNIT_SHARED 0x00000004
#define ZFCP_STATUS_UNIT_READONLY 0x00000008
#define ZFCP_STATUS_UNIT_REGISTERED 0x00000010
+#define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING 0x00000020
/* FSF request status (this does not have a common part) */
#define ZFCP_STATUS_FSFREQ_NOT_INIT 0x00000000
struct scsi_device *device; /* scsi device struct pointer */
struct zfcp_erp_action erp_action; /* pending error recovery */
atomic_t erp_counter;
+ wait_queue_head_t scsi_scan_wq; /* can be used to wait until
+ all scsi_scan_target
+ requests have been
+ completed. */
};
/* FSF request */
u32 fsf_command; /* FSF Command copy */
struct fsf_qtcb *qtcb; /* address of associated QTCB */
u32 seq_no; /* Sequence number of request */
- unsigned long data; /* private data of request */
- struct timer_list timer; /* used for erp or scsi er */
+ unsigned long data; /* private data of request */
+ struct timer_list timer; /* used for erp or scsi er */
struct zfcp_erp_action *erp_action; /* used if this request is
issued on behalf of erp */
mempool_t *pool; /* used if request was alloacted
wwn_t init_wwpn;
fcp_lun_t init_fcp_lun;
char *driver_version;
- kmem_cache_t *fsf_req_qtcb_cache;
- kmem_cache_t *sr_buffer_cache;
- kmem_cache_t *gid_pn_cache;
+ struct kmem_cache *fsf_req_qtcb_cache;
+ struct kmem_cache *sr_buffer_cache;
+ struct kmem_cache *gid_pn_cache;
};
/**
#define zfcp_get_busid_by_port(port) (zfcp_get_busid_by_adapter(port->adapter))
#define zfcp_get_busid_by_unit(unit) (zfcp_get_busid_by_port(unit->port))
+/*
+ * Helper functions for request ID management.
+ */
+static inline int zfcp_reqlist_hash(unsigned long req_id)
+{
+ return req_id % REQUEST_LIST_SIZE;
+}
+
+static inline void zfcp_reqlist_add(struct zfcp_adapter *adapter,
+ struct zfcp_fsf_req *fsf_req)
+{
+ unsigned int idx;
+
+ idx = zfcp_reqlist_hash(fsf_req->req_id);
+ list_add_tail(&fsf_req->list, &adapter->req_list[idx]);
+}
+
+static inline void zfcp_reqlist_remove(struct zfcp_adapter *adapter,
+ struct zfcp_fsf_req *fsf_req)
+{
+ list_del(&fsf_req->list);
+}
+
+static inline struct zfcp_fsf_req *
+zfcp_reqlist_find(struct zfcp_adapter *adapter, unsigned long req_id)
+{
+ struct zfcp_fsf_req *request;
+ unsigned int idx;
+
+ idx = zfcp_reqlist_hash(req_id);
+ list_for_each_entry(request, &adapter->req_list[idx], list)
+ if (request->req_id == req_id)
+ return request;
+ return NULL;
+}
+
/*
* functions needed for reference/usage counting
*/