@ -299,16 +299,16 @@ static int srp_create_target_ib(struct srp_target_port *target)
return - ENOMEM ;
recv_cq = ib_create_cq ( target - > srp_host - > srp_dev - > dev ,
srp_recv_completion , NULL , target , SRP_RQ_SIZE ,
target - > comp_vector ) ;
srp_recv_completion , NULL , target ,
target - > queue_size , target - > comp_vector ) ;
if ( IS_ERR ( recv_cq ) ) {
ret = PTR_ERR ( recv_cq ) ;
goto err ;
}
send_cq = ib_create_cq ( target - > srp_host - > srp_dev - > dev ,
srp_send_completion , NULL , target , SRP_SQ_SIZE ,
target - > comp_vector ) ;
srp_send_completion , NULL , target ,
target - > queue_size , target - > comp_vector ) ;
if ( IS_ERR ( send_cq ) ) {
ret = PTR_ERR ( send_cq ) ;
goto err_recv_cq ;
@ -317,8 +317,8 @@ static int srp_create_target_ib(struct srp_target_port *target)
ib_req_notify_cq ( recv_cq , IB_CQ_NEXT_COMP ) ;
init_attr - > event_handler = srp_qp_event ;
init_attr - > cap . max_send_wr = SRP_SQ_SIZE ;
init_attr - > cap . max_recv_wr = SRP_RQ_SIZE ;
init_attr - > cap . max_send_wr = target - > queue_size ;
init_attr - > cap . max_recv_wr = target - > queue_size ;
init_attr - > cap . max_recv_sge = 1 ;
init_attr - > cap . max_send_sge = 1 ;
init_attr - > sq_sig_type = IB_SIGNAL_ALL_WR ;
@ -364,6 +364,10 @@ err:
return ret ;
}
/*
* Note : this function may be called without srp_alloc_iu_bufs ( ) having been
* invoked . Hence the target - > [ rt ] x_ring checks .
*/
static void srp_free_target_ib ( struct srp_target_port * target )
{
int i ;
@ -375,10 +379,18 @@ static void srp_free_target_ib(struct srp_target_port *target)
target - > qp = NULL ;
target - > send_cq = target - > recv_cq = NULL ;
for ( i = 0 ; i < SRP_RQ_SIZE ; + + i )
srp_free_iu ( target - > srp_host , target - > rx_ring [ i ] ) ;
for ( i = 0 ; i < SRP_SQ_SIZE ; + + i )
srp_free_iu ( target - > srp_host , target - > tx_ring [ i ] ) ;
if ( target - > rx_ring ) {
for ( i = 0 ; i < target - > queue_size ; + + i )
srp_free_iu ( target - > srp_host , target - > rx_ring [ i ] ) ;
kfree ( target - > rx_ring ) ;
target - > rx_ring = NULL ;
}
if ( target - > tx_ring ) {
for ( i = 0 ; i < target - > queue_size ; + + i )
srp_free_iu ( target - > srp_host , target - > tx_ring [ i ] ) ;
kfree ( target - > tx_ring ) ;
target - > tx_ring = NULL ;
}
}
static void srp_path_rec_completion ( int status ,
@ -564,7 +576,11 @@ static void srp_free_req_data(struct srp_target_port *target)
struct srp_request * req ;
int i ;
for ( i = 0 , req = target - > req_ring ; i < SRP_CMD_SQ_SIZE ; + + i , + + req ) {
if ( ! target - > req_ring )
return ;
for ( i = 0 ; i < target - > req_ring_size ; + + i ) {
req = & target - > req_ring [ i ] ;
kfree ( req - > fmr_list ) ;
kfree ( req - > map_page ) ;
if ( req - > indirect_dma_addr ) {
@ -574,6 +590,9 @@ static void srp_free_req_data(struct srp_target_port *target)
}
kfree ( req - > indirect_desc ) ;
}
kfree ( target - > req_ring ) ;
target - > req_ring = NULL ;
}
static int srp_alloc_req_data ( struct srp_target_port * target )
@ -586,7 +605,12 @@ static int srp_alloc_req_data(struct srp_target_port *target)
INIT_LIST_HEAD ( & target - > free_reqs ) ;
for ( i = 0 ; i < SRP_CMD_SQ_SIZE ; + + i ) {
target - > req_ring = kzalloc ( target - > req_ring_size *
sizeof ( * target - > req_ring ) , GFP_KERNEL ) ;
if ( ! target - > req_ring )
goto out ;
for ( i = 0 ; i < target - > req_ring_size ; + + i ) {
req = & target - > req_ring [ i ] ;
req - > fmr_list = kmalloc ( target - > cmd_sg_cnt * sizeof ( void * ) ,
GFP_KERNEL ) ;
@ -810,7 +834,7 @@ static void srp_terminate_io(struct srp_rport *rport)
struct srp_target_port * target = rport - > lld_data ;
int i ;
for ( i = 0 ; i < SRP_CMD_SQ_SIZE ; + + i ) {
for ( i = 0 ; i < target - > req_ring_size ; + + i ) {
struct srp_request * req = & target - > req_ring [ i ] ;
srp_finish_req ( target , req , DID_TRANSPORT_FAILFAST < < 16 ) ;
}
@ -847,13 +871,13 @@ static int srp_rport_reconnect(struct srp_rport *rport)
else
srp_create_target_ib ( target ) ;
for ( i = 0 ; i < SRP_CMD_SQ_SIZE ; + + i ) {
for ( i = 0 ; i < target - > req_ring_size ; + + i ) {
struct srp_request * req = & target - > req_ring [ i ] ;
srp_finish_req ( target , req , DID_RESET < < 16 ) ;
}
INIT_LIST_HEAD ( & target - > free_tx ) ;
for ( i = 0 ; i < SRP_SQ_SIZE ; + + i )
for ( i = 0 ; i < target - > queue_size ; + + i )
list_add ( & target - > tx_ring [ i ] - > list , & target - > free_tx ) ;
if ( ret = = 0 )
@ -1562,11 +1586,24 @@ err_unlock:
return SCSI_MLQUEUE_HOST_BUSY ;
}
/*
* Note : the resources allocated in this function are freed in
* srp_free_target_ib ( ) .
*/
static int srp_alloc_iu_bufs ( struct srp_target_port * target )
{
int i ;
for ( i = 0 ; i < SRP_RQ_SIZE ; + + i ) {
target - > rx_ring = kzalloc ( target - > queue_size * sizeof ( * target - > rx_ring ) ,
GFP_KERNEL ) ;
if ( ! target - > rx_ring )
goto err_no_ring ;
target - > tx_ring = kzalloc ( target - > queue_size * sizeof ( * target - > tx_ring ) ,
GFP_KERNEL ) ;
if ( ! target - > tx_ring )
goto err_no_ring ;
for ( i = 0 ; i < target - > queue_size ; + + i ) {
target - > rx_ring [ i ] = srp_alloc_iu ( target - > srp_host ,
target - > max_ti_iu_len ,
GFP_KERNEL , DMA_FROM_DEVICE ) ;
@ -1574,7 +1611,7 @@ static int srp_alloc_iu_bufs(struct srp_target_port *target)
goto err ;
}
for ( i = 0 ; i < SRP_SQ_SIZE ; + + i ) {
for ( i = 0 ; i < target - > queue_size ; + + i ) {
target - > tx_ring [ i ] = srp_alloc_iu ( target - > srp_host ,
target - > max_iu_len ,
GFP_KERNEL , DMA_TO_DEVICE ) ;
@ -1587,16 +1624,18 @@ static int srp_alloc_iu_bufs(struct srp_target_port *target)
return 0 ;
err :
for ( i = 0 ; i < SRP_RQ_SIZE ; + + i ) {
for ( i = 0 ; i < target - > queue_size ; + + i ) {
srp_free_iu ( target - > srp_host , target - > rx_ring [ i ] ) ;
target - > rx_ring [ i ] = NULL ;
}
for ( i = 0 ; i < SRP_SQ_SIZE ; + + i ) {
srp_free_iu ( target - > srp_host , target - > tx_ring [ i ] ) ;
target - > tx_ring [ i ] = NULL ;
}
err_no_ring :
kfree ( target - > tx_ring ) ;
target - > tx_ring = NULL ;
kfree ( target - > rx_ring ) ;
target - > rx_ring = NULL ;
return - ENOMEM ;
}
@ -1647,6 +1686,9 @@ static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
target - > scsi_host - > can_queue
= min ( target - > req_lim - SRP_TSK_MGMT_SQ_SIZE ,
target - > scsi_host - > can_queue ) ;
target - > scsi_host - > cmd_per_lun
= min_t ( int , target - > scsi_host - > can_queue ,
target - > scsi_host - > cmd_per_lun ) ;
} else {
shost_printk ( KERN_WARNING , target - > scsi_host ,
PFX " Unhandled RSP opcode %#x \n " , lrsp - > opcode ) ;
@ -1654,7 +1696,7 @@ static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
goto error ;
}
if ( ! target - > rx_ring [ 0 ] ) {
if ( ! target - > rx_ring ) {
ret = srp_alloc_iu_bufs ( target ) ;
if ( ret )
goto error ;
@ -1674,7 +1716,7 @@ static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
if ( ret )
goto error_free ;
for ( i = 0 ; i < SRP_RQ_SIZE ; i + + ) {
for ( i = 0 ; i < target - > queue_size ; i + + ) {
struct srp_iu * iu = target - > rx_ring [ i ] ;
ret = srp_post_recv ( target , iu ) ;
if ( ret )
@ -1933,7 +1975,7 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
if ( target - > tsk_mgmt_status )
return FAILED ;
for ( i = 0 ; i < SRP_CMD_SQ_SIZE ; + + i ) {
for ( i = 0 ; i < target - > req_ring_size ; + + i ) {
struct srp_request * req = & target - > req_ring [ i ] ;
if ( req - > scmnd & & req - > scmnd - > device = = scmnd - > device )
srp_finish_req ( target , req , DID_RESET < < 16 ) ;
@ -2136,9 +2178,9 @@ static struct scsi_host_template srp_template = {
. eh_host_reset_handler = srp_reset_host ,
. skip_settle_delay = true ,
. sg_tablesize = SRP_DEF_SG_TABLESIZE ,
. can_queue = SRP_CMD_SQ_SIZE ,
. can_queue = SRP_DEFAULT_ CMD_SQ_SIZE ,
. this_id = - 1 ,
. cmd_per_lun = SRP_CMD_SQ_SIZE ,
. cmd_per_lun = SRP_DEFAULT_ CMD_SQ_SIZE ,
. use_clustering = ENABLE_CLUSTERING ,
. shost_attrs = srp_host_attrs
} ;
@ -2245,6 +2287,7 @@ enum {
SRP_OPT_SG_TABLESIZE = 1 < < 11 ,
SRP_OPT_COMP_VECTOR = 1 < < 12 ,
SRP_OPT_TL_RETRY_COUNT = 1 < < 13 ,
SRP_OPT_QUEUE_SIZE = 1 < < 14 ,
SRP_OPT_ALL = ( SRP_OPT_ID_EXT |
SRP_OPT_IOC_GUID |
SRP_OPT_DGID |
@ -2267,6 +2310,7 @@ static const match_table_t srp_opt_tokens = {
{ SRP_OPT_SG_TABLESIZE , " sg_tablesize=%u " } ,
{ SRP_OPT_COMP_VECTOR , " comp_vector=%u " } ,
{ SRP_OPT_TL_RETRY_COUNT , " tl_retry_count=%u " } ,
{ SRP_OPT_QUEUE_SIZE , " queue_size=%d " } ,
{ SRP_OPT_ERR , NULL }
} ;
@ -2361,13 +2405,25 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
target - > scsi_host - > max_sectors = token ;
break ;
case SRP_OPT_QUEUE_SIZE :
if ( match_int ( args , & token ) | | token < 1 ) {
pr_warn ( " bad queue_size parameter '%s' \n " , p ) ;
goto out ;
}
target - > scsi_host - > can_queue = token ;
target - > queue_size = token + SRP_RSP_SQ_SIZE +
SRP_TSK_MGMT_SQ_SIZE ;
if ( ! ( opt_mask & SRP_OPT_MAX_CMD_PER_LUN ) )
target - > scsi_host - > cmd_per_lun = token ;
break ;
case SRP_OPT_MAX_CMD_PER_LUN :
if ( match_int ( args , & token ) ) {
if ( match_int ( args , & token ) | | token < 1 ) {
pr_warn ( " bad max cmd_per_lun parameter '%s' \n " ,
p ) ;
goto out ;
}
target - > scsi_host - > cmd_per_lun = min ( token , SRP_CMD_SQ_SIZE ) ;
target - > scsi_host - > cmd_per_lun = token ;
break ;
case SRP_OPT_IO_CLASS :
@ -2455,6 +2511,12 @@ static int srp_parse_options(const char *buf, struct srp_target_port *target)
pr_warn ( " target creation request is missing parameter '%s' \n " ,
srp_opt_tokens [ i ] . pattern ) ;
if ( target - > scsi_host - > cmd_per_lun > target - > scsi_host - > can_queue
& & ( opt_mask & SRP_OPT_MAX_CMD_PER_LUN ) )
pr_warn ( " cmd_per_lun = %d > queue_size = %d \n " ,
target - > scsi_host - > cmd_per_lun ,
target - > scsi_host - > can_queue ) ;
out :
kfree ( options ) ;
return ret ;
@ -2493,11 +2555,14 @@ static ssize_t srp_create_target(struct device *dev,
target - > sg_tablesize = indirect_sg_entries ? : cmd_sg_entries ;
target - > allow_ext_sg = allow_ext_sg ;
target - > tl_retry_count = 7 ;
target - > queue_size = SRP_DEFAULT_QUEUE_SIZE ;
ret = srp_parse_options ( buf , target ) ;
if ( ret )
goto err ;
target - > req_ring_size = target - > queue_size - SRP_TSK_MGMT_SQ_SIZE ;
if ( ! srp_conn_unique ( target - > srp_host , target ) ) {
shost_printk ( KERN_INFO , target - > scsi_host ,
PFX " Already connected to target port with id_ext=%016llx;ioc_guid=%016llx;initiator_ext=%016llx \n " ,