aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.com>2019-02-21 08:38:06 +0100
committerHannes Reinecke <hare@suse.de>2021-11-07 16:25:14 +0100
commitd855c0f944ed75c432d076b0c2f5ea5a156276da (patch)
treef2452708c3e3bcb566dea3b4b7a8206cd40a9476
parent3747ba8b2652333b653ce8d42cfe4c3c27fe9d6e (diff)
downloadscsi-devel-d855c0f944ed75c432d076b0c2f5ea5a156276da.tar.gz
aacraid: use scsi_get_internal_cmd()
Use scsi_get_internal_cmd() to allocate internal commands. And move scsi_add_host() such that it's allocated early enough to provide tags for the initialisation commands. Signed-off-by: Hannes Reinecke <hare@suse.com>
-rw-r--r--drivers/scsi/aacraid/aachba.c92
-rw-r--r--drivers/scsi/aacraid/aacraid.h9
-rw-r--r--drivers/scsi/aacraid/commctrl.c25
-rw-r--r--drivers/scsi/aacraid/comminit.c2
-rw-r--r--drivers/scsi/aacraid/commsup.c60
-rw-r--r--drivers/scsi/aacraid/dpcsup.c2
-rw-r--r--drivers/scsi/aacraid/linit.c8
7 files changed, 96 insertions, 102 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 2e01dfea9280b..93202f1fdc05c 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -360,7 +360,7 @@ int aac_get_config_status(struct aac_dev *dev, int commit_flag)
int status = 0;
struct fib * fibptr;
- if (!(fibptr = aac_fib_alloc(dev)))
+ if (!(fibptr = aac_fib_alloc(dev, DMA_FROM_DEVICE)))
return -ENOMEM;
aac_fib_init(fibptr);
@@ -457,7 +457,7 @@ int aac_get_containers(struct aac_dev *dev)
struct aac_get_container_count_resp *dresp;
int maximum_num_containers = MAXIMUM_NUM_CONTAINERS;
- if (!(fibptr = aac_fib_alloc(dev)))
+ if (!(fibptr = aac_fib_alloc(dev, DMA_FROM_DEVICE)))
return -ENOMEM;
aac_fib_init(fibptr);
@@ -752,61 +752,56 @@ static void _aac_probe_container1(void * context, struct fib * fibptr)
}
}
-static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *))
+static int _aac_probe_container(struct fib * fibptr, int (*callback)(struct scsi_cmnd *))
{
+ struct scsi_cmnd *scsicmd = fibptr->scmd;
struct aac_dev * dev;
- struct fib * fibptr;
int status = -ENOMEM;
+ struct aac_query_mount *dinfo;
int cid = scmd_id(scsicmd);
dev = (struct aac_dev *)scsicmd->device->host->hostdata;
if (scsicmd->host_scribble) {
- cid = *(int *)scsicmd->host_scribble;
- if (cid > dev->maximum_num_containers) {
+ cid = *(unsigned int *)scsicmd->host_scribble;
+ if (cid >= dev->maximum_num_containers) {
status = -ENODEV;
goto out_status;
}
}
- if ((fibptr = aac_fib_alloc(dev))) {
- struct aac_query_mount *dinfo;
- aac_fib_init(fibptr);
+ aac_fib_init(fibptr);
- dinfo = (struct aac_query_mount *)fib_data(fibptr);
+ dinfo = (struct aac_query_mount *)fib_data(fibptr);
- if (fibptr->dev->supplement_adapter_info.supported_options2 &
- AAC_OPTION_VARIABLE_BLOCK_SIZE)
- dinfo->command = cpu_to_le32(VM_NameServeAllBlk);
- else
- dinfo->command = cpu_to_le32(VM_NameServe);
+ if (fibptr->dev->supplement_adapter_info.supported_options2 &
+ AAC_OPTION_VARIABLE_BLOCK_SIZE)
+ dinfo->command = cpu_to_le32(VM_NameServeAllBlk);
+ else
+ dinfo->command = cpu_to_le32(VM_NameServe);
- dinfo->count = cpu_to_le32(cid);
- dinfo->type = cpu_to_le32(FT_FILESYS);
- scsicmd->SCp.ptr = (char *)callback;
- scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
+ dinfo->count = cpu_to_le32(cid);
+ dinfo->type = cpu_to_le32(FT_FILESYS);
+ scsicmd->SCp.ptr = (char *)callback;
+ scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;
- status = aac_fib_send(ContainerCommand,
+ status = aac_fib_send(ContainerCommand,
fibptr,
sizeof(struct aac_query_mount),
FsaNormal,
0, 1,
_aac_probe_container1,
(void *) scsicmd);
- /*
- * Check that the command queued to the controller
- */
- if (status == -EINPROGRESS)
- return 0;
-
- if (status < 0) {
- scsicmd->SCp.ptr = NULL;
- aac_fib_complete(fibptr);
- aac_fib_free(fibptr);
- }
- }
+ /*
+ * Check that the command queued to the controller
+ */
+ if (status == -EINPROGRESS)
+ return 0;
out_status:
if (status < 0) {
struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev;
+
+ scsicmd->SCp.ptr = NULL;
+ aac_fib_complete(fibptr);
if (fsa_dev_ptr && cid < dev->maximum_num_containers) {
fsa_dev_ptr += cid;
if ((fsa_dev_ptr->valid & 1) == 0) {
@@ -838,29 +833,23 @@ static void aac_probe_container_scsi_done(struct scsi_cmnd *scsi_cmnd)
int aac_probe_container(struct aac_dev *dev, int cid)
{
- struct scsi_cmnd *scsicmd = kzalloc(sizeof(*scsicmd), GFP_KERNEL);
- struct scsi_device *scsidev = kzalloc(sizeof(*scsidev), GFP_KERNEL);
+ struct fib *fibptr;
+ struct scsi_cmnd *scsicmd;
int status;
- if (!scsicmd || !scsidev) {
- kfree(scsicmd);
- kfree(scsidev);
+ fibptr = aac_fib_alloc(dev, DMA_FROM_DEVICE);
+ if (!fibptr)
return -ENOMEM;
- }
+
+ scsicmd = fibptr->scmd;
scsicmd->scsi_done = aac_probe_container_scsi_done;
scsicmd->host_scribble = (unsigned char *)&cid;
- scsicmd->device = scsidev;
- scsidev->sdev_state = 0;
- scsidev->id = cid;
- scsidev->host = dev->scsi_host_ptr;
-
- if (_aac_probe_container(scsicmd, aac_probe_container_callback1) == 0)
+ if (_aac_probe_container(fibptr, aac_probe_container_callback1) == 0)
while (scsicmd->host_scribble == (unsigned char *)&cid)
schedule();
- kfree(scsidev);
status = scsicmd->SCp.Status;
- kfree(scsicmd);
+ aac_fib_free(fibptr);
return status;
}
@@ -1705,7 +1694,7 @@ static int aac_send_safw_bmic_cmd(struct aac_dev *dev,
return 0;
/* allocate FIB */
- fibptr = aac_fib_alloc(dev);
+ fibptr = aac_fib_alloc(dev, DMA_BIDIRECTIONAL);
if (!fibptr)
return -ENOMEM;
@@ -2065,7 +2054,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
struct aac_bus_info *command;
struct aac_bus_info_response *bus_info;
- if (!(fibptr = aac_fib_alloc(dev)))
+ if (!(fibptr = aac_fib_alloc(dev, DMA_FROM_DEVICE)))
return -ENOMEM;
aac_fib_init(fibptr);
@@ -2112,7 +2101,7 @@ int aac_get_adapter_info(struct aac_dev* dev)
if (rcode >= 0)
memcpy(&dev->supplement_adapter_info, sinfo, sizeof(*sinfo));
if (rcode == -ERESTARTSYS) {
- fibptr = aac_fib_alloc(dev);
+ fibptr = aac_fib_alloc(dev, DMA_FROM_DEVICE);
if (!fibptr)
return -ENOMEM;
}
@@ -2822,6 +2811,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
if (((fsa_dev_ptr[cid].valid & 1) == 0) ||
(fsa_dev_ptr[cid].sense_data.sense_key ==
NOT_READY)) {
+ struct fib * fibptr;
+
switch (scsicmd->cmnd[0]) {
case SERVICE_ACTION_IN_16:
if (!(dev->raw_io_interface) ||
@@ -2834,7 +2825,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
case TEST_UNIT_READY:
if (dev->in_reset)
return -1;
- return _aac_probe_container(scsicmd,
+ fibptr = aac_fib_alloc_tag(dev, scsicmd);
+ return _aac_probe_container(fibptr,
aac_probe_container_callback2);
default:
break;
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 3733df77bc65d..6121d9f1978a9 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -1291,7 +1291,6 @@ struct fsa_dev_info {
};
struct fib {
- void *next; /* this is used by the allocator */
s16 type;
s16 size;
/*
@@ -1299,6 +1298,10 @@ struct fib {
*/
struct aac_dev *dev;
/*
+ * The associated scsi command
+ */
+ struct scsi_cmnd *scmd;
+ /*
* This is the event the sendfib routine will wait on if the
* caller did not pass one and this is synch io.
*/
@@ -1552,7 +1555,6 @@ struct aac_dev
*/
struct fib *fibs;
- struct fib *free_fib;
spinlock_t fib_lock;
struct mutex ioctl_mutex;
@@ -1729,6 +1731,7 @@ struct aac_dev
#define FIB_CONTEXT_FLAG_NATIVE_HBA_TMF (0x00000020)
#define FIB_CONTEXT_FLAG_SCSI_CMD (0x00000040)
#define FIB_CONTEXT_FLAG_EH_RESET (0x00000080)
+#define FIB_CONTEXT_FLAG_INTERNAL_CMD (0x00000100)
/*
* Define the command values
@@ -2686,7 +2689,7 @@ void aac_free_irq(struct aac_dev *dev);
int aac_setup_safw_adapter(struct aac_dev *dev);
const char *aac_driverinfo(struct Scsi_Host *);
void aac_fib_vector_assign(struct aac_dev *dev);
-struct fib *aac_fib_alloc(struct aac_dev *dev);
+struct fib *aac_fib_alloc(struct aac_dev *dev, int direction);
struct fib *aac_fib_alloc_tag(struct aac_dev *dev, struct scsi_cmnd *scmd);
int aac_fib_setup(struct aac_dev *dev);
void aac_fib_map_free(struct aac_dev *dev);
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index e7cc927ed952d..bc5b81696476c 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -55,7 +55,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
if (dev->in_reset) {
return -EBUSY;
}
- fibptr = aac_fib_alloc(dev);
+ fibptr = aac_fib_alloc(dev, DMA_BIDIRECTIONAL);
if(fibptr == NULL) {
return -ENOMEM;
}
@@ -478,7 +478,7 @@ static int check_revision(struct aac_dev *dev, void __user *arg)
*/
static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
{
- struct fib* srbfib;
+ struct fib* srbfib = NULL;
int status;
struct aac_srb *srbcmd = NULL;
struct aac_hba_cmd_req *hbacmd = NULL;
@@ -509,12 +509,6 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
dprintk((KERN_DEBUG"aacraid: No permission to send raw srb\n"));
return -EPERM;
}
- /*
- * Allocate and initialize a Fib then setup a SRB command
- */
- if (!(srbfib = aac_fib_alloc(dev))) {
- return -ENOMEM;
- }
memset(sg_list, 0, sizeof(sg_list)); /* cleanup may take issue */
if(copy_from_user(&fibsize, &user_srb->count,sizeof(u32))){
@@ -561,6 +555,15 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
rcode = -EINVAL;
goto cleanup;
}
+
+ /*
+ * Allocate and initialize a Fib
+ */
+ if (!(srbfib = aac_fib_alloc(dev, data_dir))) {
+ rcode = -ENOMEM;
+ goto cleanup;
+ }
+
actual_fibsize = sizeof(struct aac_srb) - sizeof(struct sgentry) +
((user_srbcmd->sg.count & 0xff) * sizeof(struct sgentry));
actual_fibsize64 = actual_fibsize + (user_srbcmd->sg.count & 0xff) *
@@ -988,8 +991,10 @@ cleanup:
if (rcode != -ERESTARTSYS) {
for (i = 0; i <= sg_indx; i++)
kfree(sg_list[i]);
- aac_fib_complete(srbfib);
- aac_fib_free(srbfib);
+ if (srbfib) {
+ aac_fib_complete(srbfib);
+ aac_fib_free(srbfib);
+ }
}
return rcode;
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 355b16f0b1456..0d5be76891b0e 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -327,7 +327,7 @@ int aac_send_shutdown(struct aac_dev * dev)
aac_wait_for_io_completion(dev);
- fibctx = aac_fib_alloc(dev);
+ fibctx = aac_fib_alloc(dev, DMA_NONE);
if (!fibctx)
return -ENOMEM;
aac_fib_init(fibctx);
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index deb32c9f4b3e6..9cb5b970bac40 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -173,7 +173,6 @@ int aac_fib_setup(struct aac_dev * dev)
fibptr->dev = dev;
fibptr->hw_fib_va = hw_fib;
fibptr->data = (void *) fibptr->hw_fib_va->data;
- fibptr->next = fibptr+1; /* Forward chain the fibs */
init_completion(&fibptr->event_wait);
spin_lock_init(&fibptr->event_lock);
hw_fib->header.XferState = cpu_to_le32(0xffffffff);
@@ -200,14 +199,6 @@ int aac_fib_setup(struct aac_dev * dev)
*/
aac_fib_vector_assign(dev);
- /*
- * Add the fib chain to the free list
- */
- dev->fibs[dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB - 1].next = NULL;
- /*
- * Set 8 fibs aside for management tools
- */
- dev->free_fib = &dev->fibs[dev->scsi_host_ptr->can_queue];
return 0;
}
@@ -233,7 +224,7 @@ struct fib *aac_fib_alloc_tag(struct aac_dev *dev, struct scsi_cmnd *scmd)
fibptr->type = FSAFS_NTC_FIB_CONTEXT;
fibptr->callback_data = NULL;
fibptr->callback = NULL;
- fibptr->flags = 0;
+ fibptr->scmd = scmd;
return fibptr;
}
@@ -241,36 +232,30 @@ struct fib *aac_fib_alloc_tag(struct aac_dev *dev, struct scsi_cmnd *scmd)
/**
* aac_fib_alloc - allocate a fib
* @dev: Adapter to allocate the fib for
+ * @direction: DMA data direction
*
* Allocate a fib from the adapter fib pool. If the pool is empty we
* return NULL.
*/
-struct fib *aac_fib_alloc(struct aac_dev *dev)
+struct fib *aac_fib_alloc(struct aac_dev *dev, int direction)
{
- struct fib * fibptr;
+ struct scsi_cmnd *scmd;
+ struct fib * fibptr = NULL;
unsigned long flags;
+
spin_lock_irqsave(&dev->fib_lock, flags);
- fibptr = dev->free_fib;
- if(!fibptr){
- spin_unlock_irqrestore(&dev->fib_lock, flags);
- return fibptr;
+ scmd = scsi_host_get_reserved_cmd(dev->scsi_host_ptr, direction,
+ REQ_NOWAIT);
+ if (scmd) {
+ fibptr = aac_fib_alloc_tag(dev, scmd);
+ fibptr->flags |= FIB_CONTEXT_FLAG_INTERNAL_CMD;
}
- dev->free_fib = fibptr->next;
spin_unlock_irqrestore(&dev->fib_lock, flags);
- /*
- * Set the proper node type code and node byte size
- */
- fibptr->type = FSAFS_NTC_FIB_CONTEXT;
+ if (!fibptr)
+ return NULL;
+
fibptr->size = sizeof(struct fib);
- /*
- * Null out fields that depend on being zero at the start of
- * each I/O
- */
- fibptr->hw_fib_va->header.XferState = 0;
- fibptr->flags = 0;
- fibptr->callback = NULL;
- fibptr->callback_data = NULL;
return fibptr;
}
@@ -298,8 +283,15 @@ void aac_fib_free(struct fib *fibptr)
(void*)fibptr,
le32_to_cpu(fibptr->hw_fib_va->header.XferState));
}
- fibptr->next = fibptr->dev->free_fib;
- fibptr->dev->free_fib = fibptr;
+ if (fibptr->scmd) {
+ struct scsi_cmnd *scmd = fibptr->scmd;
+
+ fibptr->scmd = NULL;
+ if (fibptr->flags & FIB_CONTEXT_FLAG_INTERNAL_CMD) {
+ scsi_put_internal_cmd(scmd);
+ fibptr->flags &= ~FIB_CONTEXT_FLAG_INTERNAL_CMD;
+ }
+ }
spin_unlock_irqrestore(&fibptr->dev->fib_lock, flags);
}
@@ -1663,7 +1655,7 @@ int aac_reset_adapter(struct aac_dev *aac, int forced, u8 reset_type)
retval = unblock_retval;
if ((forced < 2) && (retval == -ENODEV)) {
/* Unwind aac_send_shutdown() IOP_RESET unsupported/disabled */
- struct fib * fibctx = aac_fib_alloc(aac);
+ struct fib * fibctx = aac_fib_alloc(aac, DMA_NONE);
if (fibctx) {
struct aac_pause *cmd;
int status;
@@ -2290,7 +2282,7 @@ static int aac_send_wellness_command(struct aac_dev *dev, char *wellness_str,
int ret = -ENOMEM;
u32 vbus, vid;
- fibptr = aac_fib_alloc(dev);
+ fibptr = aac_fib_alloc(dev, DMA_TO_DEVICE);
if (!fibptr)
goto out;
@@ -2388,7 +2380,7 @@ static int aac_send_hosttime(struct aac_dev *dev, struct timespec64 *now)
struct fib *fibptr;
__le32 *info;
- fibptr = aac_fib_alloc(dev);
+ fibptr = aac_fib_alloc(dev, DMA_TO_DEVICE);
if (!fibptr)
goto out;
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
index fbe334c59f376..9424792432ec8 100644
--- a/drivers/scsi/aacraid/dpcsup.c
+++ b/drivers/scsi/aacraid/dpcsup.c
@@ -315,7 +315,7 @@ unsigned int aac_intr_normal(struct aac_dev *dev, u32 index, int isAif,
struct fib *fibctx;
struct aac_aifcmd *cmd;
- fibctx = aac_fib_alloc(dev);
+ fibctx = aac_fib_alloc(dev, DMA_FROM_DEVICE);
if (!fibctx)
return 1;
aac_fib_init(fibctx);
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index b92a6595358ec..a4a42efa53fbe 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -716,7 +716,7 @@ static int aac_eh_abort(struct scsi_cmnd* cmd)
return ret;
/* start a HBA_TMF_ABORT_TASK TMF request */
- fib = aac_fib_alloc(aac);
+ fib = aac_fib_alloc(aac, DMA_NONE);
if (!fib)
return ret;
@@ -927,7 +927,7 @@ static int aac_eh_dev_reset(struct scsi_cmnd *cmd)
pr_err("%s: Host device reset request. SCSI hang ?\n",
AAC_DRIVERNAME);
- fib = aac_fib_alloc(aac);
+ fib = aac_fib_alloc(aac, DMA_NONE);
if (!fib)
return ret;
@@ -990,7 +990,7 @@ static int aac_eh_target_reset(struct scsi_cmnd *cmd)
pr_err("%s: Host target reset request. SCSI hang ?\n",
AAC_DRIVERNAME);
- fib = aac_fib_alloc(aac);
+ fib = aac_fib_alloc(aac, DMA_NONE);
if (!fib)
return ret;
@@ -1507,6 +1507,7 @@ static struct scsi_host_template aac_driver_template = {
#endif
.emulated = 1,
.no_write_same = 1,
+ .admin_queue = 1,
};
static void __aac_shutdown(struct aac_dev * aac)
@@ -1645,6 +1646,7 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
shost->max_cmd_len = 16;
shost->max_id = MAXIMUM_NUM_CONTAINERS;
shost->max_lun = AAC_MAX_LUN;
+ shost->nr_reserved_cmds = AAC_NUM_MGT_FIB;
shost->sg_tablesize = HBA_MAX_SG_SEPARATE;
if (aac_cfg_major == AAC_CHARDEV_NEEDS_REINIT)