Skip to contentSkip to conversation

stex: Add reset code for st_yel

PATCH In review Ed Lin 2 participants 3 messages Aug 15, 2009 – Aug 17, 2009 SCSI

lore
Share & tools
lore

Ed Lin

author
#0 lore raw

PATCH 1/1 stex: Add reset code for st_yel

Add reset related code for st_yel.
1. Set the SS_H2I_INT_RESET bit.
2. Wait for the SS_MU_OPERATIONAL flag. This is also part of normal handshake process so move it to handshake routine.
3. Continue handshake with the firmware.

---

drivers/scsi/stex.c +30 -4
index 8d2a95c..b57f92f 100644
@@ -55,6 +55,7 @@ enum {
 	OIS	= 0x30,	/* MU_OUTBOUND_INTERRUPT_STATUS */
 	OIM	= 0x3c,	/* MU_OUTBOUND_INTERRUPT_MASK */
 
+	YIOA_STATUS				= 0x00,
 	YH2I_INT				= 0x20,
 	YINT_EN					= 0x34,
 	YI2H_INT				= 0x9c,
@@ -108,6 +109,10 @@ enum {
 
 	SS_HEAD_HANDSHAKE			= 0x80,
 
+	SS_H2I_INT_RESET			= 0x100,
+
+	SS_MU_OPERATIONAL			= 0x80000000,
+
 	STEX_CDB_LENGTH				= 16,
 	STATUS_VAR_LEN				= 128,
 
@@ -884,7 +889,7 @@ static void stex_ss_mu_intr(struct st_hba *hba)
 		tag = (u16)value;
 		if (unlikely(tag >= hba->host->can_queue)) {
 			printk(KERN_WARNING DRV_NAME
-					"(%s): invalid tag\n", pci_name(hba->pdev));
+				"(%s): invalid tag\n", pci_name(hba->pdev));
 			continue;
 		}
 
@@ -1040,16 +1045,28 @@ static int stex_ss_handshake(struct st_hba *hba)
 	void __iomem *base = hba->mmio_base;
 	struct st_msg_header *msg_h;
 	struct handshake_frame *h;
-	__le32 *scratch = hba->scratch;
+	__le32 *scratch;
 	u32 data;
 	unsigned long before;
 	int ret = 0;
 
-	h = (struct handshake_frame *)(hba->alloc_rq(hba));
-	msg_h = (struct st_msg_header *)h - 1;
+	before = jiffies;
+	while ((readl(base + YIOA_STATUS) & SS_MU_OPERATIONAL) == 0) {
+		if (time_after(jiffies, before + MU_MAX_DELAY * HZ)) {
+			printk(KERN_ERR DRV_NAME
+				"(%s): firmware not operational\n",
+				pci_name(hba->pdev));
+			return -1;
+		}
+		rmb();
+		msleep(1);
+	}
+
+	msg_h = (struct st_msg_header *)hba->dma_mem;
 	msg_h->handle = cpu_to_le64(hba->dma_handle);
 	msg_h->flag = SS_HEAD_HANDSHAKE;
 
+	h = (struct handshake_frame *)(msg_h + 1);
 	h->rb_phy = cpu_to_le64(hba->dma_handle);
 	h->req_sz = cpu_to_le16(hba->rq_size);
 	h->req_cnt = cpu_to_le16(hba->rq_count+1);
@@ -1205,6 +1222,13 @@ static void stex_hard_reset(struct st_hba *hba)
 			hba->pdev->saved_config_space[i]);
 }
 
