Skip to contentSkip to conversation

MVSAS: Enhanced hot plug handling

PATCH In review Andy Yan 2 participants 3 messages Nov 9, 2009 – Nov 10, 2009 SCSI

lore
Share & tools
lore

Andy Yan

author
#0 lore raw

PATCH 6/7 MVSAS: Enhanced hot plug handling

Quoted 2 lines

From 894361e5503f4ddc9a073173e2e3942fd7f40905 Mon Sep 17 00:00:00 2001

From: Andy <[email protected]>
Date: Fri, 6 Nov 2009 17:33:49 +0800
Subject: [PATCH 6/7] bug fix with hot plug.
Add code to make the disk IO more stable when hot plug disk, and refined some code with usage of HW resource,enhanced error checking.

---
 drivers/scsi/mvsas/mv_64xx.c |   27 ++++-
 drivers/scsi/mvsas/mv_94xx.c |  146 +++++++++++++++----
 drivers/scsi/mvsas/mv_init.c |   28 +++-
 drivers/scsi/mvsas/mv_sas.c  |  320 ++++++++++++++++++++++++++++-------------
 drivers/scsi/mvsas/mv_sas.h  |   14 ++-
 5 files changed, 389 insertions(+), 146 deletions(-)
drivers/scsi/mvsas/mv_64xx.c +25 -2
index 4c005fa..f0097d9 100644
@@ -132,9 +132,9 @@ static void mvs_64xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard)
 	tmp &= ~PHYEV_RDY_CH;
 	mvs_write_port_irq_stat(mvi, phy_id, tmp);
 	tmp = mvs_read_phy_ctl(mvi, phy_id);
-	if (hard)
+	if (hard == 1)
 		tmp |= PHY_RST_HARD;
-	else
+	else if (hard == 0)
 		tmp |= PHY_RST;
 	mvs_write_phy_ctl(mvi, phy_id, tmp);
 	if (hard) {
@@ -487,6 +487,28 @@ static void mvs_64xx_command_active(struct mvs_info *mvi, u32 slot_idx)
 	} while (tmp & 1 << (slot_idx % 32));
 }
 
