summaryrefslogtreecommitdiff
path: root/drivers/scsi/pm8001
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/pm8001')
-rw-r--r--drivers/scsi/pm8001/pm8001_ctl.c7
-rw-r--r--drivers/scsi/pm8001/pm8001_defs.h9
-rw-r--r--drivers/scsi/pm8001/pm8001_hwi.c5
-rw-r--r--drivers/scsi/pm8001/pm8001_init.c41
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.c100
-rw-r--r--drivers/scsi/pm8001/pm8001_sas.h6
-rw-r--r--drivers/scsi/pm8001/pm80xx_hwi.c70
7 files changed, 158 insertions, 80 deletions
diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c
index 7b27618fd7b2..7618f9cc9986 100644
--- a/drivers/scsi/pm8001/pm8001_ctl.c
+++ b/drivers/scsi/pm8001/pm8001_ctl.c
@@ -644,7 +644,7 @@ static DEVICE_ATTR(gsm_log, S_IRUGO, pm8001_ctl_gsm_log_show, NULL);
#define FLASH_CMD_SET_NVMD 0x02
struct flash_command {
- u8 command[8];
+ u8 command[8] __nonstring;
int code;
};
@@ -1039,3 +1039,8 @@ const struct attribute_group *pm8001_host_groups[] = {
&pm8001_host_attr_group,
NULL
};
+
+const struct attribute_group *pm8001_sdev_groups[] = {
+ &sas_ata_sdev_attr_group,
+ NULL
+};
diff --git a/drivers/scsi/pm8001/pm8001_defs.h b/drivers/scsi/pm8001/pm8001_defs.h
index 501b574239e8..4e19d61dffbb 100644
--- a/drivers/scsi/pm8001/pm8001_defs.h
+++ b/drivers/scsi/pm8001/pm8001_defs.h
@@ -90,10 +90,13 @@ enum port_type {
#define PM8001_MAX_PORTS 16 /* max. possible ports */
#define PM8001_MAX_DEVICES 2048 /* max supported device */
#define PM8001_MAX_MSIX_VEC 64 /* max msi-x int for spcv/ve */
-#define PM8001_RESERVE_SLOT 8
+#define PM8001_RESERVE_SLOT 128
-#define CONFIG_SCSI_PM8001_MAX_DMA_SG 528
-#define PM8001_MAX_DMA_SG CONFIG_SCSI_PM8001_MAX_DMA_SG
+#define PM8001_SECTOR_SIZE 512
+#define PM8001_PAGE_SIZE_4K 4096
+#define PM8001_MAX_IO_SIZE (4 * 1024 * 1024)
+#define PM8001_MAX_DMA_SG (PM8001_MAX_IO_SIZE / PM8001_PAGE_SIZE_4K)
+#define PM8001_MAX_SECTORS (PM8001_MAX_IO_SIZE / PM8001_SECTOR_SIZE)
enum memory_region_num {
AAP1 = 0x0, /* application acceleration processor */
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c
index dec1e2d380f1..42a4eeac24c9 100644
--- a/drivers/scsi/pm8001/pm8001_hwi.c
+++ b/drivers/scsi/pm8001/pm8001_hwi.c
@@ -3472,12 +3472,13 @@ int pm8001_mpi_task_abort_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
status, tag, scp);
switch (status) {
case IO_SUCCESS:
- pm8001_dbg(pm8001_ha, EH, "IO_SUCCESS\n");
+ pm8001_dbg(pm8001_ha, FAIL, "ABORT IO_SUCCESS for tag %#x\n",
+ tag);
ts->resp = SAS_TASK_COMPLETE;
ts->stat = SAS_SAM_STAT_GOOD;
break;
case IO_NOT_VALID:
- pm8001_dbg(pm8001_ha, EH, "IO_NOT_VALID\n");
+ pm8001_dbg(pm8001_ha, FAIL, "IO_NOT_VALID for tag %#x\n", tag);
ts->resp = TMF_RESP_FUNC_FAILED;
break;
}
diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c
index ed6b7d954dda..599410bcdfea 100644
--- a/drivers/scsi/pm8001/pm8001_init.c
+++ b/drivers/scsi/pm8001/pm8001_init.c
@@ -68,6 +68,10 @@ static bool pm8001_read_wwn = true;
module_param_named(read_wwn, pm8001_read_wwn, bool, 0444);
MODULE_PARM_DESC(zoned, "Get WWN from the controller. Default: true");
+uint pcs_event_log_severity = 0x03;
+module_param(pcs_event_log_severity, int, 0644);
+MODULE_PARM_DESC(pcs_event_log_severity, "PCS event log severity level");
+
static struct scsi_transport_template *pm8001_stt;
static int pm8001_init_ccb_tag(struct pm8001_hba_info *);
@@ -100,40 +104,26 @@ static void pm8001_map_queues(struct Scsi_Host *shost)
struct pm8001_hba_info *pm8001_ha = sha->lldd_ha;
struct blk_mq_queue_map *qmap = &shost->tag_set.map[HCTX_TYPE_DEFAULT];
- if (pm8001_ha->number_of_intr > 1)
- blk_mq_pci_map_queues(qmap, pm8001_ha->pdev, 1);
+ if (pm8001_ha->number_of_intr > 1) {
+ blk_mq_map_hw_queues(qmap, &pm8001_ha->pdev->dev, 1);
+ return;
+ }
- return blk_mq_map_queues(qmap);
+ blk_mq_map_queues(qmap);
}
/*
* The main structure which LLDD must register for scsi core.
*/
static const struct scsi_host_template pm8001_sht = {
- .module = THIS_MODULE,
- .name = DRV_NAME,
- .proc_name = DRV_NAME,
- .queuecommand = sas_queuecommand,
- .dma_need_drain = ata_scsi_dma_need_drain,
- .target_alloc = sas_target_alloc,
- .slave_configure = sas_slave_configure,
+ LIBSAS_SHT_BASE
.scan_finished = pm8001_scan_finished,
.scan_start = pm8001_scan_start,
- .change_queue_depth = sas_change_queue_depth,
- .bios_param = sas_bios_param,
.can_queue = 1,
- .this_id = -1,
.sg_tablesize = PM8001_MAX_DMA_SG,
- .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
- .eh_device_reset_handler = sas_eh_device_reset_handler,
- .eh_target_reset_handler = sas_eh_target_reset_handler,
- .slave_alloc = sas_slave_alloc,
- .target_destroy = sas_target_destroy,
- .ioctl = sas_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = sas_ioctl,
-#endif
+ .max_sectors = PM8001_MAX_SECTORS,
.shost_groups = pm8001_host_groups,
+ .sdev_groups = pm8001_sdev_groups,
.track_queue_depth = 1,
.cmd_per_lun = 32,
.map_queues = pm8001_map_queues,
@@ -462,9 +452,6 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha,
}
for (i = 0; i < PM8001_MAX_DEVICES; i++) {
pm8001_ha->devices[i].dev_type = SAS_PHY_UNUSED;
- pm8001_ha->devices[i].id = i;
- pm8001_ha->devices[i].device_id = PM8001_MAX_DEVICES;
- atomic_set(&pm8001_ha->devices[i].running_req, 0);
}
pm8001_ha->flags = PM8001F_INIT_TIME;
return 0;
@@ -749,7 +736,7 @@ static int pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha)
return -EIO;
}
time_remaining = wait_for_completion_timeout(&completion,
- msecs_to_jiffies(60*1000)); // 1 min
+ secs_to_jiffies(60)); // 1 min
if (!time_remaining) {
kfree(payload.func_specific);
pm8001_dbg(pm8001_ha, FAIL, "get_nvmd_req timeout\n");
@@ -1448,7 +1435,7 @@ err_out_disable:
/* update of pci device, vendor id and driver data with
* unique value for each of the controller
*/
-static struct pci_device_id pm8001_pci_table[] = {
+static const struct pci_device_id pm8001_pci_table[] = {
{ PCI_VDEVICE(PMC_Sierra, 0x8001), chip_8001 },
{ PCI_VDEVICE(PMC_Sierra, 0x8006), chip_8006 },
{ PCI_VDEVICE(ADAPTEC2, 0x8006), chip_8006 },
diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c
index a5a31dfa4512..f7067878b34f 100644
--- a/drivers/scsi/pm8001/pm8001_sas.c
+++ b/drivers/scsi/pm8001/pm8001_sas.c
@@ -101,6 +101,63 @@ int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out)
return 0;
}
+static void pm80xx_get_tag_opcodes(struct sas_task *task, int *ata_op,
+ int *ata_tag, bool *task_aborted)
+{
+ unsigned long flags;
+ struct ata_queued_cmd *qc = NULL;
+
+ *ata_op = 0;
+ *ata_tag = -1;
+ *task_aborted = false;
+
+ if (!task)
+ return;
+
+ spin_lock_irqsave(&task->task_state_lock, flags);
+ if (unlikely((task->task_state_flags & SAS_TASK_STATE_ABORTED)))
+ *task_aborted = true;
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+
+ if (task->task_proto == SAS_PROTOCOL_STP) {
+ // sas_ata_qc_issue path uses SAS_PROTOCOL_STP.
+ // This only works for scsi + libsas + libata users.
+ qc = task->uldd_task;
+ if (qc) {
+ *ata_op = qc->tf.command;
+ *ata_tag = qc->tag;
+ }
+ }
+}
+
+void pm80xx_show_pending_commands(struct pm8001_hba_info *pm8001_ha,
+ struct pm8001_device *target_pm8001_dev)
+{
+ int i = 0, ata_op = 0, ata_tag = -1;
+ struct pm8001_ccb_info *ccb = NULL;
+ struct sas_task *task = NULL;
+ struct pm8001_device *pm8001_dev = NULL;
+ bool task_aborted;
+
+ for (i = 0; i < pm8001_ha->ccb_count; i++) {
+ ccb = &pm8001_ha->ccb_info[i];
+ if (ccb->ccb_tag == PM8001_INVALID_TAG)
+ continue;
+ pm8001_dev = ccb->device;
+ if (target_pm8001_dev && pm8001_dev &&
+ target_pm8001_dev != pm8001_dev)
+ continue;
+ task = ccb->task;
+ pm80xx_get_tag_opcodes(task, &ata_op, &ata_tag, &task_aborted);
+ pm8001_dbg(pm8001_ha, FAIL,
+ "tag %#x, device %#x task %p task aborted %d ata opcode %#x ata tag %d\n",
+ ccb->ccb_tag,
+ (pm8001_dev ? pm8001_dev->device_id : 0),
+ task, task_aborted,
+ ata_op, ata_tag);
+ }
+}
+
/**
* pm8001_mem_alloc - allocate memory for pm8001.
* @pdev: pci device.
@@ -166,7 +223,6 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
unsigned long flags;
pm8001_ha = sas_phy->ha->lldd_ha;
phy = &pm8001_ha->phy[phy_id];
- pm8001_ha->phy[phy_id].enable_completion = &completion;
if (PM8001_CHIP_DISP->fatal_errors(pm8001_ha)) {
/*
@@ -190,6 +246,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
rates->maximum_linkrate;
}
if (pm8001_ha->phy[phy_id].phy_state == PHY_LINK_DISABLE) {
+ pm8001_ha->phy[phy_id].enable_completion = &completion;
PM8001_CHIP_DISP->phy_start_req(pm8001_ha, phy_id);
wait_for_completion(&completion);
}
@@ -198,6 +255,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
break;
case PHY_FUNC_HARD_RESET:
if (pm8001_ha->phy[phy_id].phy_state == PHY_LINK_DISABLE) {
+ pm8001_ha->phy[phy_id].enable_completion = &completion;
PM8001_CHIP_DISP->phy_start_req(pm8001_ha, phy_id);
wait_for_completion(&completion);
}
@@ -206,6 +264,7 @@ int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
break;
case PHY_FUNC_LINK_RESET:
if (pm8001_ha->phy[phy_id].phy_state == PHY_LINK_DISABLE) {
+ pm8001_ha->phy[phy_id].enable_completion = &completion;
PM8001_CHIP_DISP->phy_start_req(pm8001_ha, phy_id);
wait_for_completion(&completion);
}
@@ -372,23 +431,6 @@ static int pm8001_task_prep_ssp(struct pm8001_hba_info *pm8001_ha,
return PM8001_CHIP_DISP->ssp_io_req(pm8001_ha, ccb);
}
- /* Find the local port id that's attached to this device */
-static int sas_find_local_port_id(struct domain_device *dev)
-{
- struct domain_device *pdev = dev->parent;
-
- /* Directly attached device */
- if (!pdev)
- return dev->port->id;
- while (pdev) {
- struct domain_device *pdev_p = pdev->parent;
- if (!pdev_p)
- return pdev->port->id;
- pdev = pdev->parent;
- }
- return 0;
-}
-
#define DEV_IS_GONE(pm8001_dev) \
((!pm8001_dev || (pm8001_dev->dev_type == SAS_PHY_UNUSED)))
@@ -461,10 +503,10 @@ int pm8001_queue_command(struct sas_task *task, gfp_t gfp_flags)
spin_lock_irqsave(&pm8001_ha->lock, flags);
pm8001_dev = dev->lldd_dev;
- port = &pm8001_ha->port[sas_find_local_port_id(dev)];
+ port = pm8001_ha->phy[pm8001_dev->attached_phy].port;
if (!internal_abort &&
- (DEV_IS_GONE(pm8001_dev) || !port->port_attached)) {
+ (DEV_IS_GONE(pm8001_dev) || !port || !port->port_attached)) {
ts->resp = SAS_TASK_UNDELIVERED;
ts->stat = SAS_PHY_DOWN;
if (sas_protocol_ata(task_proto)) {
@@ -570,6 +612,13 @@ void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha,
pm8001_ccb_free(pm8001_ha, ccb);
}
+static void pm8001_init_dev(struct pm8001_device *pm8001_dev, int id)
+{
+ pm8001_dev->id = id;
+ pm8001_dev->device_id = PM8001_MAX_DEVICES;
+ atomic_set(&pm8001_dev->running_req, 0);
+}
+
/**
* pm8001_alloc_dev - find a empty pm8001_device
* @pm8001_ha: our hba card information
@@ -578,9 +627,11 @@ static struct pm8001_device *pm8001_alloc_dev(struct pm8001_hba_info *pm8001_ha)
{
u32 dev;
for (dev = 0; dev < PM8001_MAX_DEVICES; dev++) {
- if (pm8001_ha->devices[dev].dev_type == SAS_PHY_UNUSED) {
- pm8001_ha->devices[dev].id = dev;
- return &pm8001_ha->devices[dev];
+ struct pm8001_device *pm8001_dev = &pm8001_ha->devices[dev];
+
+ if (pm8001_dev->dev_type == SAS_PHY_UNUSED) {
+ pm8001_init_dev(pm8001_dev, dev);
+ return pm8001_dev;
}
}
if (dev == PM8001_MAX_DEVICES) {
@@ -611,9 +662,7 @@ struct pm8001_device *pm8001_find_dev(struct pm8001_hba_info *pm8001_ha,
void pm8001_free_dev(struct pm8001_device *pm8001_dev)
{
- u32 id = pm8001_dev->id;
memset(pm8001_dev, 0, sizeof(*pm8001_dev));
- pm8001_dev->id = id;
pm8001_dev->dev_type = SAS_PHY_UNUSED;
pm8001_dev->device_id = PM8001_MAX_DEVICES;
pm8001_dev->sas_device = NULL;
@@ -717,6 +766,7 @@ static void pm8001_dev_gone_notify(struct domain_device *dev)
spin_lock_irqsave(&pm8001_ha->lock, flags);
}
PM8001_CHIP_DISP->dereg_dev_req(pm8001_ha, device_id);
+ pm8001_ha->phy[pm8001_dev->attached_phy].phy_attached = 0;
pm8001_free_dev(pm8001_dev);
} else {
pm8001_dbg(pm8001_ha, DISC, "Found dev has gone.\n");
diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h
index 3ccb7371902f..315f6a7523f0 100644
--- a/drivers/scsi/pm8001/pm8001_sas.h
+++ b/drivers/scsi/pm8001/pm8001_sas.h
@@ -56,7 +56,6 @@
#include <scsi/sas_ata.h>
#include <linux/atomic.h>
#include <linux/blk-mq.h>
-#include <linux/blk-mq-pci.h>
#include "pm8001_defs.h"
#define DRV_NAME "pm80xx"
@@ -96,6 +95,8 @@ extern struct list_head hba_list;
extern const struct pm8001_dispatch pm8001_8001_dispatch;
extern const struct pm8001_dispatch pm8001_80xx_dispatch;
+extern uint pcs_event_log_severity;
+
struct pm8001_hba_info;
struct pm8001_ccb_info;
struct pm8001_device;
@@ -717,6 +718,7 @@ int pm80xx_fatal_errors(struct pm8001_hba_info *pm8001_ha);
void pm8001_free_dev(struct pm8001_device *pm8001_dev);
/* ctl shared API */
extern const struct attribute_group *pm8001_host_groups[];
+extern const struct attribute_group *pm8001_sdev_groups[];
#define PM8001_INVALID_TAG ((u32)-1)
@@ -784,6 +786,8 @@ static inline void pm8001_ccb_task_free_done(struct pm8001_hba_info *pm8001_ha,
}
void pm8001_setds_completion(struct domain_device *dev);
void pm8001_tmf_aborted(struct sas_task *task);
+void pm80xx_show_pending_commands(struct pm8001_hba_info *pm8001_ha,
+ struct pm8001_device *dev);
#endif
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c
index a52ae6841939..5b373c53c036 100644
--- a/drivers/scsi/pm8001/pm80xx_hwi.c
+++ b/drivers/scsi/pm8001/pm80xx_hwi.c
@@ -568,13 +568,13 @@ static void read_main_config_table(struct pm8001_hba_info *pm8001_ha)
pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version =
pm8001_mr32(address, MAIN_MPI_INACTIVE_FW_VERSION);
- pm8001_dbg(pm8001_ha, DEV,
+ pm8001_dbg(pm8001_ha, INIT,
"Main cfg table: sign:%x interface rev:%x fw_rev:%x\n",
pm8001_ha->main_cfg_tbl.pm80xx_tbl.signature,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.interface_rev,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.firmware_rev);
- pm8001_dbg(pm8001_ha, DEV,
+ pm8001_dbg(pm8001_ha, INIT,
"table offset: gst:%x iq:%x oq:%x int vec:%x phy attr:%x\n",
pm8001_ha->main_cfg_tbl.pm80xx_tbl.gst_offset,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.inbound_queue_offset,
@@ -582,7 +582,7 @@ static void read_main_config_table(struct pm8001_hba_info *pm8001_ha)
pm8001_ha->main_cfg_tbl.pm80xx_tbl.int_vec_table_offset,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.phy_attr_table_offset);
- pm8001_dbg(pm8001_ha, DEV,
+ pm8001_dbg(pm8001_ha, INIT,
"Main cfg table; ila rev:%x Inactive fw rev:%x\n",
pm8001_ha->main_cfg_tbl.pm80xx_tbl.ila_version,
pm8001_ha->main_cfg_tbl.pm80xx_tbl.inc_fw_version);
@@ -763,7 +763,8 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha)
pm8001_ha->memoryMap.region[IOP].phys_addr_lo;
pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_size =
PM8001_EVENT_LOG_SIZE;
- pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity = 0x01;
+ pm8001_ha->main_cfg_tbl.pm80xx_tbl.pcs_event_log_severity =
+ pcs_event_log_severity;
pm8001_ha->main_cfg_tbl.pm80xx_tbl.fatal_err_interrupt = 0x01;
/* Enable higher IQs and OQs, 32 to 63, bit 16 */
@@ -2037,7 +2038,7 @@ mpi_ssp_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
atomic_dec(&pm8001_dev->running_req);
break;
}
- pm8001_dbg(pm8001_ha, IO, "scsi_status = 0x%x\n ",
+ pm8001_dbg(pm8001_ha, IO, "scsi_status = 0x%x\n",
psspPayload->ssp_resp_iu.status);
spin_lock_irqsave(&t->task_state_lock, flags);
t->task_state_flags &= ~SAS_TASK_STATE_PENDING;
@@ -2245,7 +2246,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,
u32 param;
u32 status;
u32 tag;
- int i, j;
+ int i, j, ata_tag = -1;
u8 sata_addr_low[4];
u32 temp_sata_addr_low, temp_sata_addr_hi;
u8 sata_addr_hi[4];
@@ -2255,6 +2256,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,
u32 *sata_resp;
struct pm8001_device *pm8001_dev;
unsigned long flags;
+ struct ata_queued_cmd *qc;
psataPayload = (struct sata_completion_resp *)(piomb + 4);
status = le32_to_cpu(psataPayload->status);
@@ -2266,8 +2268,11 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,
pm8001_dev = ccb->device;
if (t) {
- if (t->dev && (t->dev->lldd_dev))
+ if (t->dev && (t->dev->lldd_dev)) {
pm8001_dev = t->dev->lldd_dev;
+ qc = t->uldd_task;
+ ata_tag = qc ? qc->tag : -1;
+ }
} else {
pm8001_dbg(pm8001_ha, FAIL, "task null, freeing CCB tag %d\n",
ccb->ccb_tag);
@@ -2275,16 +2280,14 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha,
return;
}
-
if (pm8001_dev && unlikely(!t->lldd_task || !t->dev))
return;
ts = &t->task_status;
-
if (status != IO_SUCCESS) {
pm8001_dbg(pm8001_ha, FAIL,
- "IO failed device_id %u status 0x%x tag %d\n",
- pm8001_dev->device_id, status, tag);
+ "IO failed status %#x pm80xx tag %#x ata tag %d\n",
+ status, tag, ata_tag);
}
/* Print sas address of IO failed device */
@@ -2666,13 +2669,19 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha,
/* Check if this is NCQ error */
if (event == IO_XFER_ERROR_ABORTED_NCQ_MODE) {
+ /* tag value is invalid with this event */
+ pm8001_dbg(pm8001_ha, FAIL, "NCQ ERROR for device %#x tag %#x\n",
+ dev_id, tag);
+
/* find device using device id */
pm8001_dev = pm8001_find_dev(pm8001_ha, dev_id);
/* send read log extension by aborting the link - libata does what we want */
- if (pm8001_dev)
+ if (pm8001_dev) {
+ pm80xx_show_pending_commands(pm8001_ha, pm8001_dev);
pm8001_handle_event(pm8001_ha,
pm8001_dev,
IO_XFER_ERROR_ABORTED_NCQ_MODE);
+ }
return;
}
@@ -3335,10 +3344,11 @@ static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
u32 phy_id =
le32_to_cpu(pPayload->phyid) & 0xFF;
struct pm8001_phy *phy = &pm8001_ha->phy[phy_id];
+ u32 tag = le32_to_cpu(pPayload->tag);
pm8001_dbg(pm8001_ha, INIT,
- "phy start resp status:0x%x, phyid:0x%x\n",
- status, phy_id);
+ "phy start resp status:0x%x, phyid:0x%x, tag 0x%x\n",
+ status, phy_id, tag);
if (status == 0)
phy->phy_state = PHY_LINK_DOWN;
@@ -3347,6 +3357,8 @@ static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
complete(phy->enable_completion);
phy->enable_completion = NULL;
}
+
+ pm8001_tag_free(pm8001_ha, tag);
return 0;
}
@@ -3627,8 +3639,10 @@ static int mpi_phy_stop_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
u32 phyid =
le32_to_cpu(pPayload->phyid) & 0xFF;
struct pm8001_phy *phy = &pm8001_ha->phy[phyid];
- pm8001_dbg(pm8001_ha, MSG, "phy:0x%x status:0x%x\n",
- phyid, status);
+ u32 tag = le32_to_cpu(pPayload->tag);
+
+ pm8001_dbg(pm8001_ha, MSG, "phy:0x%x status:0x%x tag 0x%x\n", phyid,
+ status, tag);
if (status == PHY_STOP_SUCCESS ||
status == PHY_STOP_ERR_DEVICE_ATTACHED) {
phy->phy_state = PHY_LINK_DISABLE;
@@ -3636,6 +3650,7 @@ static int mpi_phy_stop_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
phy->sas_phy.linkrate = SAS_PHY_DISABLED;
}
+ pm8001_tag_free(pm8001_ha, tag);
return 0;
}
@@ -3654,10 +3669,9 @@ static int mpi_set_controller_config_resp(struct pm8001_hba_info *pm8001_ha,
u32 tag = le32_to_cpu(pPayload->tag);
pm8001_dbg(pm8001_ha, MSG,
- "SET CONTROLLER RESP: status 0x%x qlfr_pgcd 0x%x\n",
- status, err_qlfr_pgcd);
+ "SET CONTROLLER RESP: status 0x%x qlfr_pgcd 0x%x tag 0x%x\n",
+ status, err_qlfr_pgcd, tag);
pm8001_tag_free(pm8001_ha, tag);
-
return 0;
}
@@ -4631,9 +4645,16 @@ static int
pm80xx_chip_phy_start_req(struct pm8001_hba_info *pm8001_ha, u8 phy_id)
{
struct phy_start_req payload;
- u32 tag = 0x01;
+ int ret;
+ u32 tag;
u32 opcode = OPC_INB_PHYSTART;
+ ret = pm8001_tag_alloc(pm8001_ha, &tag);
+ if (ret) {
+ pm8001_dbg(pm8001_ha, FAIL, "Tag allocation failed\n");
+ return ret;
+ }
+
memset(&payload, 0, sizeof(payload));
payload.tag = cpu_to_le32(tag);
@@ -4669,9 +4690,16 @@ static int pm80xx_chip_phy_stop_req(struct pm8001_hba_info *pm8001_ha,
u8 phy_id)
{
struct phy_stop_req payload;
- u32 tag = 0x01;
+ int ret;
+ u32 tag;
u32 opcode = OPC_INB_PHYSTOP;
+ ret = pm8001_tag_alloc(pm8001_ha, &tag);
+ if (ret) {
+ pm8001_dbg(pm8001_ha, FAIL, "Tag allocation failed\n");
+ return ret;
+ }
+
memset(&payload, 0, sizeof(payload));
payload.tag = cpu_to_le32(tag);
payload.phy_id = cpu_to_le32(phy_id);