Commit a4804cd6 authored by Mike Christie's avatar Mike Christie Committed by James Bottomley

[SCSI] iscsi: add iscsi host helpers

This finishes the host/session unbinding, by adding some helpers
to add and remove hosts and the session they manage.
Signed-off-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 75613521
...@@ -371,10 +371,8 @@ static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session) ...@@ -371,10 +371,8 @@ static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session)
{ {
struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
iscsi_session_teardown(cls_session); iscsi_host_remove(shost);
scsi_remove_host(shost); iscsi_host_free(shost);
iscsi_host_teardown(shost);
scsi_host_put(shost);
} }
static struct iscsi_cls_session * static struct iscsi_cls_session *
...@@ -396,7 +394,7 @@ iscsi_iser_session_create(struct Scsi_Host *shost, ...@@ -396,7 +394,7 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
return NULL; return NULL;
} }
shost = scsi_host_alloc(&iscsi_iser_sht, 0); shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISCSI_MAX_CMD_PER_LUN);
if (!shost) if (!shost)
return NULL; return NULL;
shost->transportt = iscsi_iser_scsi_transport; shost->transportt = iscsi_iser_scsi_transport;
...@@ -405,9 +403,7 @@ iscsi_iser_session_create(struct Scsi_Host *shost, ...@@ -405,9 +403,7 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
shost->max_channel = 0; shost->max_channel = 0;
shost->max_cmd_len = 16; shost->max_cmd_len = 16;
iscsi_host_setup(shost, qdepth); if (iscsi_host_add(shost, NULL))
if (scsi_add_host(shost, NULL))
goto free_host; goto free_host;
*hostno = shost->host_no; *hostno = shost->host_no;
...@@ -443,10 +439,9 @@ iscsi_iser_session_create(struct Scsi_Host *shost, ...@@ -443,10 +439,9 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
return cls_session; return cls_session;
remove_host: remove_host:
scsi_remove_host(shost); iscsi_host_remove(shost);
free_host: free_host:
iscsi_host_teardown(shost); iscsi_host_free(shost);
scsi_host_put(shost);
return NULL; return NULL;
} }
......
...@@ -1866,7 +1866,7 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, ...@@ -1866,7 +1866,7 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
return NULL; return NULL;
} }
shost = scsi_host_alloc(&iscsi_sht, sizeof(struct iscsi_host)); shost = iscsi_host_alloc(&iscsi_sht, 0, qdepth);
if (!shost) if (!shost)
return NULL; return NULL;
shost->transportt = iscsi_tcp_scsi_transport; shost->transportt = iscsi_tcp_scsi_transport;
...@@ -1874,10 +1874,9 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, ...@@ -1874,10 +1874,9 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
shost->max_id = 0; shost->max_id = 0;
shost->max_channel = 0; shost->max_channel = 0;
shost->max_cmd_len = 16; shost->max_cmd_len = 16;
shost->can_queue = cmds_max;
iscsi_host_setup(shost, qdepth); if (iscsi_host_add(shost, NULL))
if (scsi_add_host(shost, NULL))
goto free_host; goto free_host;
*hostno = shost->host_no; *hostno = shost->host_no;
...@@ -1912,10 +1911,9 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, ...@@ -1912,10 +1911,9 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
remove_session: remove_session:
iscsi_session_teardown(cls_session); iscsi_session_teardown(cls_session);
remove_host: remove_host:
scsi_remove_host(shost); iscsi_host_remove(shost);
free_host: free_host:
iscsi_host_teardown(shost); iscsi_host_free(shost);
scsi_host_put(shost);
return NULL; return NULL;
} }
...@@ -1924,11 +1922,9 @@ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session) ...@@ -1924,11 +1922,9 @@ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session)
struct Scsi_Host *shost = iscsi_session_to_shost(cls_session); struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
iscsi_r2tpool_free(cls_session->dd_data); iscsi_r2tpool_free(cls_session->dd_data);
iscsi_session_teardown(cls_session);
scsi_remove_host(shost); iscsi_host_remove(shost);
iscsi_host_teardown(shost); iscsi_host_free(shost);
scsi_host_put(shost);
} }
static int iscsi_tcp_slave_configure(struct scsi_device *sdev) static int iscsi_tcp_slave_configure(struct scsi_device *sdev)
......
...@@ -1764,8 +1764,39 @@ void iscsi_pool_free(struct iscsi_pool *q) ...@@ -1764,8 +1764,39 @@ void iscsi_pool_free(struct iscsi_pool *q)
} }
EXPORT_SYMBOL_GPL(iscsi_pool_free); EXPORT_SYMBOL_GPL(iscsi_pool_free);
void iscsi_host_setup(struct Scsi_Host *shost, uint16_t qdepth) /**
* iscsi_host_add - add host to system
* @shost: scsi host
* @pdev: parent device
*
* This should be called by partial offload and software iscsi drivers
* to add a host to the system.
*/
int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev)
{
return scsi_add_host(shost, pdev);
}
EXPORT_SYMBOL_GPL(iscsi_host_add);
/**
* iscsi_host_alloc - allocate a host and driver data
* @sht: scsi host template
* @dd_data_size: driver host data size
* @qdepth: default device queue depth
*
* This should be called by partial offload and software iscsi drivers.
* To access the driver specific memory use the iscsi_host_priv() macro.
*/
struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
int dd_data_size, uint16_t qdepth)
{ {
struct Scsi_Host *shost;
shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) + dd_data_size);
if (!shost)
return NULL;
shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) { if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) {
if (qdepth != 0) if (qdepth != 0)
printk(KERN_ERR "iscsi: invalid queue depth of %d. " printk(KERN_ERR "iscsi: invalid queue depth of %d. "
...@@ -1773,22 +1804,37 @@ void iscsi_host_setup(struct Scsi_Host *shost, uint16_t qdepth) ...@@ -1773,22 +1804,37 @@ void iscsi_host_setup(struct Scsi_Host *shost, uint16_t qdepth)
qdepth, ISCSI_MAX_CMD_PER_LUN); qdepth, ISCSI_MAX_CMD_PER_LUN);
qdepth = ISCSI_DEF_CMD_PER_LUN; qdepth = ISCSI_DEF_CMD_PER_LUN;
} }
shost->transportt->create_work_queue = 1;
shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
shost->cmd_per_lun = qdepth; shost->cmd_per_lun = qdepth;
return shost;
}
EXPORT_SYMBOL_GPL(iscsi_host_alloc);
/**
* iscsi_host_remove - remove host and sessions
* @shost: scsi host
*
* This will also remove any sessions attached to the host, but if userspace
* is managing the session at the same time this will break. TODO: add
* refcounting to the netlink iscsi interface so a rmmod or host hot unplug
* does not remove the memory from under us.
*/
void iscsi_host_remove(struct Scsi_Host *shost)
{
iscsi_host_for_each_session(shost, iscsi_session_teardown);
scsi_remove_host(shost);
} }
EXPORT_SYMBOL_GPL(iscsi_host_setup); EXPORT_SYMBOL_GPL(iscsi_host_remove);
void iscsi_host_teardown(struct Scsi_Host *shost) void iscsi_host_free(struct Scsi_Host *shost)
{ {
struct iscsi_host *ihost = shost_priv(shost); struct iscsi_host *ihost = shost_priv(shost);
kfree(ihost->netdev); kfree(ihost->netdev);
kfree(ihost->hwaddress); kfree(ihost->hwaddress);
kfree(ihost->initiatorname); kfree(ihost->initiatorname);
scsi_host_put(shost);
} }
EXPORT_SYMBOL_GPL(iscsi_host_teardown); EXPORT_SYMBOL_GPL(iscsi_host_free);
/** /**
* iscsi_session_setup - create iscsi cls session and host and session * iscsi_session_setup - create iscsi cls session and host and session
......
...@@ -279,6 +279,24 @@ static int iscsi_is_session_dev(const struct device *dev) ...@@ -279,6 +279,24 @@ static int iscsi_is_session_dev(const struct device *dev)
return dev->release == iscsi_session_release; return dev->release == iscsi_session_release;
} }
static int iscsi_iter_session_fn(struct device *dev, void *data)
{
void (* fn) (struct iscsi_cls_session *) = data;
if (!iscsi_is_session_dev(dev))
return 0;
fn(iscsi_dev_to_session(dev));
return 0;
}
void iscsi_host_for_each_session(struct Scsi_Host *shost,
void (*fn)(struct iscsi_cls_session *))
{
device_for_each_child(&shost->shost_gendev, fn,
iscsi_iter_session_fn);
}
EXPORT_SYMBOL_GPL(iscsi_host_for_each_session);
/** /**
* iscsi_scan_finished - helper to report when running scans are done * iscsi_scan_finished - helper to report when running scans are done
* @shost: scsi host * @shost: scsi host
...@@ -1599,6 +1617,8 @@ iscsi_register_transport(struct iscsi_transport *tt) ...@@ -1599,6 +1617,8 @@ iscsi_register_transport(struct iscsi_transport *tt)
priv->daemon_pid = -1; priv->daemon_pid = -1;
priv->iscsi_transport = tt; priv->iscsi_transport = tt;
priv->t.user_scan = iscsi_user_scan; priv->t.user_scan = iscsi_user_scan;
if (!(tt->caps & CAP_DATA_PATH_OFFLOAD))
priv->t.create_work_queue = 1;
priv->dev.class = &iscsi_transport_class; priv->dev.class = &iscsi_transport_class;
snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%s", tt->name); snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%s", tt->name);
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include <scsi/iscsi_if.h> #include <scsi/iscsi_if.h>
struct scsi_transport_template; struct scsi_transport_template;
struct scsi_host_template;
struct scsi_device; struct scsi_device;
struct Scsi_Host; struct Scsi_Host;
struct scsi_cmnd; struct scsi_cmnd;
...@@ -41,6 +42,7 @@ struct iscsi_cls_session; ...@@ -41,6 +42,7 @@ struct iscsi_cls_session;
struct iscsi_cls_conn; struct iscsi_cls_conn;
struct iscsi_session; struct iscsi_session;
struct iscsi_nopin; struct iscsi_nopin;
struct device;
/* #define DEBUG_SCSI */ /* #define DEBUG_SCSI */
#ifdef DEBUG_SCSI #ifdef DEBUG_SCSI
...@@ -311,6 +313,8 @@ struct iscsi_host { ...@@ -311,6 +313,8 @@ struct iscsi_host {
char local_address[ISCSI_ADDRESS_BUF_LEN]; char local_address[ISCSI_ADDRESS_BUF_LEN];
}; };
#define iscsi_host_priv(_shost) \
(shost_priv(_shost) + sizeof(struct iscsi_host))
/* /*
* scsi host template * scsi host template
*/ */
...@@ -330,8 +334,11 @@ extern int iscsi_host_set_param(struct Scsi_Host *shost, ...@@ -330,8 +334,11 @@ extern int iscsi_host_set_param(struct Scsi_Host *shost,
int buflen); int buflen);
extern int iscsi_host_get_param(struct Scsi_Host *shost, extern int iscsi_host_get_param(struct Scsi_Host *shost,
enum iscsi_host_param param, char *buf); enum iscsi_host_param param, char *buf);
extern void iscsi_host_setup(struct Scsi_Host *shost, uint16_t qdepth); extern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev);
extern void iscsi_host_teardown(struct Scsi_Host *shost); extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
int dd_data_size, uint16_t qdepth);
extern void iscsi_host_remove(struct Scsi_Host *shost);
extern void iscsi_host_free(struct Scsi_Host *shost);
/* /*
* session management * session management
......
...@@ -207,6 +207,10 @@ struct iscsi_cls_host { ...@@ -207,6 +207,10 @@ struct iscsi_cls_host {
char scan_workq_name[KOBJ_NAME_LEN]; char scan_workq_name[KOBJ_NAME_LEN];
}; };
extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
void (*fn)(struct iscsi_cls_session *));
/* /*
* session and connection functions that can be used by HW iSCSI LLDs * session and connection functions that can be used by HW iSCSI LLDs
*/ */
......
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