+void mvs_64xx_clear_srs_irq(struct mvs_info *mvi, u8 reg_set, u8 clear_all)
+{
+	void __iomem *regs = mvi->regs;
+	u32 tmp;
+
+
+	if (clear_all) {
+		tmp = mr32(MVS_INT_STAT_SRS_0);
+		if (tmp) {
+			mv_printk("check SRS 0 %08X.\n", tmp);
+			mw32(MVS_INT_STAT_SRS_0, tmp);
+		}
+	} else {
+		tmp = mr32(MVS_INT_STAT_SRS_0);
+		if (tmp &  (1 << (reg_set % 32))) {
+			mv_printk("register set 0x%x was stopped.\n", reg_set);
+			mw32(MVS_INT_STAT_SRS_0, 1 << (reg_set % 32));
+		}
+	}
+}
+
+
 static void mvs_64xx_issue_stop(struct mvs_info *mvi, enum mvs_port_type type,
 				u32 tfs)
 {
@@ -769,6 +791,7 @@ const struct mvs_dispatch mvs_64xx_dispatch = {
 	mvs_write_port_irq_mask,
 	mvs_get_sas_addr,
 	mvs_64xx_command_active,
+	mvs_64xx_clear_srs_irq,
 	mvs_64xx_issue_stop,
 	mvs_start_delivery,
 	mvs_rx_update,
drivers/scsi/mvsas/mv_94xx.c +115 -31

218 lines not on this page · raw message

drivers/scsi/mvsas/mv_init.c +21 -7
index fb1bee0..0ecb6b6 100644
@@ -82,7 +82,7 @@ static struct sas_domain_function_template mvs_transport_ops = {
 	.lldd_abort_task	= mvs_abort_task,
 	.lldd_abort_task_set    = mvs_abort_task_set,
 	.lldd_clear_aca         = mvs_clear_aca,
-       .lldd_clear_task_set    = mvs_clear_task_set,
+	.lldd_clear_task_set    = mvs_clear_task_set,
 	.lldd_I_T_nexus_reset	= mvs_I_T_nexus_reset,
 	.lldd_lu_reset 		= mvs_lu_reset,
 	.lldd_query_task	= mvs_query_task,
@@ -190,9 +190,9 @@ static void mvs_tasklet(unsigned long opaque)
 
 	for (i = 0; i < core_nr; i++) {
 		mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
-		stat = MVS_CHIP_DISP->isr_status(mvi, mvi->irq);
+		stat = MVS_CHIP_DISP->isr_status(mvi, mvi->pdev->irq);
 		if (stat)
-			MVS_CHIP_DISP->isr(mvi, mvi->irq, stat);
+			MVS_CHIP_DISP->isr(mvi, mvi->pdev->irq, stat);
 	}
 
 }
@@ -252,7 +252,11 @@ static irqreturn_t mvs_interrupt(int irq, void *opaque)
 
 static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
 {
-	int i, slot_nr;
+	int i = 0, j = 0, slot_nr;
+	unsigned long buf_size;
+	void *buf;
+	dma_addr_t buf_dma;
+	struct mvs_slot_info *slot = 0;
 
 	if (mvi->flags & MVF_FLAG_SOC)
 		slot_nr = MVS_SOC_SLOTS;
@@ -266,11 +270,13 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
 		mvi->port[i].port_attached = 0;
 		INIT_LIST_HEAD(&mvi->port[i].list);
 	}
+
 	for (i = 0; i < MVS_MAX_DEVICES; i++) {
 		mvi->devices[i].taskfileset = MVS_ID_NOT_MAPPED;
 		mvi->devices[i].dev_type = NO_DEVICE;
 		mvi->devices[i].device_id = i;
 		mvi->devices[i].dev_status = MVS_DEV_NORMAL;
+		init_timer(&mvi->devices[i].timer);
 	}
 
 	/*
@@ -279,11 +285,13 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
 	mvi->tx = dma_alloc_coherent(mvi->dev,
 				     sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ,
 				     &mvi->tx_dma, GFP_KERNEL);
+
 	if (!mvi->tx)
 		goto err_out;
 	memset(mvi->tx, 0, sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ);
 	mvi->rx_fis = dma_alloc_coherent(mvi->dev, MVS_RX_FISL_SZ,
 					 &mvi->rx_fis_dma, GFP_KERNEL);
+
 	if (!mvi->rx_fis)
 		goto err_out;
 	memset(mvi->rx_fis, 0, MVS_RX_FISL_SZ);
@@ -291,6 +299,7 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
 	mvi->rx = dma_alloc_coherent(mvi->dev,
 				     sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1),
 				     &mvi->rx_dma, GFP_KERNEL);
+
 	if (!mvi->rx)
 		goto err_out;
 	memset(mvi->rx, 0, sizeof(*mvi->rx) * (MVS_RX_RING_SZ + 1));
@@ -300,6 +309,7 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
 	mvi->slot = dma_alloc_coherent(mvi->dev,
 				       sizeof(*mvi->slot) * slot_nr,
 				       &mvi->slot_dma, GFP_KERNEL);
+
 	if (!mvi->slot)
 		goto err_out;
 	memset(mvi->slot, 0, sizeof(*mvi->slot) * slot_nr);
@@ -421,7 +431,6 @@ static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev,
 	mvi->chip_id = ent->driver_data;
 	mvi->chip = &mvs_chips[mvi->chip_id];
 	INIT_LIST_HEAD(&mvi->wq_list);
-	mvi->irq = pdev->irq;
 
 	((struct mvs_prv_info *)sha->lldd_ha)->mvi[id] = mvi;
 	((struct mvs_prv_info *)sha->lldd_ha)->n_phy = mvi->chip->n_phy;
@@ -496,6 +505,7 @@ static int __devinit mvs_prep_sas_ha_init(struct Scsi_Host *shost,
 
 	sha->sas_phy = arr_phy;
 	sha->sas_port = arr_port;
+	sha->core.shost = shost;
 
 	sha->lldd_ha = kzalloc(sizeof(struct mvs_prv_info), GFP_KERNEL);
 	if (!sha->lldd_ha)
@@ -504,7 +514,7 @@ static int __devinit mvs_prep_sas_ha_init(struct Scsi_Host *shost,
 	((struct mvs_prv_info *)sha->lldd_ha)->n_host = core_nr;
 
 	shost->transportt = mvs_stt;
-	shost->max_id = 128;
+	shost->max_id = MVS_MAX_DEVICES;
 	shost->max_lun = ~0;
 	shost->max_channel = 1;
 	shost->max_cmd_len = 16;
@@ -639,6 +649,10 @@ static int __devinit mvs_pci_init(struct pci_dev *pdev,
 		}
 		nhost++;
 	} while (nhost < chip->n_host);
+#ifdef MVS_USE_TASKLET
+	tasklet_init(&mv_tasklet, mvs_tasklet,
+		(unsigned long)SHOST_TO_SAS_HA(shost));
+#endif
 
 	mvs_post_sas_ha_init(shost, chip);
 
@@ -699,7 +713,7 @@ static void __devexit mvs_pci_remove(struct pci_dev *pdev)
 	scsi_remove_host(mvi->shost);
 
 	MVS_CHIP_DISP->interrupt_disable(mvi);
-	free_irq(mvi->irq, sha);
+	free_irq(mvi->pdev->irq, sha);
 	if (mvi->flags & MVF_MSI) {
 		mvs_disable_msi(mvi);
 		pci_disable_msi(pdev);
drivers/scsi/mvsas/mv_sas.c +218 -102

660 lines not on this page · raw message

drivers/scsi/mvsas/mv_sas.h +10 -4
index b0f43e7..e0ba1f1 100644
@@ -38,17 +38,17 @@
 #include <linux/irq.h>
 #include <linux/vmalloc.h>
 #include <scsi/libsas.h>
+#include <scsi/scsi.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/sas_ata.h>
 #include <linux/version.h>
 #include "mv_defs.h"
 
 #define DRV_NAME		"mvsas"
-#define DRV_VERSION		"0.8.2"
+#define DRV_VERSION		"0.8.9"
 #define _MV_DUMP		0
 #define MVS_ID_NOT_MAPPED	0x7f
 /* #define DISABLE_HOTPLUG_DMA_FIX */
-#define MAX_EXP_RUNNING_REQ	2
 #define WIDE_PORT_MAX_PHY		4
 #define	MV_DISABLE_NCQ	0
 #define mv_printk(fmt, arg ...)	\
@@ -130,6 +130,7 @@ struct mvs_dispatch {
 
 	void (*get_sas_addr)(void *buf, u32 buflen);
 	void (*command_active)(struct mvs_info *mvi, u32 slot_idx);
+	void (*clear_srs_irq)(struct mvs_info *mvi, u8 reg_set, u8 clear_all);
 	void (*issue_stop)(struct mvs_info *mvi, enum mvs_port_type type,
 				u32 tfs);
 	void (*start_delivery)(struct mvs_info *mvi, u32 tx);
@@ -240,9 +241,10 @@ struct mvs_device {
 	enum sas_dev_type dev_type;
 	struct mvs_info *mvi_info;
 	struct domain_device *sas_device;
+	struct timer_list timer;
 	u32 attached_phy;
 	u32 device_id;
-	u32 runing_req;
+	u32 running_req;
 	u8 taskfileset;
 	u8 dev_status;
 	u16 reserved;
@@ -391,6 +393,8 @@ void mvs_scan_start(struct Scsi_Host *shost);
 int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time);
 int mvs_queue_command(struct sas_task *task, const int num,
 			gfp_t gfp_flags);
+void mvs_set_sense(u8 *buffer, int len, int d_sense,
+		int key, int asc, int ascq);
 int mvs_abort_task(struct sas_task *task);
 int mvs_abort_task_set(struct domain_device *dev, u8 *lun);
 int mvs_clear_aca(struct domain_device *dev, u8 *lun);
@@ -403,7 +407,9 @@ int mvs_lu_reset(struct domain_device *dev, u8 *lun);
 int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags);
 int mvs_I_T_nexus_reset(struct domain_device *dev);
 int mvs_query_task(struct sas_task *task);
-void mvs_release_task(struct mvs_info *mvi, int phy_no,
+void mvs_do_release_task(struct mvs_info *mvi,
+		int phy_no, struct domain_device *dev);
+void mvs_release_task(struct mvs_info *mvi,
 			struct domain_device *dev);
 void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events);
 void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st);
Signature · 1 line
1.6.2.2
#1 lore raw

@@ -914,13 +911,22 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
tei.port = &mvi->port[dev->port->id -
mvi->chip->n_phy];
else
tei.port = &mvi->port[dev->port->id];
-
- if (!tei.port->port_attached) {
+ if (tei.port && !tei.port->port_attached) {
if (sas_protocol_ata(t->task_proto)) {
- mv_dprintk("port %d does not"
- "attached device.\n",
dev->port->id);
- rc = SAS_PHY_DOWN;
- goto out_done;
+ struct task_status_struct *ts =
&t->task_status;
+ ts->stat = SAS_PROTO_RESPONSE;
+ ts->stat = SAS_PHY_DOWN;

[Jack] Here ts->stat was double set. Maybe the first one is unnessary.

#2 lore raw
In reply to Andy Yan

+
spin_unlock_irqrestore(dev->sata_dev.ap->lock,
+ flags_libsas);
+ spin_unlock_irqrestore(&mvi->lock, flags);
+ t->task_done(t);
+ spin_lock_irqsave(&mvi->lock, flags);
+ spin_lock_irqsave(dev->sata_dev.ap->lock,
+ flags_libsas);

[Jack] Is there something wrong with the the lock sequence . for sata io path, will __acquires(dev->sata_dev.ap->lock) when issue cmd to lldd
and you acquires your mvi lock then, so should you change the lock sequence to :

spin_unlock_irqrestore(&mvi->lock, flags);
spin_unlock_irqrestore(dev->sata_dev.ap->lock,

						flags_libsas);
t->task_done(t);
spin_lock_irqsave(dev->sata_dev.ap->lock,
					flags_libsas);

spin_lock_irqsave(&mvi->lock, flags);