mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 11:19:37 +00:00
scsi: hpsa: remove abort handler
- simplify the driver - there are a lot of quirky racy conditions not handled - causes more aborts/resets when the number of commands to be aborted is large, such as in multi-path fail-overs. - has been turned off in our internal driver since 8/31/2015 Reviewed-by: Scott Benesh <scott.benesh@microsemi.com> Reviewed-by: Scott Teel <scott.teel@microsemi.com> Reviewed-by: Kevin Barnett <kevin.barnett@microsemi.com> Signed-off-by: Don Brace <don.brace@microsemi.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
b63c64ac5a
commit
08ec46f673
2 changed files with 8 additions and 614 deletions
|
@ -258,7 +258,6 @@ static int hpsa_scan_finished(struct Scsi_Host *sh,
|
||||||
static int hpsa_change_queue_depth(struct scsi_device *sdev, int qdepth);
|
static int hpsa_change_queue_depth(struct scsi_device *sdev, int qdepth);
|
||||||
|
|
||||||
static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd);
|
static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd);
|
||||||
static int hpsa_eh_abort_handler(struct scsi_cmnd *scsicmd);
|
|
||||||
static int hpsa_slave_alloc(struct scsi_device *sdev);
|
static int hpsa_slave_alloc(struct scsi_device *sdev);
|
||||||
static int hpsa_slave_configure(struct scsi_device *sdev);
|
static int hpsa_slave_configure(struct scsi_device *sdev);
|
||||||
static void hpsa_slave_destroy(struct scsi_device *sdev);
|
static void hpsa_slave_destroy(struct scsi_device *sdev);
|
||||||
|
@ -326,7 +325,7 @@ static inline bool hpsa_is_cmd_idle(struct CommandList *c)
|
||||||
|
|
||||||
static inline bool hpsa_is_pending_event(struct CommandList *c)
|
static inline bool hpsa_is_pending_event(struct CommandList *c)
|
||||||
{
|
{
|
||||||
return c->abort_pending || c->reset_pending;
|
return c->reset_pending;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* extract sense key, asc, and ascq from sense data. -1 means invalid. */
|
/* extract sense key, asc, and ascq from sense data. -1 means invalid. */
|
||||||
|
@ -581,12 +580,6 @@ static u32 soft_unresettable_controller[] = {
|
||||||
0x409D0E11, /* Smart Array 6400 EM */
|
0x409D0E11, /* Smart Array 6400 EM */
|
||||||
};
|
};
|
||||||
|
|
||||||
static u32 needs_abort_tags_swizzled[] = {
|
|
||||||
0x323D103C, /* Smart Array P700m */
|
|
||||||
0x324a103C, /* Smart Array P712m */
|
|
||||||
0x324b103C, /* SmartArray P711m */
|
|
||||||
};
|
|
||||||
|
|
||||||
static int board_id_in_array(u32 a[], int nelems, u32 board_id)
|
static int board_id_in_array(u32 a[], int nelems, u32 board_id)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -615,12 +608,6 @@ static int ctlr_is_resettable(u32 board_id)
|
||||||
ctlr_is_soft_resettable(board_id);
|
ctlr_is_soft_resettable(board_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ctlr_needs_abort_tags_swizzled(u32 board_id)
|
|
||||||
{
|
|
||||||
return board_id_in_array(needs_abort_tags_swizzled,
|
|
||||||
ARRAY_SIZE(needs_abort_tags_swizzled), board_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t host_show_resettable(struct device *dev,
|
static ssize_t host_show_resettable(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
|
@ -928,8 +915,8 @@ static struct device_attribute *hpsa_shost_attrs[] = {
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HPSA_NRESERVED_CMDS (HPSA_CMDS_RESERVED_FOR_ABORTS + \
|
#define HPSA_NRESERVED_CMDS (HPSA_CMDS_RESERVED_FOR_DRIVER +\
|
||||||
HPSA_CMDS_RESERVED_FOR_DRIVER + HPSA_MAX_CONCURRENT_PASSTHRUS)
|
HPSA_MAX_CONCURRENT_PASSTHRUS)
|
||||||
|
|
||||||
static struct scsi_host_template hpsa_driver_template = {
|
static struct scsi_host_template hpsa_driver_template = {
|
||||||
.module = THIS_MODULE,
|
.module = THIS_MODULE,
|
||||||
|
@ -941,7 +928,6 @@ static struct scsi_host_template hpsa_driver_template = {
|
||||||
.change_queue_depth = hpsa_change_queue_depth,
|
.change_queue_depth = hpsa_change_queue_depth,
|
||||||
.this_id = -1,
|
.this_id = -1,
|
||||||
.use_clustering = ENABLE_CLUSTERING,
|
.use_clustering = ENABLE_CLUSTERING,
|
||||||
.eh_abort_handler = hpsa_eh_abort_handler,
|
|
||||||
.eh_device_reset_handler = hpsa_eh_device_reset_handler,
|
.eh_device_reset_handler = hpsa_eh_device_reset_handler,
|
||||||
.ioctl = hpsa_ioctl,
|
.ioctl = hpsa_ioctl,
|
||||||
.slave_alloc = hpsa_slave_alloc,
|
.slave_alloc = hpsa_slave_alloc,
|
||||||
|
@ -2361,26 +2347,12 @@ static void hpsa_cmd_resolve_events(struct ctlr_info *h,
|
||||||
bool do_wake = false;
|
bool do_wake = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prevent the following race in the abort handler:
|
* Reset c->scsi_cmd here so that the reset handler will know
|
||||||
*
|
|
||||||
* 1. LLD is requested to abort a SCSI command
|
|
||||||
* 2. The SCSI command completes
|
|
||||||
* 3. The struct CommandList associated with step 2 is made available
|
|
||||||
* 4. New I/O request to LLD to another LUN re-uses struct CommandList
|
|
||||||
* 5. Abort handler follows scsi_cmnd->host_scribble and
|
|
||||||
* finds struct CommandList and tries to aborts it
|
|
||||||
* Now we have aborted the wrong command.
|
|
||||||
*
|
|
||||||
* Reset c->scsi_cmd here so that the abort or reset handler will know
|
|
||||||
* this command has completed. Then, check to see if the handler is
|
* this command has completed. Then, check to see if the handler is
|
||||||
* waiting for this command, and, if so, wake it.
|
* waiting for this command, and, if so, wake it.
|
||||||
*/
|
*/
|
||||||
c->scsi_cmd = SCSI_CMD_IDLE;
|
c->scsi_cmd = SCSI_CMD_IDLE;
|
||||||
mb(); /* Declare command idle before checking for pending events. */
|
mb(); /* Declare command idle before checking for pending events. */
|
||||||
if (c->abort_pending) {
|
|
||||||
do_wake = true;
|
|
||||||
c->abort_pending = false;
|
|
||||||
}
|
|
||||||
if (c->reset_pending) {
|
if (c->reset_pending) {
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct hpsa_scsi_dev_t *dev;
|
struct hpsa_scsi_dev_t *dev;
|
||||||
|
@ -2423,20 +2395,6 @@ static void hpsa_retry_cmd(struct ctlr_info *h, struct CommandList *c)
|
||||||
queue_work_on(raw_smp_processor_id(), h->resubmit_wq, &c->work);
|
queue_work_on(raw_smp_processor_id(), h->resubmit_wq, &c->work);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hpsa_set_scsi_cmd_aborted(struct scsi_cmnd *cmd)
|
|
||||||
{
|
|
||||||
cmd->result = DID_ABORT << 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hpsa_cmd_abort_and_free(struct ctlr_info *h, struct CommandList *c,
|
|
||||||
struct scsi_cmnd *cmd)
|
|
||||||
{
|
|
||||||
hpsa_set_scsi_cmd_aborted(cmd);
|
|
||||||
dev_warn(&h->pdev->dev, "CDB %16phN was aborted with status 0x%x\n",
|
|
||||||
c->Request.CDB, c->err_info->ScsiStatus);
|
|
||||||
hpsa_cmd_resolve_and_free(h, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void process_ioaccel2_completion(struct ctlr_info *h,
|
static void process_ioaccel2_completion(struct ctlr_info *h,
|
||||||
struct CommandList *c, struct scsi_cmnd *cmd,
|
struct CommandList *c, struct scsi_cmnd *cmd,
|
||||||
struct hpsa_scsi_dev_t *dev)
|
struct hpsa_scsi_dev_t *dev)
|
||||||
|
@ -2561,12 +2519,9 @@ static void complete_scsi_command(struct CommandList *cp)
|
||||||
return hpsa_cmd_free_and_done(h, cp, cmd);
|
return hpsa_cmd_free_and_done(h, cp, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((unlikely(hpsa_is_pending_event(cp)))) {
|
if ((unlikely(hpsa_is_pending_event(cp))))
|
||||||
if (cp->reset_pending)
|
if (cp->reset_pending)
|
||||||
return hpsa_cmd_free_and_done(h, cp, cmd);
|
return hpsa_cmd_free_and_done(h, cp, cmd);
|
||||||
if (cp->abort_pending)
|
|
||||||
return hpsa_cmd_abort_and_free(h, cp, cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cp->cmd_type == CMD_IOACCEL2)
|
if (cp->cmd_type == CMD_IOACCEL2)
|
||||||
return process_ioaccel2_completion(h, cp, cmd, dev);
|
return process_ioaccel2_completion(h, cp, cmd, dev);
|
||||||
|
@ -2686,8 +2641,8 @@ static void complete_scsi_command(struct CommandList *cp)
|
||||||
cp->Request.CDB);
|
cp->Request.CDB);
|
||||||
break;
|
break;
|
||||||
case CMD_ABORTED:
|
case CMD_ABORTED:
|
||||||
/* Return now to avoid calling scsi_done(). */
|
cmd->result = DID_ABORT << 16;
|
||||||
return hpsa_cmd_abort_and_free(h, cp, cmd);
|
break;
|
||||||
case CMD_ABORT_FAILED:
|
case CMD_ABORT_FAILED:
|
||||||
cmd->result = DID_ERROR << 16;
|
cmd->result = DID_ERROR << 16;
|
||||||
dev_warn(&h->pdev->dev, "CDB %16phN : abort failed\n",
|
dev_warn(&h->pdev->dev, "CDB %16phN : abort failed\n",
|
||||||
|
@ -3793,53 +3748,6 @@ static unsigned char hpsa_volume_offline(struct ctlr_info *h,
|
||||||
return HPSA_LV_OK;
|
return HPSA_LV_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Find out if a logical device supports aborts by simply trying one.
|
|
||||||
* Smart Array may claim not to support aborts on logical drives, but
|
|
||||||
* if a MSA2000 * is connected, the drives on that will be presented
|
|
||||||
* by the Smart Array as logical drives, and aborts may be sent to
|
|
||||||
* those devices successfully. So the simplest way to find out is
|
|
||||||
* to simply try an abort and see how the device responds.
|
|
||||||
*/
|
|
||||||
static int hpsa_device_supports_aborts(struct ctlr_info *h,
|
|
||||||
unsigned char *scsi3addr)
|
|
||||||
{
|
|
||||||
struct CommandList *c;
|
|
||||||
struct ErrorInfo *ei;
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
u64 tag = (u64) -1; /* bogus tag */
|
|
||||||
|
|
||||||
/* Assume that physical devices support aborts */
|
|
||||||
if (!is_logical_dev_addr_mode(scsi3addr))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
c = cmd_alloc(h);
|
|
||||||
|
|
||||||
(void) fill_cmd(c, HPSA_ABORT_MSG, h, &tag, 0, 0, scsi3addr, TYPE_MSG);
|
|
||||||
(void) hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE,
|
|
||||||
DEFAULT_TIMEOUT);
|
|
||||||
/* no unmap needed here because no data xfer. */
|
|
||||||
ei = c->err_info;
|
|
||||||
switch (ei->CommandStatus) {
|
|
||||||
case CMD_INVALID:
|
|
||||||
rc = 0;
|
|
||||||
break;
|
|
||||||
case CMD_UNABORTABLE:
|
|
||||||
case CMD_ABORT_FAILED:
|
|
||||||
rc = 1;
|
|
||||||
break;
|
|
||||||
case CMD_TMF_STATUS:
|
|
||||||
rc = hpsa_evaluate_tmf_status(h, c);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
rc = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cmd_free(h, c);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int hpsa_update_device_info(struct ctlr_info *h,
|
static int hpsa_update_device_info(struct ctlr_info *h,
|
||||||
unsigned char scsi3addr[], struct hpsa_scsi_dev_t *this_device,
|
unsigned char scsi3addr[], struct hpsa_scsi_dev_t *this_device,
|
||||||
unsigned char *is_OBDR_device)
|
unsigned char *is_OBDR_device)
|
||||||
|
@ -3939,31 +3847,6 @@ static int hpsa_update_device_info(struct ctlr_info *h,
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hpsa_update_device_supports_aborts(struct ctlr_info *h,
|
|
||||||
struct hpsa_scsi_dev_t *dev, u8 *scsi3addr)
|
|
||||||
{
|
|
||||||
unsigned long flags;
|
|
||||||
int rc, entry;
|
|
||||||
/*
|
|
||||||
* See if this device supports aborts. If we already know
|
|
||||||
* the device, we already know if it supports aborts, otherwise
|
|
||||||
* we have to find out if it supports aborts by trying one.
|
|
||||||
*/
|
|
||||||
spin_lock_irqsave(&h->devlock, flags);
|
|
||||||
rc = hpsa_scsi_find_entry(dev, h->dev, h->ndevices, &entry);
|
|
||||||
if ((rc == DEVICE_SAME || rc == DEVICE_UPDATED) &&
|
|
||||||
entry >= 0 && entry < h->ndevices) {
|
|
||||||
dev->supports_aborts = h->dev[entry]->supports_aborts;
|
|
||||||
spin_unlock_irqrestore(&h->devlock, flags);
|
|
||||||
} else {
|
|
||||||
spin_unlock_irqrestore(&h->devlock, flags);
|
|
||||||
dev->supports_aborts =
|
|
||||||
hpsa_device_supports_aborts(h, scsi3addr);
|
|
||||||
if (dev->supports_aborts < 0)
|
|
||||||
dev->supports_aborts = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helper function to assign bus, target, lun mapping of devices.
|
* Helper function to assign bus, target, lun mapping of devices.
|
||||||
* Logical drive target and lun are assigned at this time, but
|
* Logical drive target and lun are assigned at this time, but
|
||||||
|
@ -4001,35 +3884,6 @@ static void figure_bus_target_lun(struct ctlr_info *h,
|
||||||
0, lunid & 0x3fff);
|
0, lunid & 0x3fff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get address of physical disk used for an ioaccel2 mode command:
|
|
||||||
* 1. Extract ioaccel2 handle from the command.
|
|
||||||
* 2. Find a matching ioaccel2 handle from list of physical disks.
|
|
||||||
* 3. Return:
|
|
||||||
* 1 and set scsi3addr to address of matching physical
|
|
||||||
* 0 if no matching physical disk was found.
|
|
||||||
*/
|
|
||||||
static int hpsa_get_pdisk_of_ioaccel2(struct ctlr_info *h,
|
|
||||||
struct CommandList *ioaccel2_cmd_to_abort, unsigned char *scsi3addr)
|
|
||||||
{
|
|
||||||
struct io_accel2_cmd *c2 =
|
|
||||||
&h->ioaccel2_cmd_pool[ioaccel2_cmd_to_abort->cmdindex];
|
|
||||||
unsigned long flags;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&h->devlock, flags);
|
|
||||||
for (i = 0; i < h->ndevices; i++)
|
|
||||||
if (h->dev[i]->ioaccel_handle == le32_to_cpu(c2->scsi_nexus)) {
|
|
||||||
memcpy(scsi3addr, h->dev[i]->scsi3addr,
|
|
||||||
sizeof(h->dev[i]->scsi3addr));
|
|
||||||
spin_unlock_irqrestore(&h->devlock, flags);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&h->devlock, flags);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int figure_external_status(struct ctlr_info *h, int raid_ctlr_position,
|
static int figure_external_status(struct ctlr_info *h, int raid_ctlr_position,
|
||||||
int i, int nphysicals, int nlocal_logicals)
|
int i, int nphysicals, int nlocal_logicals)
|
||||||
{
|
{
|
||||||
|
@ -4394,7 +4248,6 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h)
|
||||||
}
|
}
|
||||||
|
|
||||||
figure_bus_target_lun(h, lunaddrbytes, tmpdevice);
|
figure_bus_target_lun(h, lunaddrbytes, tmpdevice);
|
||||||
hpsa_update_device_supports_aborts(h, tmpdevice, lunaddrbytes);
|
|
||||||
this_device = currentsd[ncurrent];
|
this_device = currentsd[ncurrent];
|
||||||
|
|
||||||
/* Turn on discovery_polling if there are ext target devices.
|
/* Turn on discovery_polling if there are ext target devices.
|
||||||
|
@ -5528,8 +5381,6 @@ static void hpsa_command_resubmit_worker(struct work_struct *work)
|
||||||
}
|
}
|
||||||
if (c->reset_pending)
|
if (c->reset_pending)
|
||||||
return hpsa_cmd_free_and_done(c->h, c, cmd);
|
return hpsa_cmd_free_and_done(c->h, c, cmd);
|
||||||
if (c->abort_pending)
|
|
||||||
return hpsa_cmd_abort_and_free(c->h, c, cmd);
|
|
||||||
if (c->cmd_type == CMD_IOACCEL2) {
|
if (c->cmd_type == CMD_IOACCEL2) {
|
||||||
struct ctlr_info *h = c->h;
|
struct ctlr_info *h = c->h;
|
||||||
struct io_accel2_cmd *c2 = &h->ioaccel2_cmd_pool[c->cmdindex];
|
struct io_accel2_cmd *c2 = &h->ioaccel2_cmd_pool[c->cmdindex];
|
||||||
|
@ -5987,433 +5838,6 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void swizzle_abort_tag(u8 *tag)
|
|
||||||
{
|
|
||||||
u8 original_tag[8];
|
|
||||||
|
|
||||||
memcpy(original_tag, tag, 8);
|
|
||||||
tag[0] = original_tag[3];
|
|
||||||
tag[1] = original_tag[2];
|
|
||||||
tag[2] = original_tag[1];
|
|
||||||
tag[3] = original_tag[0];
|
|
||||||
tag[4] = original_tag[7];
|
|
||||||
tag[5] = original_tag[6];
|
|
||||||
tag[6] = original_tag[5];
|
|
||||||
tag[7] = original_tag[4];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hpsa_get_tag(struct ctlr_info *h,
|
|
||||||
struct CommandList *c, __le32 *taglower, __le32 *tagupper)
|
|
||||||
{
|
|
||||||
u64 tag;
|
|
||||||
if (c->cmd_type == CMD_IOACCEL1) {
|
|
||||||
struct io_accel1_cmd *cm1 = (struct io_accel1_cmd *)
|
|
||||||
&h->ioaccel_cmd_pool[c->cmdindex];
|
|
||||||
tag = le64_to_cpu(cm1->tag);
|
|
||||||
*tagupper = cpu_to_le32(tag >> 32);
|
|
||||||
*taglower = cpu_to_le32(tag);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (c->cmd_type == CMD_IOACCEL2) {
|
|
||||||
struct io_accel2_cmd *cm2 = (struct io_accel2_cmd *)
|
|
||||||
&h->ioaccel2_cmd_pool[c->cmdindex];
|
|
||||||
/* upper tag not used in ioaccel2 mode */
|
|
||||||
memset(tagupper, 0, sizeof(*tagupper));
|
|
||||||
*taglower = cm2->Tag;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tag = le64_to_cpu(c->Header.tag);
|
|
||||||
*tagupper = cpu_to_le32(tag >> 32);
|
|
||||||
*taglower = cpu_to_le32(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int hpsa_send_abort(struct ctlr_info *h, unsigned char *scsi3addr,
|
|
||||||
struct CommandList *abort, int reply_queue)
|
|
||||||
{
|
|
||||||
int rc = IO_OK;
|
|
||||||
struct CommandList *c;
|
|
||||||
struct ErrorInfo *ei;
|
|
||||||
__le32 tagupper, taglower;
|
|
||||||
|
|
||||||
c = cmd_alloc(h);
|
|
||||||
|
|
||||||
/* fill_cmd can't fail here, no buffer to map */
|
|
||||||
(void) fill_cmd(c, HPSA_ABORT_MSG, h, &abort->Header.tag,
|
|
||||||
0, 0, scsi3addr, TYPE_MSG);
|
|
||||||
if (h->needs_abort_tags_swizzled)
|
|
||||||
swizzle_abort_tag(&c->Request.CDB[4]);
|
|
||||||
(void) hpsa_scsi_do_simple_cmd(h, c, reply_queue, DEFAULT_TIMEOUT);
|
|
||||||
hpsa_get_tag(h, abort, &taglower, &tagupper);
|
|
||||||
dev_dbg(&h->pdev->dev, "%s: Tag:0x%08x:%08x: do_simple_cmd(abort) completed.\n",
|
|
||||||
__func__, tagupper, taglower);
|
|
||||||
/* no unmap needed here because no data xfer. */
|
|
||||||
|
|
||||||
ei = c->err_info;
|
|
||||||
switch (ei->CommandStatus) {
|
|
||||||
case CMD_SUCCESS:
|
|
||||||
break;
|
|
||||||
case CMD_TMF_STATUS:
|
|
||||||
rc = hpsa_evaluate_tmf_status(h, c);
|
|
||||||
break;
|
|
||||||
case CMD_UNABORTABLE: /* Very common, don't make noise. */
|
|
||||||
rc = -1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dev_dbg(&h->pdev->dev, "%s: Tag:0x%08x:%08x: interpreting error.\n",
|
|
||||||
__func__, tagupper, taglower);
|
|
||||||
hpsa_scsi_interpret_error(h, c);
|
|
||||||
rc = -1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cmd_free(h, c);
|
|
||||||
dev_dbg(&h->pdev->dev, "%s: Tag:0x%08x:%08x: Finished.\n",
|
|
||||||
__func__, tagupper, taglower);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setup_ioaccel2_abort_cmd(struct CommandList *c, struct ctlr_info *h,
|
|
||||||
struct CommandList *command_to_abort, int reply_queue)
|
|
||||||
{
|
|
||||||
struct io_accel2_cmd *c2 = &h->ioaccel2_cmd_pool[c->cmdindex];
|
|
||||||
struct hpsa_tmf_struct *ac = (struct hpsa_tmf_struct *) c2;
|
|
||||||
struct io_accel2_cmd *c2a =
|
|
||||||
&h->ioaccel2_cmd_pool[command_to_abort->cmdindex];
|
|
||||||
struct scsi_cmnd *scmd = command_to_abort->scsi_cmd;
|
|
||||||
struct hpsa_scsi_dev_t *dev = scmd->device->hostdata;
|
|
||||||
|
|
||||||
if (!dev)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We're overlaying struct hpsa_tmf_struct on top of something which
|
|
||||||
* was allocated as a struct io_accel2_cmd, so we better be sure it
|
|
||||||
* actually fits, and doesn't overrun the error info space.
|
|
||||||
*/
|
|
||||||
BUILD_BUG_ON(sizeof(struct hpsa_tmf_struct) >
|
|
||||||
sizeof(struct io_accel2_cmd));
|
|
||||||
BUG_ON(offsetof(struct io_accel2_cmd, error_data) <
|
|
||||||
offsetof(struct hpsa_tmf_struct, error_len) +
|
|
||||||
sizeof(ac->error_len));
|
|
||||||
|
|
||||||
c->cmd_type = IOACCEL2_TMF;
|
|
||||||
c->scsi_cmd = SCSI_CMD_BUSY;
|
|
||||||
|
|
||||||
/* Adjust the DMA address to point to the accelerated command buffer */
|
|
||||||
c->busaddr = (u32) h->ioaccel2_cmd_pool_dhandle +
|
|
||||||
(c->cmdindex * sizeof(struct io_accel2_cmd));
|
|
||||||
BUG_ON(c->busaddr & 0x0000007F);
|
|
||||||
|
|
||||||
memset(ac, 0, sizeof(*c2)); /* yes this is correct */
|
|
||||||
ac->iu_type = IOACCEL2_IU_TMF_TYPE;
|
|
||||||
ac->reply_queue = reply_queue;
|
|
||||||
ac->tmf = IOACCEL2_TMF_ABORT;
|
|
||||||
ac->it_nexus = cpu_to_le32(dev->ioaccel_handle);
|
|
||||||
memset(ac->lun_id, 0, sizeof(ac->lun_id));
|
|
||||||
ac->tag = cpu_to_le64(c->cmdindex << DIRECT_LOOKUP_SHIFT);
|
|
||||||
ac->abort_tag = cpu_to_le64(le32_to_cpu(c2a->Tag));
|
|
||||||
ac->error_ptr = cpu_to_le64(c->busaddr +
|
|
||||||
offsetof(struct io_accel2_cmd, error_data));
|
|
||||||
ac->error_len = cpu_to_le32(sizeof(c2->error_data));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ioaccel2 path firmware cannot handle abort task requests.
|
|
||||||
* Change abort requests to physical target reset, and send to the
|
|
||||||
* address of the physical disk used for the ioaccel 2 command.
|
|
||||||
* Return 0 on success (IO_OK)
|
|
||||||
* -1 on failure
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int hpsa_send_reset_as_abort_ioaccel2(struct ctlr_info *h,
|
|
||||||
unsigned char *scsi3addr, struct CommandList *abort, int reply_queue)
|
|
||||||
{
|
|
||||||
int rc = IO_OK;
|
|
||||||
struct scsi_cmnd *scmd; /* scsi command within request being aborted */
|
|
||||||
struct hpsa_scsi_dev_t *dev; /* device to which scsi cmd was sent */
|
|
||||||
unsigned char phys_scsi3addr[8]; /* addr of phys disk with volume */
|
|
||||||
unsigned char *psa = &phys_scsi3addr[0];
|
|
||||||
|
|
||||||
/* Get a pointer to the hpsa logical device. */
|
|
||||||
scmd = abort->scsi_cmd;
|
|
||||||
dev = (struct hpsa_scsi_dev_t *)(scmd->device->hostdata);
|
|
||||||
if (dev == NULL) {
|
|
||||||
dev_warn(&h->pdev->dev,
|
|
||||||
"Cannot abort: no device pointer for command.\n");
|
|
||||||
return -1; /* not abortable */
|
|
||||||
}
|
|
||||||
|
|
||||||
if (h->raid_offload_debug > 0)
|
|
||||||
dev_info(&h->pdev->dev,
|
|
||||||
"scsi %d:%d:%d:%d %s scsi3addr 0x%8phN\n",
|
|
||||||
h->scsi_host->host_no, dev->bus, dev->target, dev->lun,
|
|
||||||
"Reset as abort", scsi3addr);
|
|
||||||
|
|
||||||
if (!dev->offload_enabled) {
|
|
||||||
dev_warn(&h->pdev->dev,
|
|
||||||
"Can't abort: device is not operating in HP SSD Smart Path mode.\n");
|
|
||||||
return -1; /* not abortable */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Incoming scsi3addr is logical addr. We need physical disk addr. */
|
|
||||||
if (!hpsa_get_pdisk_of_ioaccel2(h, abort, psa)) {
|
|
||||||
dev_warn(&h->pdev->dev, "Can't abort: Failed lookup of physical address.\n");
|
|
||||||
return -1; /* not abortable */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* send the reset */
|
|
||||||
if (h->raid_offload_debug > 0)
|
|
||||||
dev_info(&h->pdev->dev,
|
|
||||||
"Reset as abort: Resetting physical device at scsi3addr 0x%8phN\n",
|
|
||||||
psa);
|
|
||||||
rc = hpsa_do_reset(h, dev, psa, HPSA_PHYS_TARGET_RESET, reply_queue);
|
|
||||||
if (rc != 0) {
|
|
||||||
dev_warn(&h->pdev->dev,
|
|
||||||
"Reset as abort: Failed on physical device at scsi3addr 0x%8phN\n",
|
|
||||||
psa);
|
|
||||||
return rc; /* failed to reset */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* wait for device to recover */
|
|
||||||
if (wait_for_device_to_become_ready(h, psa, reply_queue) != 0) {
|
|
||||||
dev_warn(&h->pdev->dev,
|
|
||||||
"Reset as abort: Failed: Device never recovered from reset: 0x%8phN\n",
|
|
||||||
psa);
|
|
||||||
return -1; /* failed to recover */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* device recovered */
|
|
||||||
dev_info(&h->pdev->dev,
|
|
||||||
"Reset as abort: Device recovered from reset: scsi3addr 0x%8phN\n",
|
|
||||||
psa);
|
|
||||||
|
|
||||||
return rc; /* success */
|
|
||||||
}
|
|
||||||
|
|
||||||
static int hpsa_send_abort_ioaccel2(struct ctlr_info *h,
|
|
||||||
struct CommandList *abort, int reply_queue)
|
|
||||||
{
|
|
||||||
int rc = IO_OK;
|
|
||||||
struct CommandList *c;
|
|
||||||
__le32 taglower, tagupper;
|
|
||||||
struct hpsa_scsi_dev_t *dev;
|
|
||||||
struct io_accel2_cmd *c2;
|
|
||||||
|
|
||||||
dev = abort->scsi_cmd->device->hostdata;
|
|
||||||
if (!dev)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (!dev->offload_enabled && !dev->hba_ioaccel_enabled)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
c = cmd_alloc(h);
|
|
||||||
setup_ioaccel2_abort_cmd(c, h, abort, reply_queue);
|
|
||||||
c2 = &h->ioaccel2_cmd_pool[c->cmdindex];
|
|
||||||
(void) hpsa_scsi_do_simple_cmd(h, c, reply_queue, DEFAULT_TIMEOUT);
|
|
||||||
hpsa_get_tag(h, abort, &taglower, &tagupper);
|
|
||||||
dev_dbg(&h->pdev->dev,
|
|
||||||
"%s: Tag:0x%08x:%08x: do_simple_cmd(ioaccel2 abort) completed.\n",
|
|
||||||
__func__, tagupper, taglower);
|
|
||||||
/* no unmap needed here because no data xfer. */
|
|
||||||
|
|
||||||
dev_dbg(&h->pdev->dev,
|
|
||||||
"%s: Tag:0x%08x:%08x: abort service response = 0x%02x.\n",
|
|
||||||
__func__, tagupper, taglower, c2->error_data.serv_response);
|
|
||||||
switch (c2->error_data.serv_response) {
|
|
||||||
case IOACCEL2_SERV_RESPONSE_TMF_COMPLETE:
|
|
||||||
case IOACCEL2_SERV_RESPONSE_TMF_SUCCESS:
|
|
||||||
rc = 0;
|
|
||||||
break;
|
|
||||||
case IOACCEL2_SERV_RESPONSE_TMF_REJECTED:
|
|
||||||
case IOACCEL2_SERV_RESPONSE_FAILURE:
|
|
||||||
case IOACCEL2_SERV_RESPONSE_TMF_WRONG_LUN:
|
|
||||||
rc = -1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dev_warn(&h->pdev->dev,
|
|
||||||
"%s: Tag:0x%08x:%08x: unknown abort service response 0x%02x\n",
|
|
||||||
__func__, tagupper, taglower,
|
|
||||||
c2->error_data.serv_response);
|
|
||||||
rc = -1;
|
|
||||||
}
|
|
||||||
cmd_free(h, c);
|
|
||||||
dev_dbg(&h->pdev->dev, "%s: Tag:0x%08x:%08x: Finished.\n", __func__,
|
|
||||||
tagupper, taglower);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int hpsa_send_abort_both_ways(struct ctlr_info *h,
|
|
||||||
struct hpsa_scsi_dev_t *dev, struct CommandList *abort, int reply_queue)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* ioccelerator mode 2 commands should be aborted via the
|
|
||||||
* accelerated path, since RAID path is unaware of these commands,
|
|
||||||
* but not all underlying firmware can handle abort TMF.
|
|
||||||
* Change abort to physical device reset when abort TMF is unsupported.
|
|
||||||
*/
|
|
||||||
if (abort->cmd_type == CMD_IOACCEL2) {
|
|
||||||
if ((HPSATMF_IOACCEL_ENABLED & h->TMFSupportFlags) ||
|
|
||||||
dev->physical_device)
|
|
||||||
return hpsa_send_abort_ioaccel2(h, abort,
|
|
||||||
reply_queue);
|
|
||||||
else
|
|
||||||
return hpsa_send_reset_as_abort_ioaccel2(h,
|
|
||||||
dev->scsi3addr,
|
|
||||||
abort, reply_queue);
|
|
||||||
}
|
|
||||||
return hpsa_send_abort(h, dev->scsi3addr, abort, reply_queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Find out which reply queue a command was meant to return on */
|
|
||||||
static int hpsa_extract_reply_queue(struct ctlr_info *h,
|
|
||||||
struct CommandList *c)
|
|
||||||
{
|
|
||||||
if (c->cmd_type == CMD_IOACCEL2)
|
|
||||||
return h->ioaccel2_cmd_pool[c->cmdindex].reply_queue;
|
|
||||||
return c->Header.ReplyQueue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Limit concurrency of abort commands to prevent
|
|
||||||
* over-subscription of commands
|
|
||||||
*/
|
|
||||||
static inline int wait_for_available_abort_cmd(struct ctlr_info *h)
|
|
||||||
{
|
|
||||||
#define ABORT_CMD_WAIT_MSECS 5000
|
|
||||||
return !wait_event_timeout(h->abort_cmd_wait_queue,
|
|
||||||
atomic_dec_if_positive(&h->abort_cmds_available) >= 0,
|
|
||||||
msecs_to_jiffies(ABORT_CMD_WAIT_MSECS));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send an abort for the specified command.
|
|
||||||
* If the device and controller support it,
|
|
||||||
* send a task abort request.
|
|
||||||
*/
|
|
||||||
static int hpsa_eh_abort_handler(struct scsi_cmnd *sc)
|
|
||||||
{
|
|
||||||
|
|
||||||
int rc;
|
|
||||||
struct ctlr_info *h;
|
|
||||||
struct hpsa_scsi_dev_t *dev;
|
|
||||||
struct CommandList *abort; /* pointer to command to be aborted */
|
|
||||||
struct scsi_cmnd *as; /* ptr to scsi cmd inside aborted command. */
|
|
||||||
char msg[256]; /* For debug messaging. */
|
|
||||||
int ml = 0;
|
|
||||||
__le32 tagupper, taglower;
|
|
||||||
int refcount, reply_queue;
|
|
||||||
|
|
||||||
if (sc == NULL)
|
|
||||||
return FAILED;
|
|
||||||
|
|
||||||
if (sc->device == NULL)
|
|
||||||
return FAILED;
|
|
||||||
|
|
||||||
/* Find the controller of the command to be aborted */
|
|
||||||
h = sdev_to_hba(sc->device);
|
|
||||||
if (h == NULL)
|
|
||||||
return FAILED;
|
|
||||||
|
|
||||||
/* Find the device of the command to be aborted */
|
|
||||||
dev = sc->device->hostdata;
|
|
||||||
if (!dev) {
|
|
||||||
dev_err(&h->pdev->dev, "%s FAILED, Device lookup failed.\n",
|
|
||||||
msg);
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If controller locked up, we can guarantee command won't complete */
|
|
||||||
if (lockup_detected(h)) {
|
|
||||||
hpsa_show_dev_msg(KERN_WARNING, h, dev,
|
|
||||||
"ABORT FAILED, lockup detected");
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is a good time to check if controller lockup has occurred */
|
|
||||||
if (detect_controller_lockup(h)) {
|
|
||||||
hpsa_show_dev_msg(KERN_WARNING, h, dev,
|
|
||||||
"ABORT FAILED, new lockup detected");
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check that controller supports some kind of task abort */
|
|
||||||
if (!(HPSATMF_PHYS_TASK_ABORT & h->TMFSupportFlags) &&
|
|
||||||
!(HPSATMF_LOG_TASK_ABORT & h->TMFSupportFlags))
|
|
||||||
return FAILED;
|
|
||||||
|
|
||||||
memset(msg, 0, sizeof(msg));
|
|
||||||
ml += sprintf(msg+ml, "scsi %d:%d:%d:%llu %s %p",
|
|
||||||
h->scsi_host->host_no, sc->device->channel,
|
|
||||||
sc->device->id, sc->device->lun,
|
|
||||||
"Aborting command", sc);
|
|
||||||
|
|
||||||
/* Get SCSI command to be aborted */
|
|
||||||
abort = (struct CommandList *) sc->host_scribble;
|
|
||||||
if (abort == NULL) {
|
|
||||||
/* This can happen if the command already completed. */
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
refcount = atomic_inc_return(&abort->refcount);
|
|
||||||
if (refcount == 1) { /* Command is done already. */
|
|
||||||
cmd_free(h, abort);
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't bother trying the abort if we know it won't work. */
|
|
||||||
if (abort->cmd_type != CMD_IOACCEL2 &&
|
|
||||||
abort->cmd_type != CMD_IOACCEL1 && !dev->supports_aborts) {
|
|
||||||
cmd_free(h, abort);
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check that we're aborting the right command.
|
|
||||||
* It's possible the CommandList already completed and got re-used.
|
|
||||||
*/
|
|
||||||
if (abort->scsi_cmd != sc) {
|
|
||||||
cmd_free(h, abort);
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
abort->abort_pending = true;
|
|
||||||
hpsa_get_tag(h, abort, &taglower, &tagupper);
|
|
||||||
reply_queue = hpsa_extract_reply_queue(h, abort);
|
|
||||||
ml += sprintf(msg+ml, "Tag:0x%08x:%08x ", tagupper, taglower);
|
|
||||||
as = abort->scsi_cmd;
|
|
||||||
if (as != NULL)
|
|
||||||
ml += sprintf(msg+ml,
|
|
||||||
"CDBLen: %d CDB: 0x%02x%02x... SN: 0x%lx ",
|
|
||||||
as->cmd_len, as->cmnd[0], as->cmnd[1],
|
|
||||||
as->serial_number);
|
|
||||||
dev_warn(&h->pdev->dev, "%s BEING SENT\n", msg);
|
|
||||||
hpsa_show_dev_msg(KERN_WARNING, h, dev, "Aborting command");
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Command is in flight, or possibly already completed
|
|
||||||
* by the firmware (but not to the scsi mid layer) but we can't
|
|
||||||
* distinguish which. Send the abort down.
|
|
||||||
*/
|
|
||||||
if (wait_for_available_abort_cmd(h)) {
|
|
||||||
dev_warn(&h->pdev->dev,
|
|
||||||
"%s FAILED, timeout waiting for an abort command to become available.\n",
|
|
||||||
msg);
|
|
||||||
cmd_free(h, abort);
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
rc = hpsa_send_abort_both_ways(h, dev, abort, reply_queue);
|
|
||||||
atomic_inc(&h->abort_cmds_available);
|
|
||||||
wake_up_all(&h->abort_cmd_wait_queue);
|
|
||||||
if (rc != 0) {
|
|
||||||
dev_warn(&h->pdev->dev, "%s SENT, FAILED\n", msg);
|
|
||||||
hpsa_show_dev_msg(KERN_WARNING, h, dev,
|
|
||||||
"FAILED to abort command");
|
|
||||||
cmd_free(h, abort);
|
|
||||||
return FAILED;
|
|
||||||
}
|
|
||||||
dev_info(&h->pdev->dev, "%s SENT, SUCCESS\n", msg);
|
|
||||||
wait_event(h->event_sync_wait_queue,
|
|
||||||
abort->scsi_cmd != sc || lockup_detected(h));
|
|
||||||
cmd_free(h, abort);
|
|
||||||
return !lockup_detected(h) ? SUCCESS : FAILED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For operations with an associated SCSI command, a command block is allocated
|
* For operations with an associated SCSI command, a command block is allocated
|
||||||
* at init, and managed by cmd_tagged_alloc() and cmd_tagged_free() using the
|
* at init, and managed by cmd_tagged_alloc() and cmd_tagged_free() using the
|
||||||
|
@ -6459,9 +5883,7 @@ static void cmd_tagged_free(struct ctlr_info *h, struct CommandList *c)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Release our reference to the block. We don't need to do anything
|
* Release our reference to the block. We don't need to do anything
|
||||||
* else to free it, because it is accessed by index. (There's no point
|
* else to free it, because it is accessed by index.
|
||||||
* in checking the result of the decrement, since we cannot guarantee
|
|
||||||
* that there isn't a concurrent abort which is also accessing it.)
|
|
||||||
*/
|
*/
|
||||||
(void)atomic_dec(&c->refcount);
|
(void)atomic_dec(&c->refcount);
|
||||||
}
|
}
|
||||||
|
@ -7000,7 +6422,6 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
|
||||||
int cmd_type)
|
int cmd_type)
|
||||||
{
|
{
|
||||||
int pci_dir = XFER_NONE;
|
int pci_dir = XFER_NONE;
|
||||||
u64 tag; /* for commands to be aborted */
|
|
||||||
|
|
||||||
c->cmd_type = CMD_IOCTL_PEND;
|
c->cmd_type = CMD_IOCTL_PEND;
|
||||||
c->scsi_cmd = SCSI_CMD_BUSY;
|
c->scsi_cmd = SCSI_CMD_BUSY;
|
||||||
|
@ -7184,27 +6605,6 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
|
||||||
c->Request.CDB[6] = 0x00;
|
c->Request.CDB[6] = 0x00;
|
||||||
c->Request.CDB[7] = 0x00;
|
c->Request.CDB[7] = 0x00;
|
||||||
break;
|
break;
|
||||||
case HPSA_ABORT_MSG:
|
|
||||||
memcpy(&tag, buff, sizeof(tag));
|
|
||||||
dev_dbg(&h->pdev->dev,
|
|
||||||
"Abort Tag:0x%016llx using rqst Tag:0x%016llx",
|
|
||||||
tag, c->Header.tag);
|
|
||||||
c->Request.CDBLen = 16;
|
|
||||||
c->Request.type_attr_dir =
|
|
||||||
TYPE_ATTR_DIR(cmd_type,
|
|
||||||
ATTR_SIMPLE, XFER_WRITE);
|
|
||||||
c->Request.Timeout = 0; /* Don't time out */
|
|
||||||
c->Request.CDB[0] = HPSA_TASK_MANAGEMENT;
|
|
||||||
c->Request.CDB[1] = HPSA_TMF_ABORT_TASK;
|
|
||||||
c->Request.CDB[2] = 0x00; /* reserved */
|
|
||||||
c->Request.CDB[3] = 0x00; /* reserved */
|
|
||||||
/* Tag to abort goes in CDB[4]-CDB[11] */
|
|
||||||
memcpy(&c->Request.CDB[4], &tag, sizeof(tag));
|
|
||||||
c->Request.CDB[12] = 0x00; /* reserved */
|
|
||||||
c->Request.CDB[13] = 0x00; /* reserved */
|
|
||||||
c->Request.CDB[14] = 0x00; /* reserved */
|
|
||||||
c->Request.CDB[15] = 0x00; /* reserved */
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
dev_warn(&h->pdev->dev, "unknown message type %d\n",
|
dev_warn(&h->pdev->dev, "unknown message type %d\n",
|
||||||
cmd);
|
cmd);
|
||||||
|
@ -8162,9 +7562,6 @@ static int hpsa_pci_init(struct ctlr_info *h)
|
||||||
h->product_name = products[prod_index].product_name;
|
h->product_name = products[prod_index].product_name;
|
||||||
h->access = *(products[prod_index].access);
|
h->access = *(products[prod_index].access);
|
||||||
|
|
||||||
h->needs_abort_tags_swizzled =
|
|
||||||
ctlr_needs_abort_tags_swizzled(h->board_id);
|
|
||||||
|
|
||||||
pci_disable_link_state(h->pdev, PCIE_LINK_STATE_L0S |
|
pci_disable_link_state(h->pdev, PCIE_LINK_STATE_L0S |
|
||||||
PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
|
PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
|
||||||
|
|
||||||
|
@ -8885,7 +8282,6 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
spin_lock_init(&h->scan_lock);
|
spin_lock_init(&h->scan_lock);
|
||||||
spin_lock_init(&h->reset_lock);
|
spin_lock_init(&h->reset_lock);
|
||||||
atomic_set(&h->passthru_cmds_avail, HPSA_MAX_CONCURRENT_PASSTHRUS);
|
atomic_set(&h->passthru_cmds_avail, HPSA_MAX_CONCURRENT_PASSTHRUS);
|
||||||
atomic_set(&h->abort_cmds_available, HPSA_CMDS_RESERVED_FOR_ABORTS);
|
|
||||||
|
|
||||||
/* Allocate and clear per-cpu variable lockup_detected */
|
/* Allocate and clear per-cpu variable lockup_detected */
|
||||||
h->lockup_detected = alloc_percpu(u32);
|
h->lockup_detected = alloc_percpu(u32);
|
||||||
|
@ -8937,7 +8333,6 @@ static int hpsa_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
if (rc)
|
if (rc)
|
||||||
goto clean5; /* cmd, irq, shost, pci, lu, aer/h */
|
goto clean5; /* cmd, irq, shost, pci, lu, aer/h */
|
||||||
init_waitqueue_head(&h->scan_wait_queue);
|
init_waitqueue_head(&h->scan_wait_queue);
|
||||||
init_waitqueue_head(&h->abort_cmd_wait_queue);
|
|
||||||
init_waitqueue_head(&h->event_sync_wait_queue);
|
init_waitqueue_head(&h->event_sync_wait_queue);
|
||||||
mutex_init(&h->reset_mutex);
|
mutex_init(&h->reset_mutex);
|
||||||
h->scan_finished = 1; /* no scan currently in progress */
|
h->scan_finished = 1; /* no scan currently in progress */
|
||||||
|
|
|
@ -298,7 +298,6 @@ struct ctlr_info {
|
||||||
struct workqueue_struct *resubmit_wq;
|
struct workqueue_struct *resubmit_wq;
|
||||||
struct workqueue_struct *rescan_ctlr_wq;
|
struct workqueue_struct *rescan_ctlr_wq;
|
||||||
atomic_t abort_cmds_available;
|
atomic_t abort_cmds_available;
|
||||||
wait_queue_head_t abort_cmd_wait_queue;
|
|
||||||
wait_queue_head_t event_sync_wait_queue;
|
wait_queue_head_t event_sync_wait_queue;
|
||||||
struct mutex reset_mutex;
|
struct mutex reset_mutex;
|
||||||
u8 reset_in_progress;
|
u8 reset_in_progress;
|
||||||
|
|
Loading…
Reference in a new issue