2006-11-16 13:24:13 +03:00
/*
* SCSI target lib functions
*
* Copyright ( C ) 2005 Mike Christie < michaelc @ cs . wisc . edu >
* Copyright ( C ) 2005 FUJITA Tomonori < tomof @ acm . org >
*
* 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 of the
* License , 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 . , 51 Franklin St , Fifth Floor , Boston , MA
* 02110 - 1301 USA
*/
# include <linux/blkdev.h>
# include <linux/hash.h>
# include <linux/module.h>
# include <linux/pagemap.h>
# include <scsi/scsi.h>
# include <scsi/scsi_cmnd.h>
# include <scsi/scsi_device.h>
# include <scsi/scsi_host.h>
2007-07-11 10:08:17 +04:00
# include <scsi/scsi_transport.h>
2006-11-16 13:24:13 +03:00
# include <scsi/scsi_tgt.h>
# include "scsi_tgt_priv.h"
static struct workqueue_struct * scsi_tgtd ;
2006-12-07 07:33:20 +03:00
static struct kmem_cache * scsi_tgt_cmd_cache ;
2006-11-16 13:24:13 +03:00
/*
* TODO : this struct will be killed when the block layer supports large bios
* and James ' s work struct code is in
*/
struct scsi_tgt_cmd {
/* TODO replace work with James b's code */
struct work_struct work ;
2007-03-03 03:55:54 +03:00
/* TODO fix limits of some drivers */
struct bio * bio ;
2006-11-16 13:24:13 +03:00
struct list_head hash_list ;
struct request * rq ;
2007-07-11 10:08:17 +04:00
u64 itn_id ;
2006-11-16 13:24:13 +03:00
u64 tag ;
} ;
# define TGT_HASH_ORDER 4
# define cmd_hashfn(tag) hash_long((unsigned long) (tag), TGT_HASH_ORDER)
struct scsi_tgt_queuedata {
struct Scsi_Host * shost ;
struct list_head cmd_hash [ 1 < < TGT_HASH_ORDER ] ;
spinlock_t cmd_hash_lock ;
} ;
/*
* Function : scsi_host_get_command ( )
*
* Purpose : Allocate and setup a scsi command block and blk request
*
* Arguments : shost - scsi host
* data_dir - dma data dir
* gfp_mask - allocator flags
*
* Returns : The allocated scsi command structure .
*
* This should be called by target LLDs to get a command .
*/
struct scsi_cmnd * scsi_host_get_command ( struct Scsi_Host * shost ,
enum dma_data_direction data_dir ,
gfp_t gfp_mask )
{
int write = ( data_dir = = DMA_TO_DEVICE ) ;
struct request * rq ;
struct scsi_cmnd * cmd ;
struct scsi_tgt_cmd * tcmd ;
/* Bail if we can't get a reference to the device */
if ( ! get_device ( & shost - > shost_gendev ) )
return NULL ;
tcmd = kmem_cache_alloc ( scsi_tgt_cmd_cache , GFP_ATOMIC ) ;
if ( ! tcmd )
goto put_dev ;
2007-03-03 03:55:54 +03:00
/*
* The blk helpers are used to the READ / WRITE requests
* transfering data from a initiator point of view . Since
* we are in target mode we want the opposite .
*/
rq = blk_get_request ( shost - > uspace_req_q , ! write , gfp_mask ) ;
2006-11-16 13:24:13 +03:00
if ( ! rq )
goto free_tcmd ;
cmd = __scsi_get_command ( shost , gfp_mask ) ;
if ( ! cmd )
goto release_rq ;
cmd - > sc_data_direction = data_dir ;
cmd - > jiffies_at_alloc = jiffies ;
cmd - > request = rq ;
2008-04-30 12:19:47 +04:00
cmd - > cmnd = rq - > cmd ;
2006-11-16 13:24:13 +03:00
rq - > special = cmd ;
rq - > cmd_type = REQ_TYPE_SPECIAL ;
rq - > cmd_flags | = REQ_TYPE_BLOCK_PC ;
rq - > end_io_data = tcmd ;
tcmd - > rq = rq ;
return cmd ;
release_rq :
blk_put_request ( rq ) ;
free_tcmd :
kmem_cache_free ( scsi_tgt_cmd_cache , tcmd ) ;
put_dev :
put_device ( & shost - > shost_gendev ) ;
return NULL ;
}
EXPORT_SYMBOL_GPL ( scsi_host_get_command ) ;
/*
* Function : scsi_host_put_command ( )
*
* Purpose : Free a scsi command block
*
* Arguments : shost - scsi host
* cmd - command block to free
*
* Returns : Nothing .
*
* Notes : The command must not belong to any lists .
*/
void scsi_host_put_command ( struct Scsi_Host * shost , struct scsi_cmnd * cmd )
{
struct request_queue * q = shost - > uspace_req_q ;
struct request * rq = cmd - > request ;
struct scsi_tgt_cmd * tcmd = rq - > end_io_data ;
unsigned long flags ;
kmem_cache_free ( scsi_tgt_cmd_cache , tcmd ) ;
spin_lock_irqsave ( q - > queue_lock , flags ) ;
__blk_put_request ( q , rq ) ;
spin_unlock_irqrestore ( q - > queue_lock , flags ) ;
__scsi_put_command ( shost , cmd , & shost - > shost_gendev ) ;
}
EXPORT_SYMBOL_GPL ( scsi_host_put_command ) ;
static void cmd_hashlist_del ( struct scsi_cmnd * cmd )
{
struct request_queue * q = cmd - > request - > q ;
struct scsi_tgt_queuedata * qdata = q - > queuedata ;
unsigned long flags ;
struct scsi_tgt_cmd * tcmd = cmd - > request - > end_io_data ;
spin_lock_irqsave ( & qdata - > cmd_hash_lock , flags ) ;
list_del ( & tcmd - > hash_list ) ;
spin_unlock_irqrestore ( & qdata - > cmd_hash_lock , flags ) ;
}
2007-03-03 03:55:54 +03:00
static void scsi_unmap_user_pages ( struct scsi_tgt_cmd * tcmd )
{
blk_rq_unmap_user ( tcmd - > bio ) ;
}
2006-12-06 18:02:26 +03:00
static void scsi_tgt_cmd_destroy ( struct work_struct * work )
2006-11-16 13:24:13 +03:00
{
2006-12-06 18:02:26 +03:00
struct scsi_tgt_cmd * tcmd =
container_of ( work , struct scsi_tgt_cmd , work ) ;
struct scsi_cmnd * cmd = tcmd - > rq - > special ;
2006-11-16 13:24:13 +03:00
[SCSI] tgt: fix build when dprintk is defined
Fix scsi_tgt_lib build when dprintk is defined:
Also fix accessors problem when dprintk is defined
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_cmd_destroy':
drivers/scsi/scsi_tgt_lib.c:183: warning: format '%lu' expects type 'long unsigned int', but argument 6 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_cmd_done':
drivers/scsi/scsi_tgt_lib.c:330: warning: format '%lu' expects type 'long unsigned int', but argument 5 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_transfer_response':
drivers/scsi/scsi_tgt_lib.c:345: warning: format '%lu' expects type 'long unsigned int', but argument 5 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_init_cmd':
drivers/scsi/scsi_tgt_lib.c:368: warning: format '%lu' expects type 'long unsigned int', but argument 6 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_kspace_exec':
drivers/scsi/scsi_tgt_lib.c:499: warning: format '%lu' expects type 'long unsigned int', but argument 9 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_kspace_it_nexus_rsp':
drivers/scsi/scsi_tgt_lib.c:620: error: 'mid' undeclared (first use in this function)
drivers/scsi/scsi_tgt_lib.c:620: error: (Each undeclared identifier is reported only once
drivers/scsi/scsi_tgt_lib.c:620: error: for each function it appears in.)
make[2]: *** [drivers/scsi/scsi_tgt_lib.o] Error 1
[tomo:
> - dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid);
> + dprintk("%d %d\n", host_no, result);
'mid' is a typo. I wanted to do:
dprintk("%d %d %llx\n", host_no, result, (unsigned long long)itn_id);
The rest looks ok. Thanks,
]
Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Acked-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
2007-11-15 12:53:25 +03:00
dprintk ( " cmd %p %d %u \n " , cmd , cmd - > sc_data_direction ,
2006-11-16 13:24:13 +03:00
rq_data_dir ( cmd - > request ) ) ;
scsi_unmap_user_pages ( tcmd ) ;
scsi_host_put_command ( scsi_tgt_cmd_to_host ( cmd ) , cmd ) ;
}
static void init_scsi_tgt_cmd ( struct request * rq , struct scsi_tgt_cmd * tcmd ,
2007-07-11 10:08:17 +04:00
u64 itn_id , u64 tag )
2006-11-16 13:24:13 +03:00
{
struct scsi_tgt_queuedata * qdata = rq - > q - > queuedata ;
unsigned long flags ;
struct list_head * head ;
2007-07-11 10:08:17 +04:00
tcmd - > itn_id = itn_id ;
2006-11-16 13:24:13 +03:00
tcmd - > tag = tag ;
2007-03-03 03:55:54 +03:00
tcmd - > bio = NULL ;
2006-12-06 18:02:26 +03:00
INIT_WORK ( & tcmd - > work , scsi_tgt_cmd_destroy ) ;
2006-11-16 13:24:13 +03:00
spin_lock_irqsave ( & qdata - > cmd_hash_lock , flags ) ;
head = & qdata - > cmd_hash [ cmd_hashfn ( tag ) ] ;
list_add ( & tcmd - > hash_list , head ) ;
spin_unlock_irqrestore ( & qdata - > cmd_hash_lock , flags ) ;
}
/*
* scsi_tgt_alloc_queue - setup queue used for message passing
* shost : scsi host
*
* This should be called by the LLD after host allocation .
* And will be released when the host is released .
*/
int scsi_tgt_alloc_queue ( struct Scsi_Host * shost )
{
struct scsi_tgt_queuedata * queuedata ;
struct request_queue * q ;
int err , i ;
/*
* Do we need to send a netlink event or should uspace
* just respond to the hotplug event ?
*/
q = __scsi_alloc_queue ( shost , NULL ) ;
if ( ! q )
return - ENOMEM ;
queuedata = kzalloc ( sizeof ( * queuedata ) , GFP_KERNEL ) ;
if ( ! queuedata ) {
err = - ENOMEM ;
goto cleanup_queue ;
}
queuedata - > shost = shost ;
q - > queuedata = queuedata ;
/*
* this is a silly hack . We should probably just queue as many
* command as is recvd to userspace . uspace can then make
* sure we do not overload the HBA
*/
2007-08-31 21:02:16 +04:00
q - > nr_requests = shost - > can_queue ;
2006-11-16 13:24:13 +03:00
/*
* We currently only support software LLDs so this does
* not matter for now . Do we need this for the cards we support ?
* If so we should make it a host template value .
*/
blk_queue_dma_alignment ( q , 0 ) ;
shost - > uspace_req_q = q ;
for ( i = 0 ; i < ARRAY_SIZE ( queuedata - > cmd_hash ) ; i + + )
INIT_LIST_HEAD ( & queuedata - > cmd_hash [ i ] ) ;
spin_lock_init ( & queuedata - > cmd_hash_lock ) ;
return 0 ;
cleanup_queue :
blk_cleanup_queue ( q ) ;
return err ;
}
EXPORT_SYMBOL_GPL ( scsi_tgt_alloc_queue ) ;
void scsi_tgt_free_queue ( struct Scsi_Host * shost )
{
int i ;
unsigned long flags ;
struct request_queue * q = shost - > uspace_req_q ;
struct scsi_cmnd * cmd ;
struct scsi_tgt_queuedata * qdata = q - > queuedata ;
struct scsi_tgt_cmd * tcmd , * n ;
LIST_HEAD ( cmds ) ;
spin_lock_irqsave ( & qdata - > cmd_hash_lock , flags ) ;
for ( i = 0 ; i < ARRAY_SIZE ( qdata - > cmd_hash ) ; i + + ) {
list_for_each_entry_safe ( tcmd , n , & qdata - > cmd_hash [ i ] ,
hash_list ) {
list_del ( & tcmd - > hash_list ) ;
list_add ( & tcmd - > hash_list , & cmds ) ;
}
}
spin_unlock_irqrestore ( & qdata - > cmd_hash_lock , flags ) ;
while ( ! list_empty ( & cmds ) ) {
tcmd = list_entry ( cmds . next , struct scsi_tgt_cmd , hash_list ) ;
list_del ( & tcmd - > hash_list ) ;
cmd = tcmd - > rq - > special ;
shost - > hostt - > eh_abort_handler ( cmd ) ;
2006-12-06 18:02:26 +03:00
scsi_tgt_cmd_destroy ( & tcmd - > work ) ;
2006-11-16 13:24:13 +03:00
}
}
EXPORT_SYMBOL_GPL ( scsi_tgt_free_queue ) ;
struct Scsi_Host * scsi_tgt_cmd_to_host ( struct scsi_cmnd * cmd )
{
struct scsi_tgt_queuedata * queue = cmd - > request - > q - > queuedata ;
return queue - > shost ;
}
EXPORT_SYMBOL_GPL ( scsi_tgt_cmd_to_host ) ;
/*
* scsi_tgt_queue_command - queue command for userspace processing
* @ cmd : scsi command
* @ scsilun : scsi lun
* @ tag : unique value to identify this command for tmf
*/
2007-07-11 10:08:17 +04:00
int scsi_tgt_queue_command ( struct scsi_cmnd * cmd , u64 itn_id ,
struct scsi_lun * scsilun , u64 tag )
2006-11-16 13:24:13 +03:00
{
struct scsi_tgt_cmd * tcmd = cmd - > request - > end_io_data ;
int err ;
2007-07-11 10:08:17 +04:00
init_scsi_tgt_cmd ( cmd - > request , tcmd , itn_id , tag ) ;
err = scsi_tgt_uspace_send_cmd ( cmd , itn_id , scsilun , tag ) ;
2006-11-16 13:24:13 +03:00
if ( err )
cmd_hashlist_del ( cmd ) ;
return err ;
}
EXPORT_SYMBOL_GPL ( scsi_tgt_queue_command ) ;
/*
2008-02-03 18:28:22 +03:00
* This is run from a interrupt handler normally and the unmap
2006-11-16 13:24:13 +03:00
* needs process context so we must queue
*/
static void scsi_tgt_cmd_done ( struct scsi_cmnd * cmd )
{
struct scsi_tgt_cmd * tcmd = cmd - > request - > end_io_data ;
[SCSI] tgt: fix build when dprintk is defined
Fix scsi_tgt_lib build when dprintk is defined:
Also fix accessors problem when dprintk is defined
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_cmd_destroy':
drivers/scsi/scsi_tgt_lib.c:183: warning: format '%lu' expects type 'long unsigned int', but argument 6 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_cmd_done':
drivers/scsi/scsi_tgt_lib.c:330: warning: format '%lu' expects type 'long unsigned int', but argument 5 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_transfer_response':
drivers/scsi/scsi_tgt_lib.c:345: warning: format '%lu' expects type 'long unsigned int', but argument 5 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_init_cmd':
drivers/scsi/scsi_tgt_lib.c:368: warning: format '%lu' expects type 'long unsigned int', but argument 6 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_kspace_exec':
drivers/scsi/scsi_tgt_lib.c:499: warning: format '%lu' expects type 'long unsigned int', but argument 9 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_kspace_it_nexus_rsp':
drivers/scsi/scsi_tgt_lib.c:620: error: 'mid' undeclared (first use in this function)
drivers/scsi/scsi_tgt_lib.c:620: error: (Each undeclared identifier is reported only once
drivers/scsi/scsi_tgt_lib.c:620: error: for each function it appears in.)
make[2]: *** [drivers/scsi/scsi_tgt_lib.o] Error 1
[tomo:
> - dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid);
> + dprintk("%d %d\n", host_no, result);
'mid' is a typo. I wanted to do:
dprintk("%d %d %llx\n", host_no, result, (unsigned long long)itn_id);
The rest looks ok. Thanks,
]
Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Acked-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
2007-11-15 12:53:25 +03:00
dprintk ( " cmd %p %u \n " , cmd , rq_data_dir ( cmd - > request ) ) ;
2006-11-16 13:24:13 +03:00
2007-07-11 10:08:17 +04:00
scsi_tgt_uspace_send_status ( cmd , tcmd - > itn_id , tcmd - > tag ) ;
2007-03-03 03:55:54 +03:00
2007-12-14 03:14:27 +03:00
scsi_release_buffers ( cmd ) ;
2007-03-03 03:55:54 +03:00
2006-11-16 13:24:13 +03:00
queue_work ( scsi_tgtd , & tcmd - > work ) ;
}
2007-03-03 03:55:54 +03:00
static int scsi_tgt_transfer_response ( struct scsi_cmnd * cmd )
2006-11-16 13:24:13 +03:00
{
struct Scsi_Host * shost = scsi_tgt_cmd_to_host ( cmd ) ;
int err ;
[SCSI] tgt: fix build when dprintk is defined
Fix scsi_tgt_lib build when dprintk is defined:
Also fix accessors problem when dprintk is defined
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_cmd_destroy':
drivers/scsi/scsi_tgt_lib.c:183: warning: format '%lu' expects type 'long unsigned int', but argument 6 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_cmd_done':
drivers/scsi/scsi_tgt_lib.c:330: warning: format '%lu' expects type 'long unsigned int', but argument 5 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_transfer_response':
drivers/scsi/scsi_tgt_lib.c:345: warning: format '%lu' expects type 'long unsigned int', but argument 5 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_init_cmd':
drivers/scsi/scsi_tgt_lib.c:368: warning: format '%lu' expects type 'long unsigned int', but argument 6 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_kspace_exec':
drivers/scsi/scsi_tgt_lib.c:499: warning: format '%lu' expects type 'long unsigned int', but argument 9 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_kspace_it_nexus_rsp':
drivers/scsi/scsi_tgt_lib.c:620: error: 'mid' undeclared (first use in this function)
drivers/scsi/scsi_tgt_lib.c:620: error: (Each undeclared identifier is reported only once
drivers/scsi/scsi_tgt_lib.c:620: error: for each function it appears in.)
make[2]: *** [drivers/scsi/scsi_tgt_lib.o] Error 1
[tomo:
> - dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid);
> + dprintk("%d %d\n", host_no, result);
'mid' is a typo. I wanted to do:
dprintk("%d %d %llx\n", host_no, result, (unsigned long long)itn_id);
The rest looks ok. Thanks,
]
Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Acked-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
2007-11-15 12:53:25 +03:00
dprintk ( " cmd %p %u \n " , cmd , rq_data_dir ( cmd - > request ) ) ;
2006-11-16 13:24:13 +03:00
err = shost - > hostt - > transfer_response ( cmd , scsi_tgt_cmd_done ) ;
switch ( err ) {
case SCSI_MLQUEUE_HOST_BUSY :
case SCSI_MLQUEUE_DEVICE_BUSY :
return - EAGAIN ;
}
return 0 ;
}
/* TODO: test this crap and replace bio_map_user with new interface maybe */
static int scsi_map_user_pages ( struct scsi_tgt_cmd * tcmd , struct scsi_cmnd * cmd ,
2007-03-03 03:55:54 +03:00
unsigned long uaddr , unsigned int len , int rw )
2006-11-16 13:24:13 +03:00
{
struct request_queue * q = cmd - > request - > q ;
struct request * rq = cmd - > request ;
int err ;
2007-03-03 03:55:54 +03:00
dprintk ( " %lx %u \n " , uaddr , len ) ;
2008-08-28 11:17:06 +04:00
err = blk_rq_map_user ( q , rq , NULL , ( void * ) uaddr , len , GFP_KERNEL ) ;
2007-03-03 03:55:54 +03:00
if ( err ) {
2006-11-16 13:24:13 +03:00
/*
2007-03-03 03:55:54 +03:00
* TODO : need to fixup sg_tablesize , max_segment_size ,
* max_sectors , etc for modern HW and software drivers
* where this value is bogus .
*
* TODO2 : we can alloc a reserve buffer of max size
* we can handle and do the slow copy path for really large
* IO .
2006-11-16 13:24:13 +03:00
*/
2007-03-03 03:55:54 +03:00
eprintk ( " Could not handle request of size %u. \n " , len ) ;
return err ;
2006-11-16 13:24:13 +03:00
}
2007-03-03 03:55:54 +03:00
tcmd - > bio = rq - > bio ;
2007-12-14 03:14:27 +03:00
err = scsi_init_io ( cmd , GFP_KERNEL ) ;
if ( err ) {
scsi_release_buffers ( cmd ) ;
2007-03-03 03:55:54 +03:00
goto unmap_rq ;
2007-12-14 03:14:27 +03:00
}
2008-03-01 09:36:36 +03:00
/*
* we use REQ_TYPE_BLOCK_PC so scsi_init_io doesn ' t set the
* length for us .
*/
cmd - > sdb . length = rq - > data_len ;
2006-11-16 13:24:13 +03:00
return 0 ;
2007-03-03 03:55:54 +03:00
unmap_rq :
scsi_unmap_user_pages ( tcmd ) ;
2006-11-16 13:24:13 +03:00
return err ;
}
static int scsi_tgt_copy_sense ( struct scsi_cmnd * cmd , unsigned long uaddr ,
unsigned len )
{
char __user * p = ( char __user * ) uaddr ;
if ( copy_from_user ( cmd - > sense_buffer , p ,
min_t ( unsigned , SCSI_SENSE_BUFFERSIZE , len ) ) ) {
printk ( KERN_ERR " Could not copy the sense buffer \n " ) ;
return - EIO ;
}
return 0 ;
}
static int scsi_tgt_abort_cmd ( struct Scsi_Host * shost , struct scsi_cmnd * cmd )
{
2006-12-06 18:02:26 +03:00
struct scsi_tgt_cmd * tcmd ;
2006-11-16 13:24:13 +03:00
int err ;
err = shost - > hostt - > eh_abort_handler ( cmd ) ;
if ( err )
eprintk ( " fail to abort %p \n " , cmd ) ;
2006-12-06 18:02:26 +03:00
tcmd = cmd - > request - > end_io_data ;
scsi_tgt_cmd_destroy ( & tcmd - > work ) ;
2006-11-16 13:24:13 +03:00
return err ;
}
static struct request * tgt_cmd_hash_lookup ( struct request_queue * q , u64 tag )
{
struct scsi_tgt_queuedata * qdata = q - > queuedata ;
struct request * rq = NULL ;
struct list_head * head ;
struct scsi_tgt_cmd * tcmd ;
unsigned long flags ;
head = & qdata - > cmd_hash [ cmd_hashfn ( tag ) ] ;
spin_lock_irqsave ( & qdata - > cmd_hash_lock , flags ) ;
list_for_each_entry ( tcmd , head , hash_list ) {
if ( tcmd - > tag = = tag ) {
rq = tcmd - > rq ;
list_del ( & tcmd - > hash_list ) ;
break ;
}
}
spin_unlock_irqrestore ( & qdata - > cmd_hash_lock , flags ) ;
return rq ;
}
2007-07-11 10:08:17 +04:00
int scsi_tgt_kspace_exec ( int host_no , u64 itn_id , int result , u64 tag ,
2007-03-03 03:55:54 +03:00
unsigned long uaddr , u32 len , unsigned long sense_uaddr ,
u32 sense_len , u8 rw )
2006-11-16 13:24:13 +03:00
{
struct Scsi_Host * shost ;
struct scsi_cmnd * cmd ;
struct request * rq ;
struct scsi_tgt_cmd * tcmd ;
int err = 0 ;
dprintk ( " %d %llu %d %u %lx %u \n " , host_no , ( unsigned long long ) tag ,
result , len , uaddr , rw ) ;
/* TODO: replace with a O(1) alg */
shost = scsi_host_lookup ( host_no ) ;
2008-08-08 04:49:30 +04:00
if ( ! shost ) {
2006-11-16 13:24:13 +03:00
printk ( KERN_ERR " Could not find host no %d \n " , host_no ) ;
return - EINVAL ;
}
if ( ! shost - > uspace_req_q ) {
printk ( KERN_ERR " Not target scsi host %d \n " , host_no ) ;
goto done ;
}
rq = tgt_cmd_hash_lookup ( shost - > uspace_req_q , tag ) ;
if ( ! rq ) {
printk ( KERN_ERR " Could not find tag %llu \n " ,
( unsigned long long ) tag ) ;
err = - EINVAL ;
goto done ;
}
cmd = rq - > special ;
[SCSI] tgt: fix build when dprintk is defined
Fix scsi_tgt_lib build when dprintk is defined:
Also fix accessors problem when dprintk is defined
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_cmd_destroy':
drivers/scsi/scsi_tgt_lib.c:183: warning: format '%lu' expects type 'long unsigned int', but argument 6 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_cmd_done':
drivers/scsi/scsi_tgt_lib.c:330: warning: format '%lu' expects type 'long unsigned int', but argument 5 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_transfer_response':
drivers/scsi/scsi_tgt_lib.c:345: warning: format '%lu' expects type 'long unsigned int', but argument 5 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_init_cmd':
drivers/scsi/scsi_tgt_lib.c:368: warning: format '%lu' expects type 'long unsigned int', but argument 6 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_kspace_exec':
drivers/scsi/scsi_tgt_lib.c:499: warning: format '%lu' expects type 'long unsigned int', but argument 9 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_kspace_it_nexus_rsp':
drivers/scsi/scsi_tgt_lib.c:620: error: 'mid' undeclared (first use in this function)
drivers/scsi/scsi_tgt_lib.c:620: error: (Each undeclared identifier is reported only once
drivers/scsi/scsi_tgt_lib.c:620: error: for each function it appears in.)
make[2]: *** [drivers/scsi/scsi_tgt_lib.o] Error 1
[tomo:
> - dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid);
> + dprintk("%d %d\n", host_no, result);
'mid' is a typo. I wanted to do:
dprintk("%d %d %llx\n", host_no, result, (unsigned long long)itn_id);
The rest looks ok. Thanks,
]
Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Acked-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
2007-11-15 12:53:25 +03:00
dprintk ( " cmd %p scb %x result %d len %d bufflen %u %u %x \n " ,
cmd , cmd - > cmnd [ 0 ] , result , len , scsi_bufflen ( cmd ) ,
2007-03-03 03:55:54 +03:00
rq_data_dir ( rq ) , cmd - > cmnd [ 0 ] ) ;
2006-11-16 13:24:13 +03:00
if ( result = = TASK_ABORTED ) {
scsi_tgt_abort_cmd ( shost , cmd ) ;
goto done ;
}
/*
* store the userspace values here , the working values are
* in the request_ * values
*/
tcmd = cmd - > request - > end_io_data ;
cmd - > result = result ;
2007-03-03 03:55:54 +03:00
if ( cmd - > result = = SAM_STAT_CHECK_CONDITION )
scsi_tgt_copy_sense ( cmd , sense_uaddr , sense_len ) ;
2006-11-16 13:24:13 +03:00
2007-03-03 03:55:54 +03:00
if ( len ) {
err = scsi_map_user_pages ( rq - > end_io_data , cmd , uaddr , len , rw ) ;
if ( err ) {
2007-03-03 03:55:55 +03:00
/*
* user - space daemon bugs or OOM
* TODO : we can do better for OOM .
*/
2007-03-13 04:07:15 +03:00
struct scsi_tgt_queuedata * qdata ;
struct list_head * head ;
unsigned long flags ;
2007-03-03 03:55:55 +03:00
eprintk ( " cmd %p ret %d uaddr %lx len %d rw %d \n " ,
cmd , err , uaddr , len , rw ) ;
2007-03-13 04:07:15 +03:00
qdata = shost - > uspace_req_q - > queuedata ;
head = & qdata - > cmd_hash [ cmd_hashfn ( tcmd - > tag ) ] ;
spin_lock_irqsave ( & qdata - > cmd_hash_lock , flags ) ;
list_add ( & tcmd - > hash_list , head ) ;
spin_unlock_irqrestore ( & qdata - > cmd_hash_lock , flags ) ;
goto done ;
2007-03-03 03:55:54 +03:00
}
2006-11-16 13:24:13 +03:00
}
2007-03-03 03:55:54 +03:00
err = scsi_tgt_transfer_response ( cmd ) ;
2006-11-16 13:24:13 +03:00
done :
scsi_host_put ( shost ) ;
return err ;
}
2007-07-11 10:08:17 +04:00
int scsi_tgt_tsk_mgmt_request ( struct Scsi_Host * shost , u64 itn_id ,
int function , u64 tag , struct scsi_lun * scsilun ,
void * data )
2006-11-16 13:24:13 +03:00
{
int err ;
/* TODO: need to retry if this fails. */
2007-07-11 10:08:17 +04:00
err = scsi_tgt_uspace_send_tsk_mgmt ( shost - > host_no , itn_id ,
function , tag , scsilun , data ) ;
2006-11-16 13:24:13 +03:00
if ( err < 0 )
eprintk ( " The task management request lost! \n " ) ;
return err ;
}
EXPORT_SYMBOL_GPL ( scsi_tgt_tsk_mgmt_request ) ;
2007-07-11 10:08:17 +04:00
int scsi_tgt_kspace_tsk_mgmt ( int host_no , u64 itn_id , u64 mid , int result )
2006-11-16 13:24:13 +03:00
{
struct Scsi_Host * shost ;
int err = - EINVAL ;
dprintk ( " %d %d %llx \n " , host_no , result , ( unsigned long long ) mid ) ;
shost = scsi_host_lookup ( host_no ) ;
2008-08-08 04:49:30 +04:00
if ( ! shost ) {
2006-11-16 13:24:13 +03:00
printk ( KERN_ERR " Could not find host no %d \n " , host_no ) ;
return err ;
}
if ( ! shost - > uspace_req_q ) {
printk ( KERN_ERR " Not target scsi host %d \n " , host_no ) ;
goto done ;
}
2007-07-11 10:08:22 +04:00
err = shost - > transportt - > tsk_mgmt_response ( shost , itn_id , mid , result ) ;
2007-07-11 10:08:17 +04:00
done :
scsi_host_put ( shost ) ;
return err ;
}
int scsi_tgt_it_nexus_create ( struct Scsi_Host * shost , u64 itn_id ,
char * initiator )
{
int err ;
/* TODO: need to retry if this fails. */
err = scsi_tgt_uspace_send_it_nexus_request ( shost - > host_no , itn_id , 0 ,
initiator ) ;
if ( err < 0 )
eprintk ( " The i_t_neuxs request lost, %d %llx! \n " ,
shost - > host_no , ( unsigned long long ) itn_id ) ;
return err ;
}
EXPORT_SYMBOL_GPL ( scsi_tgt_it_nexus_create ) ;
int scsi_tgt_it_nexus_destroy ( struct Scsi_Host * shost , u64 itn_id )
{
int err ;
/* TODO: need to retry if this fails. */
err = scsi_tgt_uspace_send_it_nexus_request ( shost - > host_no ,
itn_id , 1 , NULL ) ;
if ( err < 0 )
eprintk ( " The i_t_neuxs request lost, %d %llx! \n " ,
shost - > host_no , ( unsigned long long ) itn_id ) ;
return err ;
}
EXPORT_SYMBOL_GPL ( scsi_tgt_it_nexus_destroy ) ;
int scsi_tgt_kspace_it_nexus_rsp ( int host_no , u64 itn_id , int result )
{
struct Scsi_Host * shost ;
int err = - EINVAL ;
[SCSI] tgt: fix build when dprintk is defined
Fix scsi_tgt_lib build when dprintk is defined:
Also fix accessors problem when dprintk is defined
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_cmd_destroy':
drivers/scsi/scsi_tgt_lib.c:183: warning: format '%lu' expects type 'long unsigned int', but argument 6 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_cmd_done':
drivers/scsi/scsi_tgt_lib.c:330: warning: format '%lu' expects type 'long unsigned int', but argument 5 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_transfer_response':
drivers/scsi/scsi_tgt_lib.c:345: warning: format '%lu' expects type 'long unsigned int', but argument 5 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_init_cmd':
drivers/scsi/scsi_tgt_lib.c:368: warning: format '%lu' expects type 'long unsigned int', but argument 6 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_kspace_exec':
drivers/scsi/scsi_tgt_lib.c:499: warning: format '%lu' expects type 'long unsigned int', but argument 9 has type 'unsigned int'
drivers/scsi/scsi_tgt_lib.c: In function 'scsi_tgt_kspace_it_nexus_rsp':
drivers/scsi/scsi_tgt_lib.c:620: error: 'mid' undeclared (first use in this function)
drivers/scsi/scsi_tgt_lib.c:620: error: (Each undeclared identifier is reported only once
drivers/scsi/scsi_tgt_lib.c:620: error: for each function it appears in.)
make[2]: *** [drivers/scsi/scsi_tgt_lib.o] Error 1
[tomo:
> - dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid);
> + dprintk("%d %d\n", host_no, result);
'mid' is a typo. I wanted to do:
dprintk("%d %d %llx\n", host_no, result, (unsigned long long)itn_id);
The rest looks ok. Thanks,
]
Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Acked-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
2007-11-15 12:53:25 +03:00
dprintk ( " %d %d%llx \n " , host_no , result , ( unsigned long long ) itn_id ) ;
2007-07-11 10:08:17 +04:00
shost = scsi_host_lookup ( host_no ) ;
2008-08-08 04:49:30 +04:00
if ( ! shost ) {
2007-07-11 10:08:17 +04:00
printk ( KERN_ERR " Could not find host no %d \n " , host_no ) ;
return err ;
}
if ( ! shost - > uspace_req_q ) {
printk ( KERN_ERR " Not target scsi host %d \n " , host_no ) ;
goto done ;
}
err = shost - > transportt - > it_nexus_response ( shost , itn_id , result ) ;
2006-11-16 13:24:13 +03:00
done :
scsi_host_put ( shost ) ;
return err ;
}
static int __init scsi_tgt_init ( void )
{
int err ;
2008-04-10 18:48:14 +04:00
scsi_tgt_cmd_cache = KMEM_CACHE ( scsi_tgt_cmd , 0 ) ;
2006-11-16 13:24:13 +03:00
if ( ! scsi_tgt_cmd_cache )
return - ENOMEM ;
scsi_tgtd = create_workqueue ( " scsi_tgtd " ) ;
if ( ! scsi_tgtd ) {
err = - ENOMEM ;
goto free_kmemcache ;
}
err = scsi_tgt_if_init ( ) ;
if ( err )
goto destroy_wq ;
return 0 ;
destroy_wq :
destroy_workqueue ( scsi_tgtd ) ;
free_kmemcache :
kmem_cache_destroy ( scsi_tgt_cmd_cache ) ;
return err ;
}
static void __exit scsi_tgt_exit ( void )
{
destroy_workqueue ( scsi_tgtd ) ;
scsi_tgt_if_exit ( ) ;
kmem_cache_destroy ( scsi_tgt_cmd_cache ) ;
}
module_init ( scsi_tgt_init ) ;
module_exit ( scsi_tgt_exit ) ;
MODULE_DESCRIPTION ( " SCSI target core " ) ;
MODULE_LICENSE ( " GPL " ) ;