[PATCH v6 1/4] scsi: add ability to adjust module reference for scsi host

Akinobu Mita
2015-05-04T14:46:31Z

While accessing a scsi_device, the use count of the underlying LLDD module
is incremented. The module reference is retrieved through .module field of
struct scsi_host_template.

This mapping between scsi_device and underlying LLDD module works well
except ufs, unusual usb storage drivers, and sub drivers for esp_scsi.
These drivers consist with core driver and actual LLDDs, and
scsi_host_template is defined in the core driver. So the actual LLDDs can
be unloaded even if the scsi_device is being accessed.

This adds .module field in struct Scsi_Host and let the module reference
be retrieved though it instead of struct scsi_host_template. This allows
the actual LLDDs adjust module reference.

Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Cc: Vinayak Holikatti <vinholikatti@gmail.com>
Cc: Dolev Raviv <draviv@codeaurora.org>
Cc: Sujit Reddy Thumma <sthumma@codeaurora.org>
Cc: Subhash Jadavani <subhashj@codeaurora.org>
Cc: Christoph Hellwig <hch@lst.de>
Cc: "James E.J. Bottomley" <JBottomley@parallels.com>
Cc: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Hannes Reinecke <hare@suse.de>
Cc: linux-usb@vger.kernel.org
Cc: usb-storage@lists.one-eyed-alien.net
Cc: linux-scsi@vger.kernel.org
---
* Changes from v5
- Rebased as v5 doesn't apply cleanly to the latest tree anymore.

drivers/scsi/hosts.c | 1 +
drivers/scsi/scsi.c | 4 ++--
include/scsi/scsi_host.h | 1 +
3 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 8bb173e..21f1442 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -411,6 +411,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
*/
shost->max_cmd_len = 12;
shost->hostt = sht;
+ shost->module = sht->module;
shost->this_id = sht->this_id;
shost->can_queue = sht->can_queue;
shost->sg_tablesize = sht->sg_tablesize;
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 3833bf5..f7534a9 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -982,7 +982,7 @@ int scsi_device_get(struct scsi_device *sdev)
goto fail;
if (!get_device(&sdev->sdev_gendev))
goto fail;
- if (!try_module_get(sdev->host->hostt->module))
+ if (!try_module_get(sdev->host->module))
goto fail_put_device;
return 0;

@@ -1003,7 +1003,7 @@ EXPORT_SYMBOL(scsi_device_get);
*/
void scsi_device_put(struct scsi_device *sdev)
{
- module_put(sdev->host->hostt->module);
+ module_put(sdev->host->module);
put_device(&sdev->sdev_gendev);
}
EXPORT_SYMBOL(scsi_device_put);
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index e113c75..8742bfd 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -620,6 +620,7 @@ struct Scsi_Host {
*/
unsigned short max_cmd_len;

+ struct module *module;
int this_id;
int can_queue;
short cmd_per_lun;
--
1.9.1