static void zfcp_ns_gid_pn_handler(unsigned long);
/* miscellaneous */
-static inline int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t);
-static inline void zfcp_sg_list_free(struct zfcp_sg_list *);
-static inline int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *,
- void __user *, size_t);
-static inline int zfcp_sg_list_copy_to_user(void __user *,
- struct zfcp_sg_list *, size_t);
-
+static int zfcp_sg_list_alloc(struct zfcp_sg_list *, size_t);
+static void zfcp_sg_list_free(struct zfcp_sg_list *);
+static int zfcp_sg_list_copy_from_user(struct zfcp_sg_list *,
+ void __user *, size_t);
+static int zfcp_sg_list_copy_to_user(void __user *,
+ struct zfcp_sg_list *, size_t);
static long zfcp_cfdc_dev_ioctl(struct file *, unsigned int, unsigned long);
#define ZFCP_CFDC_IOC_MAGIC 0xDD
_IOWR(ZFCP_CFDC_IOC_MAGIC, 0, struct zfcp_cfdc_sense_data)
-static struct file_operations zfcp_cfdc_fops = {
+static const struct file_operations zfcp_cfdc_fops = {
.unlocked_ioctl = zfcp_cfdc_dev_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = zfcp_cfdc_dev_ioctl
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_FSF
-static int zfcp_reqlist_init(struct zfcp_adapter *adapter)
+static int zfcp_reqlist_alloc(struct zfcp_adapter *adapter)
{
- int i;
+ int idx;
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]);
-
+ for (idx = 0; idx < REQUEST_LIST_SIZE; idx++)
+ INIT_LIST_HEAD(&adapter->req_list[idx]);
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;
+ unsigned int idx;
- for (i=0; i<REQUEST_LIST_SIZE; i++)
- if (!list_empty(&adapter->req_list[i]))
+ for (idx = 0; idx < REQUEST_LIST_SIZE; idx++)
+ if (!list_empty(&adapter->req_list[idx]))
return 0;
-
return 1;
}
return 0;
len = strlen(devstr) + 1;
- str = (char *) kmalloc(len, GFP_KERNEL);
+ str = kmalloc(len, GFP_KERNEL);
if (!str)
goto err_out;
memcpy(str, devstr, len);
return;
}
+static int calc_alignment(int size)
+{
+ int align = 1;
+
+ if (!size)
+ return 0;
+
+ while ((size - align) > 0)
+ align <<= 1;
+
+ return align;
+}
+
static int __init
zfcp_module_init(void)
{
+ int retval = -ENOMEM;
+ int size, align;
+
+ size = sizeof(struct zfcp_fsf_req_qtcb);
+ align = calc_alignment(size);
+ zfcp_data.fsf_req_qtcb_cache =
+ kmem_cache_create("zfcp_fsf", size, align, 0, NULL);
+ if (!zfcp_data.fsf_req_qtcb_cache)
+ goto out;
- int retval = 0;
+ size = sizeof(struct fsf_status_read_buffer);
+ align = calc_alignment(size);
+ zfcp_data.sr_buffer_cache =
+ kmem_cache_create("zfcp_sr", size, align, 0, NULL);
+ if (!zfcp_data.sr_buffer_cache)
+ goto out_sr_cache;
+
+ size = sizeof(struct zfcp_gid_pn_data);
+ align = calc_alignment(size);
+ zfcp_data.gid_pn_cache =
+ kmem_cache_create("zfcp_gid", size, align, 0, NULL);
+ if (!zfcp_data.gid_pn_cache)
+ goto out_gid_cache;
atomic_set(&zfcp_data.loglevel, loglevel);
/* initialize adapters to be removed list head */
INIT_LIST_HEAD(&zfcp_data.adapter_remove_lh);
- zfcp_transport_template = fc_attach_transport(&zfcp_transport_functions);
- if (!zfcp_transport_template)
- return -ENODEV;
+ zfcp_data.scsi_transport_template =
+ fc_attach_transport(&zfcp_transport_functions);
+ if (!zfcp_data.scsi_transport_template)
+ goto out_transport;
retval = misc_register(&zfcp_cfdc_misc);
if (retval != 0) {
ZFCP_LOG_INFO("registration of misc device "
"zfcp_cfdc failed\n");
- goto out;
+ goto out_misc;
}
ZFCP_LOG_TRACE("major/minor for zfcp_cfdc: %d/%d\n",
/* initialise configuration rw lock */
rwlock_init(&zfcp_data.config_lock);
- /* save address of data structure managing the driver module */
- zfcp_data.scsi_host_template.module = THIS_MODULE;
-
/* setup dynamic I/O */
retval = zfcp_ccw_register();
if (retval) {
out_ccw_register:
misc_deregister(&zfcp_cfdc_misc);
+ out_misc:
+ fc_release_transport(zfcp_data.scsi_transport_template);
+ out_transport:
+ kmem_cache_destroy(zfcp_data.gid_pn_cache);
+ out_gid_cache:
+ kmem_cache_destroy(zfcp_data.sr_buffer_cache);
+ out_sr_cache:
+ kmem_cache_destroy(zfcp_data.fsf_req_qtcb_cache);
out:
return retval;
}
* elements of the scatter-gather list. The maximum size of a single element
* in the scatter-gather list is PAGE_SIZE.
*/
-static inline int
+static int
zfcp_sg_list_alloc(struct zfcp_sg_list *sg_list, size_t size)
{
struct scatterlist *sg;
retval = -ENOMEM;
goto out;
}
+ sg_init_table(sg_list->sg, sg_list->count);
for (i = 0, sg = sg_list->sg; i < sg_list->count; i++, sg++) {
- sg->length = min(size, PAGE_SIZE);
- sg->offset = 0;
address = (void *) get_zeroed_page(GFP_KERNEL);
if (address == NULL) {
sg_list->count = i;
retval = -ENOMEM;
goto out;
}
- zfcp_address_to_sg(address, sg);
+ zfcp_address_to_sg(address, sg, min(size, PAGE_SIZE));
size -= sg->length;
}
* Memory for each element in the scatter-gather list is freed.
* Finally sg_list->sg is freed itself and sg_list->count is reset.
*/
-static inline void
+static void
zfcp_sg_list_free(struct zfcp_sg_list *sg_list)
{
struct scatterlist *sg;
* @sg_count: elements in array
* Return: size of entire scatter-gather list
*/
-size_t
-zfcp_sg_size(struct scatterlist *sg, unsigned int sg_count)
+static size_t zfcp_sg_size(struct scatterlist *sg, unsigned int sg_count)
{
unsigned int i;
struct scatterlist *p;
* @size: number of bytes to be copied
* Return: 0 on success, -EFAULT if copy_from_user fails.
*/
-static inline int
+static int
zfcp_sg_list_copy_from_user(struct zfcp_sg_list *sg_list,
void __user *user_buffer,
size_t size)
* @size: number of bytes to be copied
* Return: 0 on success, -EFAULT if copy_to_user fails
*/
-static inline int
+static int
zfcp_sg_list_copy_to_user(void __user *user_buffer,
struct zfcp_sg_list *sg_list,
size_t size)
struct zfcp_unit *
zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
{
- struct zfcp_unit *unit, *tmp_unit;
- unsigned int scsi_lun;
- int found;
+ struct zfcp_unit *unit;
/*
* check that there is no unit with this FCP_LUN already in list
unit->sysfs_device.release = zfcp_sysfs_unit_release;
dev_set_drvdata(&unit->sysfs_device, unit);
+ init_waitqueue_head(&unit->scsi_scan_wq);
+
/* mark unit unusable as long as sysfs registration is not complete */
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
}
zfcp_unit_get(unit);
+ unit->scsi_lun = scsilun_to_int((struct scsi_lun *)&unit->fcp_lun);
- scsi_lun = 0;
- found = 0;
write_lock_irq(&zfcp_data.config_lock);
- list_for_each_entry(tmp_unit, &port->unit_list_head, list) {
- if (tmp_unit->scsi_lun != scsi_lun) {
- found = 1;
- break;
- }
- scsi_lun++;
- }
- unit->scsi_lun = scsi_lun;
- if (found)
- list_add_tail(&unit->list, &tmp_unit->list);
- else
- list_add_tail(&unit->list, &port->unit_list_head);
+ list_add_tail(&unit->list, &port->unit_list_head);
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
atomic_set_mask(ZFCP_STATUS_COMMON_RUNNING, &unit->status);
write_unlock_irq(&zfcp_data.config_lock);
/*
* Allocates a combined QTCB/fsf_req buffer for erp actions and fcp/SCSI
* commands.
- * It also genrates fcp-nameserver request/response buffer and unsolicited
+ * It also genrates fcp-nameserver request/response buffer and unsolicited
* status read fsf_req buffers.
*
* locks: must only be called with zfcp_data.config_sema taken
zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)
{
adapter->pool.fsf_req_erp =
- mempool_create_kmalloc_pool(ZFCP_POOL_FSF_REQ_ERP_NR,
- sizeof(struct zfcp_fsf_req_pool_element));
+ mempool_create_slab_pool(ZFCP_POOL_FSF_REQ_ERP_NR,
+ zfcp_data.fsf_req_qtcb_cache);
if (!adapter->pool.fsf_req_erp)
return -ENOMEM;
adapter->pool.fsf_req_scsi =
- mempool_create_kmalloc_pool(ZFCP_POOL_FSF_REQ_SCSI_NR,
- sizeof(struct zfcp_fsf_req_pool_element));
+ mempool_create_slab_pool(ZFCP_POOL_FSF_REQ_SCSI_NR,
+ zfcp_data.fsf_req_qtcb_cache);
if (!adapter->pool.fsf_req_scsi)
return -ENOMEM;
adapter->pool.fsf_req_abort =
- mempool_create_kmalloc_pool(ZFCP_POOL_FSF_REQ_ABORT_NR,
- sizeof(struct zfcp_fsf_req_pool_element));
+ mempool_create_slab_pool(ZFCP_POOL_FSF_REQ_ABORT_NR,
+ zfcp_data.fsf_req_qtcb_cache);
if (!adapter->pool.fsf_req_abort)
return -ENOMEM;
return -ENOMEM;
adapter->pool.data_status_read =
- mempool_create_kmalloc_pool(ZFCP_POOL_STATUS_READ_NR,
- sizeof(struct fsf_status_read_buffer));
+ mempool_create_slab_pool(ZFCP_POOL_STATUS_READ_NR,
+ zfcp_data.sr_buffer_cache);
if (!adapter->pool.data_status_read)
return -ENOMEM;
adapter->pool.data_gid_pn =
- mempool_create_kmalloc_pool(ZFCP_POOL_DATA_GID_PN_NR,
- sizeof(struct zfcp_gid_pn_data));
+ mempool_create_slab_pool(ZFCP_POOL_DATA_GID_PN_NR,
+ zfcp_data.gid_pn_cache);
if (!adapter->pool.data_gid_pn)
return -ENOMEM;
mempool_destroy(adapter->pool.data_gid_pn);
}
-void
-zfcp_dummy_release(struct device *dev)
+static void zfcp_dummy_release(struct device *dev)
{
return;
}
struct zfcp_adapter *adapter;
/*
- * Note: It is safe to release the list_lock, as any list changes
+ * Note: It is safe to release the list_lock, as any list changes
* are protected by the config_sema, which must be held to get here
*/
/* initialize list of fsf requests */
spin_lock_init(&adapter->req_list_lock);
- retval = zfcp_reqlist_init(adapter);
+ retval = zfcp_reqlist_alloc(adapter);
if (retval) {
ZFCP_LOG_INFO("request list initialization failed\n");
goto failed_low_mem_buffers;
spin_lock_init(&adapter->san_dbf_lock);
spin_lock_init(&adapter->scsi_dbf_lock);
+ retval = zfcp_adapter_debug_register(adapter);
+ if (retval)
+ goto debug_register_failed;
+
/* initialize error recovery stuff */
rwlock_init(&adapter->erp_lock);
/* initialize lock of associated request queue */
rwlock_init(&adapter->request_queue.queue_lock);
- /* intitialise SCSI ER timer */
- init_timer(&adapter->scsi_er_timer);
-
/* mark adapter unusable as long as sysfs registration is not complete */
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
- adapter->ccw_device = ccw_device;
dev_set_drvdata(&ccw_device->dev, adapter);
if (zfcp_sysfs_adapter_create_files(&ccw_device->dev))
generic_services_failed:
zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
sysfs_failed:
+ zfcp_adapter_debug_unregister(adapter);
+ debug_register_failed:
dev_set_drvdata(&ccw_device->dev, NULL);
+ zfcp_reqlist_free(adapter);
failed_low_mem_buffers:
zfcp_free_low_mem_buffers(adapter);
if (qdio_free(ccw_device) != 0)
int retval = 0;
unsigned long flags;
+ zfcp_adapter_scsi_unregister(adapter);
device_unregister(&adapter->generic_services);
zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
dev_set_drvdata(&adapter->ccw_device->dev, NULL);
goto out;
}
+ zfcp_adapter_debug_unregister(adapter);
+
/* remove specified adapter data structure from list */
write_lock_irq(&zfcp_data.config_lock);
list_del(&adapter->list);
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_FC
-void
+static void
zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
struct fsf_status_read_buffer *status_buffer)
{
if (!port || (port->wwpn != (*(wwn_t *) &els_plogi->serv_param.wwpn))) {
ZFCP_LOG_DEBUG("ignored incoming PLOGI for nonexisting port "
- "with d_id 0x%08x on adapter %s\n",
+ "with d_id 0x%06x on adapter %s\n",
status_buffer->d_id,
zfcp_get_busid_by_adapter(adapter));
} else {
if (!port || (port->wwpn != els_logo->nport_wwpn)) {
ZFCP_LOG_DEBUG("ignored incoming LOGO for nonexisting port "
- "with d_id 0x%08x on adapter %s\n",
+ "with d_id 0x%06x on adapter %s\n",
status_buffer->d_id,
zfcp_get_busid_by_adapter(adapter));
} else {
data->ct.pool = pool;
}
} else {
- data = kmalloc(sizeof(struct zfcp_gid_pn_data), GFP_ATOMIC);
+ data = kmem_cache_alloc(zfcp_data.gid_pn_cache, GFP_ATOMIC);
}
if (NULL == data)
return -ENOMEM;
memset(data, 0, sizeof(*data));
+ sg_init_table(&data->req , 1);
+ sg_init_table(&data->resp , 1);
data->ct.req = &data->req;
data->ct.resp = &data->resp;
data->ct.req_count = data->ct.resp_count = 1;
- zfcp_address_to_sg(&data->ct_iu_req, &data->req);
- zfcp_address_to_sg(&data->ct_iu_resp, &data->resp);
- data->req.length = sizeof(struct ct_iu_gid_pn_req);
- data->resp.length = sizeof(struct ct_iu_gid_pn_resp);
+ zfcp_address_to_sg(&data->ct_iu_req, &data->req, sizeof(struct ct_iu_gid_pn_req));
+ zfcp_address_to_sg(&data->ct_iu_resp, &data->resp, sizeof(struct ct_iu_gid_pn_resp));
*gid_pn = data;
return 0;
* zfcp_gid_pn_buffers_free - free buffers for GID_PN nameserver request
* @gid_pn: pointer to struct zfcp_gid_pn_data which has to be freed
*/
-static void
-zfcp_gid_pn_buffers_free(struct zfcp_gid_pn_data *gid_pn)
+static void zfcp_gid_pn_buffers_free(struct zfcp_gid_pn_data *gid_pn)
{
- if ((gid_pn->ct.pool != 0))
+ if (gid_pn->ct.pool)
mempool_free(gid_pn, gid_pn->ct.pool);
else
- kfree(gid_pn);
-
- return;
+ kmem_cache_free(zfcp_data.gid_pn_cache, gid_pn);
}
/**
gid_pn->ct.handler = zfcp_ns_gid_pn_handler;
gid_pn->ct.handler_data = (unsigned long) gid_pn;
gid_pn->ct.timeout = ZFCP_NS_GID_PN_TIMEOUT;
- gid_pn->ct.timer = &erp_action->timer;
gid_pn->port = erp_action->port;
ret = zfcp_fsf_send_ct(&gid_pn->ct, adapter->pool.fsf_req_erp,
/* looks like a valid d_id */
port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK;
atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status);
- ZFCP_LOG_DEBUG("adapter %s: wwpn=0x%016Lx ---> d_id=0x%08x\n",
+ ZFCP_LOG_DEBUG("adapter %s: wwpn=0x%016Lx ---> d_id=0x%06x\n",
zfcp_get_busid_by_port(port), port->wwpn, port->d_id);
goto out;
* @code: reason code
* @rc_table: table of reason codes and descriptions
*/
-static inline const char *
+static const char *
zfcp_rc_description(u8 code, const struct zfcp_rc_entry *rc_table)
{
const char *descr = "unknown reason code";
* @rjt_par: reject parameter acc. to FC-PH/FC-FS
* @rc_table: table of reason codes and descriptions
*/
-static inline void
+static void
zfcp_print_els_rjt(struct zfcp_ls_rjt_par *rjt_par,
const struct zfcp_rc_entry *rc_table)
{