[PATCH 17/18] aacraid: use scsi_get_internal_cmd()

Hannes Reinecke
2021-05-03T15:04:02Z

From: Hannes Reinecke <hare@suse.com>

Use scsi_get_internal_cmd() to allocate internal commands.
Internal commands are marked with a new FIB_CONTEXT_FLAG_INTERNAL_CMD,
so we need to ensure that the 'flags' field is not cleared
completely in aac_fib_send() to avoid command allocation failures.

Signed-off-by: Hannes Reinecke <hare@suse.com>
---
drivers/scsi/aacraid/aachba.c | 92 +++++++++++++++------------------
drivers/scsi/aacraid/aacraid.h | 10 ++--
drivers/scsi/aacraid/commctrl.c | 25 +++++----
drivers/scsi/aacraid/comminit.c | 2 +-
drivers/scsi/aacraid/commsup.c | 69 ++++++++++++-------------
drivers/scsi/aacraid/dpcsup.c | 2 +-
drivers/scsi/aacraid/linit.c | 13 +++--
7 files changed, 108 insertions(+), 105 deletions(-)

diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index ef59303db9b9..ce60b7344be9 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);
@@ -741,61 +741,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) {
@@ -827,29 +822,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 = kmalloc(sizeof(*scsicmd), GFP_KERNEL);
- struct scsi_device *scsidev = kmalloc(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;
}

@@ -1694,7 +1683,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;

@@ -2054,7 +2043,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);
@@ -2101,7 +2090,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;
}
@@ -2811,6 +2800,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) ||
@@ -2823,7 +2814,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 e3e4ecbea726..3cd7f33497d8 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -1291,13 +1291,16 @@ struct fsa_dev_info {
};

struct fib {
- void *next; /* this is used by the allocator */
s16 type;
s16 size;
/*
* The Adapter that this I/O is destined for.
*/
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;
@@ -1597,6 +1599,7 @@ struct aac_dev
size_t comm_size;

struct Scsi_Host *scsi_host_ptr;
+ struct scsi_device *scsi_host_dev;
int maximum_num_containers;
int maximum_num_physicals;
int maximum_num_channels;
@@ -1729,6 +1732,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 +2690,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 e7cc927ed952..bc5b81696476 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 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
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 355b16f0b145..0d5be76891b0 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 54eb4d41bc2c..6e2e381b12d4 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,32 @@ 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;
+
+ scmd = scsi_get_internal_cmd(dev->scsi_host_dev,
+ direction == DMA_TO_DEVICE ?
+ REQ_OP_SCSI_OUT : REQ_OP_SCSI_IN,
+ BLK_MQ_REQ_NOWAIT);
spin_lock_irqsave(&dev->fib_lock, flags);
- fibptr = dev->free_fib;
- if(!fibptr){
- spin_unlock_irqrestore(&dev->fib_lock, flags);
- return fibptr;
+ 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 +285,16 @@ 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;
+ }
+ }
+ fibptr->flags = 0;
spin_unlock_irqrestore(&fibptr->dev->fib_lock, flags);
}

@@ -507,7 +502,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
* will have a debug mode where the adapter can notify the host
* it had a problem and the host can log that fact.
*/
- fibptr->flags = 0;
+ fibptr->flags &= FIB_CONTEXT_FLAG_INTERNAL_CMD;
if (wait && !reply) {
return -EINVAL;
} else if (!wait && reply) {
@@ -562,7 +557,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
if (!wait) {
fibptr->callback = callback;
fibptr->callback_data = callback_data;
- fibptr->flags = FIB_CONTEXT_FLAG;
+ fibptr->flags |= FIB_CONTEXT_FLAG;
}

fibptr->done = 0;
@@ -714,7 +709,7 @@ int aac_hba_send(u8 command, struct fib *fibptr, fib_callback callback,
struct aac_hba_cmd_req *hbacmd = (struct aac_hba_cmd_req *)
fibptr->hw_fib_va;

- fibptr->flags = (FIB_CONTEXT_FLAG | FIB_CONTEXT_FLAG_NATIVE_HBA);
+ fibptr->flags |= (FIB_CONTEXT_FLAG | FIB_CONTEXT_FLAG_NATIVE_HBA);
if (callback) {
wait = 0;
fibptr->callback = callback;
@@ -1663,7 +1658,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 +2285,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 +2383,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 fbe334c59f37..9424792432ec 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 e5d89b309c3a..ab3762c01738 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -714,7 +714,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;

@@ -925,7 +925,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;

@@ -988,7 +988,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;

@@ -1641,6 +1641,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)
@@ -1715,6 +1716,10 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (error)
goto out_deinit;

+ aac->scsi_host_dev = scsi_get_host_dev(shost);
+ if (!aac->scsi_host_dev)
+ goto out_remove_host;
+
aac->maximum_num_channels = aac_drivers[index].channels;
error = aac_get_adapter_info(aac);
if (error < 0)
@@ -1790,6 +1795,8 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
kfree(aac->queues);
aac_adapter_ioremap(aac, 0);
kfree(aac->fsa_dev);
+ out_remove_host:
+ scsi_remove_host(shost);
out_free_fibs:
kfree(aac->fibs);
out_free_host:
--
2.29.2