+static void stex_ss_reset(struct st_hba *hba)
+{
+	writel(SS_H2I_INT_RESET, hba->mmio_base + YH2I_INT);
+	readl(hba->mmio_base + YH2I_INT);
+	ssleep(5);
+}
+
 static int stex_reset(struct scsi_cmnd *cmd)
 {
 	struct st_hba *hba;
@@ -1221,6 +1245,8 @@ static int stex_reset(struct scsi_cmnd *cmd)
 
 	if (hba->cardtype == st_shasta)
 		stex_hard_reset(hba);
+	else if (hba->cardtype == st_yel)
+		stex_ss_reset(hba);
 
 	if (hba->cardtype != st_yosemite) {
 		if (stex_handshake(hba)) {
#1 lore raw
Quoted 54 lines · Ed Lin

Add reset related code for st_yel.
1. Set the SS_H2I_INT_RESET bit.
2. Wait for the SS_MU_OPERATIONAL flag. This is also part of normal handshake process so move it to handshake routine.
3. Continue handshake with the firmware.

---

drivers/scsi/stex.c +8 -4
index 8d2a95c..b57f92f 100644
@@ -55,6 +55,7 @@ enum {
 	OIS	= 0x30,	/* MU_OUTBOUND_INTERRUPT_STATUS */
 	OIM	= 0x3c,	/* MU_OUTBOUND_INTERRUPT_MASK */
 
+	YIOA_STATUS				= 0x00,
 	YH2I_INT				= 0x20,
 	YINT_EN					= 0x34,
 	YI2H_INT				= 0x9c,
@@ -108,6 +109,10 @@ enum {
 
 	SS_HEAD_HANDSHAKE			= 0x80,
 
+	SS_H2I_INT_RESET			= 0x100,
+
+	SS_MU_OPERATIONAL			= 0x80000000,
+
 	STEX_CDB_LENGTH				= 16,
 	STATUS_VAR_LEN				= 128,
 
@@ -884,7 +889,7 @@ static void stex_ss_mu_intr(struct st_hba *hba)
 		tag = (u16)value;
 		if (unlikely(tag >= hba->host->can_queue)) {
 			printk(KERN_WARNING DRV_NAME
-					"(%s): invalid tag\n", pci_name(hba->pdev));
+				"(%s): invalid tag\n", pci_name(hba->pdev));
 			continue;
 		}
 
@@ -1040,16 +1045,28 @@ static int stex_ss_handshake(struct st_hba *hba)
 	void __iomem *base = hba->mmio_base;
 	struct st_msg_header *msg_h;
 	struct handshake_frame *h;
-	__le32 *scratch = hba->scratch;
+	__le32 *scratch;
 	u32 data;
 	unsigned long before;
 	int ret = 0;
 
-	h = (struct handshake_frame *)(hba->alloc_rq(hba));
-	msg_h = (struct st_msg_header *)h - 1;
+	before = jiffies;

drivers/scsi/stex.c static int stex_ss_handshake(struct st_hba *hba) · line 1063

Quoted 10 lines
drivers/scsi/stex.c +10 -0
+	while ((readl(base + YIOA_STATUS) & SS_MU_OPERATIONAL) == 0) {
+		if (time_after(jiffies, before + MU_MAX_DELAY * HZ)) {
+			printk(KERN_ERR DRV_NAME
+				"(%s): firmware not operational\n",
+				pci_name(hba->pdev));
+			return -1;
+		}
+		rmb();
+		msleep(1);
+	}

hmmmmm. Is that rmb() really necessary? It does not appear to be so.

At worst, the rmb should occur immediately after the loop, no?

ACK everything else.

Jeff

#2 lore raw
Quoted 81 lines

-----Original Message-----
From: Jeff Garzik [mailto:[email protected]]
Sent: 2009年8月15日 4:10
To: Ed Lin - PTU
Cc: James.Bottomley; linux-scsi; Promise_Linux
Subject: Re: [PATCH] stex: Add reset code for st_yel

Quoted 33 lines · Ed Lin

Add reset related code for st_yel.
1. Set the SS_H2I_INT_RESET bit.
2. Wait for the SS_MU_OPERATIONAL flag. This is also part of normal handshake process so move it to handshake routine.
3. Continue handshake with the firmware.

---

drivers/scsi/stex.c +5 -0
index 8d2a95c..b57f92f 100644
@@ -55,6 +55,7 @@ enum {
 	OIS	= 0x30,	/* MU_OUTBOUND_INTERRUPT_STATUS */
 	OIM	= 0x3c,	/* MU_OUTBOUND_INTERRUPT_MASK */
 
+	YIOA_STATUS				= 0x00,
 	YH2I_INT				= 0x20,
 	YINT_EN					= 0x34,
 	YI2H_INT				= 0x9c,
@@ -108,6 +109,10 @@ enum {
 
 	SS_HEAD_HANDSHAKE			= 0x80,
 
+	SS_H2I_INT_RESET			= 0x100,
+
+	SS_MU_OPERATIONAL			= 0x80000000,
+
 	STEX_CDB_LENGTH				= 16,
 	STATUS_VAR_LEN				= 128,
 

drivers/scsi/stex.c static void stex_ss_mu_intr(struct st_hba *hba) · line 887

Quoted 4 lines
drivers/scsi/stex.c +0 -1
@@ -884,7 +889,7 @@ static void stex_ss_mu_intr(struct st_hba *hba)
 		tag = (u16)value;
 		if (unlikely(tag >= hba->host->can_queue)) {
 			printk(KERN_WARNING DRV_NAME
-					"(%s): invalid tag¥n", 

pci_name(hba->pdev));

drivers/scsi/stex.c static void stex_ss_mu_intr(struct st_hba *hba) · line 892

Quoted 1 line
drivers/scsi/stex.c +1 -0
+				"(%s): invalid tag¥n", 

pci_name(hba->pdev));

drivers/scsi/stex.c static int stex_ss_handshake(struct

Quoted 4 lines
drivers/scsi/stex.c +0 -0
 			continue;
 		}
 
@@ -1040,16 +1045,28 @@ static int stex_ss_handshake(struct 

st_hba *hba)

Quoted 12 lines
drivers/scsi/stex.c +2 -3
 	void __iomem *base = hba->mmio_base;
 	struct st_msg_header *msg_h;
 	struct handshake_frame *h;
-	__le32 *scratch = hba->scratch;
+	__le32 *scratch;
 	u32 data;
 	unsigned long before;
 	int ret = 0;
 
-	h = (struct handshake_frame *)(hba->alloc_rq(hba));
-	msg_h = (struct st_msg_header *)h - 1;
+	before = jiffies;

drivers/scsi/stex.c static int stex_ss_handshake(struct st_hba *hba) · line 1063

Quoted 10 lines
drivers/scsi/stex.c +10 -0
+	while ((readl(base + YIOA_STATUS) & SS_MU_OPERATIONAL) == 0) {
+		if (time_after(jiffies, before + MU_MAX_DELAY * HZ)) {
+			printk(KERN_ERR DRV_NAME
+				"(%s): firmware not operational¥n",
+				pci_name(hba->pdev));
+			return -1;
+		}
+		rmb();
+		msleep(1);
+	}

hmmmmm. Is that rmb() really necessary? It does not appear to be so.

Quoted 8 lines

At worst, the rmb should occur immediately after the loop, no?

ACK everything else.

Jeff

Do you mean rmb() is not needed for readl()? I checked the x86 version of readl() and it seems to be so. If so I will come up with a new patch removing this thing.

Thanks,
Ed Lin