[PATCH 6/6] PCIERR : interfaces for synchronous I/O error detection on driver (sample: Fusion MPT)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a sample of how to use.

This patch includes following changes:
1:
  Change CHIPREG_READ32 & CHIPREG_WRITE32 to take three args,
  pointer to adapter, and two memory addresses. And change
  them to return the result of memory access.
2:
  Set proper args to every CHIPREG_{READ,WRITE}32 call, and
  also put error code that returns if the access failed.
3:
  Declare a task that resets adapter. Schedule it if an error
  is detected and reset is required. Using CHIPREG_*HR call is
  convenient to require such reset on an error.

Signed-off-by: Hidetoshi Seto <[email protected]>

-----
 drivers/message/fusion/mptbase.c |  477 +++++++++++++++++++++++++++++----------
 1 files changed, 359 insertions(+), 118 deletions(-)

Index: linux-2.6.16_WORK/drivers/message/fusion/mptbase.c
===================================================================
--- linux-2.6.16_WORK.orig/drivers/message/fusion/mptbase.c
+++ linux-2.6.16_WORK/drivers/message/fusion/mptbase.c
@@ -181,16 +181,124 @@
 static void	mpt_spi_log_info(MPT_ADAPTER *ioc, u32 log_info);
 static void	mpt_sas_log_info(MPT_ADAPTER *ioc, u32 log_info);

+#ifdef CONFIG_PCIERR_CHECK
+static void	mptbase_schedule_reset(void *ioc);
+static struct work_struct	mptbase_rstTask;
+#endif
+
 /* module entry point */
 static int  __init    fusion_init  (void);
 static void __exit    fusion_exit  (void);

-#define CHIPREG_READ32(addr) 		readl_relaxed(addr)
-#define CHIPREG_READ32_dmasync(addr)	readl(addr)
-#define CHIPREG_WRITE32(addr,val) 	writel(val, addr)
+#define CHIPREG_READ32HR(ioc,addr,val)	pciras_readl(ioc,val,addr,1)
+#define CHIPREG_WRITE32HR(ioc,addr,val)	pciras_writel(ioc,val,addr,1)
+#define CHIPREG_READ32(ioc,addr,val)	pciras_readl(ioc,val,addr,0)
+#define CHIPREG_WRITE32(ioc,addr,val)	pciras_writel(ioc,val,addr,0)
 #define CHIPREG_PIO_WRITE32(addr,val)	outl(val, (unsigned long)addr)
 #define CHIPREG_PIO_READ32(addr) 	inl((unsigned long)addr)

+#ifdef CONFIG_PCIERR_CHECK
+#define PCI_ERR_RETRIES			2
+int
+pciras_readl(MPT_ADAPTER *ioc, u32 *regval, u32 *addr, int hres)
+{
+	u32 val;
+	u16 status;
+	iocookie cookie;
+	int retries = PCI_ERR_RETRIES;
+
+	do {
+		pcierr_clear(&cookie, ioc->pcidev);
+		val = ioread32(addr);
+		status = pcierr_read(&cookie);
+		if ((status) && (retries == PCI_ERR_RETRIES))
+			printk(MYIOC_s_WARN_FMT  "pciras_readl(), "
+			"detects pci parity error, do retry.\n", ioc->name);
+	} while(status && (--retries > 0));
+
+	if (status) {
+		printk(MYIOC_s_WARN_FMT  "pciras_readl(), detects pci parity "
+			"error, retries exhausted.\n", ioc->name);
+		if (hres)
+			schedule_work(&mptbase_rstTask);
+		return 1; /* Error */
+	}
+
+	if (regval)
+		*regval = val;
+	return 0; /* Success */
+}
+
+int
+pciras_writel(MPT_ADAPTER *ioc, u32 regval, u32 *addr, int hres)
+{
+	u16 status;
+	u16 perror;
+	int retries = PCI_ERR_RETRIES;
+
+	do {
+		perror = 0;
+		writel(regval, addr);
+		pci_read_config_word(ioc->pcidev, PCI_STATUS, &status);
+		if (status == 0xffff) {
+			if (retries == PCI_ERR_RETRIES)
+				printk(MYIOC_s_WARN_FMT  "pciras_writel(), "
+				"couldn't read pci register.\n", ioc->name);
+		} else if (status & PCI_STATUS_DETECTED_PARITY) {
+			if (retries == PCI_ERR_RETRIES)
+				printk(MYIOC_s_WARN_FMT  "pciras_writel(), "
+					"detects pci parity error, do retry.\n",
+					ioc->name);
+			perror = 1;
+		}
+		pci_write_config_word(ioc->pcidev, PCI_STATUS, status);
+	} while (perror && (--retries > 0));
+
+	if (perror) {
+		printk(MYIOC_s_WARN_FMT  "pciras_writel(), detects pci "
+			"parity error, retries exhausted.\n", ioc->name);
+
+		if (hres)
+			schedule_work(&mptbase_rstTask);
+		return 1; /* Error */
+	}
+
+	return 0; /* Success */
+}
+
+static void
+mptbase_schedule_reset(void *arg)
+{
+        MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
+
+	mpt_HardResetHandler(ioc, CAN_SLEEP);
+
+	return;
+}
+
+#else /* CONFIG_PCIERR_CHECK */
+
+static inline int
+pciras_readl(MPT_ADAPTER *ioc, u32 *regval, u32 *addr, int hres)
+{
+	u32 val;
+
+	val = ioread32(addr);
+	if (regval)
+		*regval = val;
+	return 0; /* Success */
+}
+
+static inline int
+pciras_writel(MPT_ADAPTER *ioc, u32 regval, u32 *addr, int hres)
+{
+	writel(regval, addr);
+
+	return 0; /* Success */
+}
+
+#endif
+
 static void
 pci_disable_io_access(struct pci_dev *pdev)
 {
@@ -342,7 +450,7 @@

  out:
 	/*  Flush (non-TURBO) reply with a WRITE!  */
-	CHIPREG_WRITE32(&ioc->chip->ReplyFifo, pa);
+	CHIPREG_WRITE32HR(ioc, &ioc->chip->ReplyFifo, pa);

 	if (freeme)
 		mpt_free_msg_frame(ioc, mf);
@@ -373,12 +481,27 @@
 	MPT_ADAPTER *ioc = bus_id;
 	u32 pa;

+#ifdef CONFIG_PCIERR_CHECK
+	{
+		u16 status;
+
+		/* read status register to check whether DMA transfer was failed. */
+		pci_read_config_word(ioc->pcidev, PCI_STATUS, &status);
+		if (status & (PCI_STATUS_DETECTED_PARITY | PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT)) {
+			printk(MYIOC_s_WARN_FMT "mpt_interrupt(), detects pci parity error.\n", ioc->name);
+			pci_write_config_word(ioc->pcidev, PCI_STATUS, status);
+			schedule_work(&mptbase_rstTask);
+			return IRQ_HANDLED;
+		}
+	}
+#endif
 	/*
 	 *  Drain the reply FIFO!
 	 */
 	while (1) {
-		pa = CHIPREG_READ32_dmasync(&ioc->chip->ReplyFifo);
-		if (pa == 0xFFFFFFFF)
+		u16 status;
+		status = CHIPREG_READ32HR(ioc, &ioc->chip->ReplyFifo, &pa);
+		if (status || (pa == 0xFFFFFFFF))
 			return IRQ_HANDLED;
 		else if (pa & MPI_ADDRESS_REPLY_A_BIT)
 			mpt_reply(ioc, pa);
@@ -833,7 +956,7 @@

 	mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx];
dsgprintk((MYIOC_s_INFO_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx]));
-	CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr);
+	CHIPREG_WRITE32HR(ioc, &ioc->chip->RequestFifo, mf_dma_addr);
 }

 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -933,11 +1056,11 @@
 	}

 	/* Make sure there are no doorbells */
-	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
-
-	CHIPREG_WRITE32(&ioc->chip->Doorbell,
-			((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
-			 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->IntStatus, 0)
+		|| CHIPREG_WRITE32(ioc, &ioc->chip->Doorbell,
+		       ((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
+			((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT))))
+		return -6;

 	/* Wait for IOC doorbell int */
 	if ((ii = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0) {
@@ -945,13 +1068,18 @@
 	}

 	/* Read doorbell and check for active bit */
-	if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
-		return -5;
-
+	{
+		u32 pa;
+		u16 status;
+		status = CHIPREG_READ32(ioc, &ioc->chip->Doorbell, &pa);
+		if (status || !(pa & MPI_DOORBELL_ACTIVE))
+			 return -5;
+	}
 	dhsprintk((KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n",
 		ioc->name, ii));

-	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->IntStatus, 0))
+		return -8;

 	if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
 		return -2;
@@ -966,7 +1094,8 @@
 			(req_as_bytes[(ii*4) + 1] <<  8) |
 			(req_as_bytes[(ii*4) + 2] << 16) |
 			(req_as_bytes[(ii*4) + 3] << 24));
-		CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
+		if (CHIPREG_WRITE32(ioc, &ioc->chip->Doorbell, word))
+			return -9;
 		if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
 			r = -3;
 			break;
@@ -979,7 +1108,8 @@
 		r = -4;

 	/* Make sure there are no doorbells */
-	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->IntStatus, 0))
+		return -10;

 	return r;
 }
@@ -1006,16 +1136,20 @@
 	int	 r = 0;

 	/* return if in use */
-	if (CHIPREG_READ32(&ioc->chip->Doorbell)
-	    & MPI_DOORBELL_ACTIVE)
-	    return -1;
-
-	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	{
+		u32 pa;
+		u16 status;
+		status = CHIPREG_READ32(ioc, &ioc->chip->Doorbell, &pa);
+		if (status || (pa & MPI_DOORBELL_ACTIVE))
+			return -1;
+	}

-	CHIPREG_WRITE32(&ioc->chip->Doorbell,
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->IntStatus, 0) ||
+		CHIPREG_WRITE32(ioc, &ioc->chip->Doorbell,
 		((MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL
 		 <<MPI_DOORBELL_FUNCTION_SHIFT) |
-		 (access_control_value<<12)));
+		 (access_control_value<<12))))
+			return -3;

 	/* Wait for IOC to clear Doorbell Status bit */
 	if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0) {
@@ -1209,6 +1343,9 @@
 	int		 r = -ENODEV;
 	u8		 revision;
 	u8		 pcixcmd;
+#ifdef CONFIG_PCIERR_CHECK
+	u16		 pcicmd;
+#endif
 	static int	 mpt_ids = 0;
 #ifdef CONFIG_PROC_FS
 	struct proc_dir_entry *dent, *ent;
@@ -1329,6 +1466,10 @@
 		ioc->pio_chip = (SYSIF_REGS __iomem *)pmem;
 	}

+#ifdef CONFIG_PCIERR_CHECK
+	INIT_WORK(&mptbase_rstTask, mptbase_schedule_reset, (void *)ioc);
+#endif
+
 	if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC909) {
 		ioc->prod_name = "LSIFC909";
 		ioc->bus_type = FC;
@@ -1397,6 +1538,17 @@
 			pcixcmd &= 0x8F;
 			pci_write_config_byte(pdev, 0x6a, pcixcmd);
 		}
+#ifdef CONFIG_PCIERR_CHECK
+		/* set PER(0040) and SERR_EN(0100) for PCI command register */
+                /* set DPER(0001) for PCI-X command register */
+		pci_read_config_word(pdev, PCI_COMMAND, &pcicmd);
+		pcicmd |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
+		pci_write_config_word(pdev, PCI_COMMAND, pcicmd);
+
+		pci_read_config_byte(pdev, 0x6a, &pcixcmd);
+		pcixcmd |= 0x0001; /* set DPER */
+		pci_write_config_byte(pdev, 0x6a, pcixcmd);
+#endif
 	}
 	else if (pdev->device == MPI_MANUFACTPAGE_DEVID_1030_53C1035) {
 		ioc->prod_name = "LSI53C1035";
@@ -1438,9 +1590,11 @@
 	spin_lock_init(&ioc->FreeQlock);

 	/* Disable all! */
-	CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->IntMask, 0xFFFFFFFF))
+		return -EIO;
 	ioc->active = 0;
-	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->IntStatus, 0))
+		return -EIO;

 	/* Set lookup ptr. */
 	list_add_tail(&ioc->list, &ioc_list);
@@ -1559,19 +1713,23 @@
 	}

 	/* Disable interrupts! */
-	CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->IntMask, 0xFFFFFFFF))
+		return;

 	ioc->active = 0;
 	synchronize_irq(pdev->irq);

 	/* Clear any lingering interrupt */
-	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->IntStatus, 0))
+		return;

-	CHIPREG_READ32(&ioc->chip->IntStatus);
+	if (CHIPREG_READ32(ioc, &ioc->chip->IntStatus, NULL))
+		return;

 	mpt_adapter_dispose(ioc);

 	pci_set_drvdata(pdev, NULL);
+
 }

 /**************************************************************************
@@ -1605,11 +1763,13 @@
 	}

 	/* disable interrupts */
-	CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->IntMask, 0xFFFFFFFF))
+		return -EIO;
 	ioc->active = 0;

 	/* Clear any lingering interrupt */
-	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->IntStatus, 0))
+		return -EIO;

 	pci_disable_device(pdev);
 	pci_set_power_state(pdev, device_state);
@@ -1630,6 +1790,7 @@
 	u32 device_state = pdev->current_state;
 	int recovery_state;
 	int ii;
+	u32 pa;

 	printk(MYIOC_s_INFO_FMT
 	"pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
@@ -1640,11 +1801,16 @@
 	pci_enable_device(pdev);

 	/* enable interrupts */
-	CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
+	CHIPREG_WRITE32(ioc, &ioc->chip->IntMask, MPI_HIM_DIM);
 	ioc->active = 1;

 	/* F/W not running */
-	if(!CHIPREG_READ32(&ioc->chip->Doorbell)) {
+	{
+		u16 status;
+		pa = 0;
+		status = CHIPREG_READ32(ioc, &ioc->chip->Doorbell, &pa);
+	}
+	if (!pa) {
 		/* enable domain validation flags */
 		for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) {
 			ioc->spi_data.dvStatus[ii] |= MPT_SCSICFG_NEED_DV;
@@ -1655,7 +1821,7 @@
 		"pci-resume: ioc-state=0x%x,doorbell=0x%x\n",
 		ioc->name,
 		(mpt_GetIocState(ioc, 1) >> MPI_IOC_STATE_SHIFT),
-		CHIPREG_READ32(&ioc->chip->Doorbell));
+		pa);

 	/* bring ioc to operational state */
 	if ((recovery_state = mpt_do_ioc_recovery(ioc,
@@ -1708,7 +1874,8 @@
 			ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery");

 	/* Disable reply interrupts (also blocks FreeQ) */
-	CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->IntMask, 0xFFFFFFFF))
+		return -5;
 	ioc->active = 0;

 	if (ioc->alt_ioc) {
@@ -1716,7 +1883,9 @@
 			reset_alt_ioc_active = 1;

 		/* Disable alt-IOC's reply interrupts (and FreeQ) for a bit ... */
-		CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF);
+		if (CHIPREG_WRITE32(ioc->alt_ioc, &ioc->alt_ioc->chip->IntMask, 0xFFFFFFFF))
+			ret = -6;
+
 		ioc->alt_ioc->active = 0;
 	}

@@ -1733,7 +1902,9 @@
 				/* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
 				dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
 						ioc->alt_ioc->name));
-				CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
+				if (CHIPREG_WRITE32(ioc->alt_ioc, &ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM))
+					ret = -7;
+
 				ioc->alt_ioc->active = 1;
 			}

@@ -1849,7 +2020,8 @@

 	if (ret == 0) {
 		/* Enable! (reply interrupt) */
-		CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
+		if (CHIPREG_WRITE32(ioc, &ioc->chip->IntMask, MPI_HIM_DIM))
+			ret = -8;
 		ioc->active = 1;
 	}

@@ -1857,7 +2029,8 @@
 		/* (re)Enable alt-IOC! (reply interrupt) */
 		dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
 				ioc->alt_ioc->name));
-		CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
+		if (CHIPREG_WRITE32(ioc->alt_ioc, &ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM))
+			ret = -9;
 		ioc->alt_ioc->active = 1;
 	}

@@ -2042,10 +2215,12 @@
 	}

 	/* Disable adapter interrupts! */
-	CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->IntMask, 0xFFFFFFFF))
+		return;
 	ioc->active = 0;
 	/* Clear any lingering interrupt */
-	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->IntStatus, 0))
+		return;

 	if (ioc->alloc != NULL) {
 		sz = ioc->alloc_sz;
@@ -2371,7 +2546,8 @@
 	u32 s, sc;

 	/*  Get!  */
-	s = CHIPREG_READ32(&ioc->chip->Doorbell);
+	CHIPREG_READ32(ioc, &ioc->chip->Doorbell, &s);
+
 //	dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s));
 	sc = s & MPI_IOC_STATE_MASK;

@@ -2968,15 +3144,14 @@

 	ddlprintk((MYIOC_s_INFO_FMT "downloadboot: fw size 0x%x (%d), FW Ptr %p\n",
 				ioc->name, pFwHeader->ImageSize, pFwHeader->ImageSize, pFwHeader));
-
-	CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
-	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
-	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
-	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
-	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
-	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
-
-	CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM));
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, 0xFF)
+		|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE)
+		|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE)
+		|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE)
+		|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE)
+		|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE)
+		|| CHIPREG_WRITE32(ioc, &ioc->chip->Diagnostic, (MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM)))
+		return EFAULT;

 	/* wait 1 msec */
 	if (sleepFlag == CAN_SLEEP) {
@@ -2985,11 +3160,15 @@
 		mdelay (1);
 	}

-	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
+	if (CHIPREG_READ32(ioc, &ioc->chip->Diagnostic, &diag0val))
+		return -EFAULT;
+
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER))
+		return -EFAULT;

 	for (count = 0; count < 30; count ++) {
-		diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+		if (CHIPREG_READ32(ioc, &ioc->chip->Diagnostic, &diag0val))
+			return -EFAULT;
 		if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
 			ddlprintk((MYIOC_s_INFO_FMT "RESET_ADAPTER cleared, count=%d\n",
 				ioc->name, count));
@@ -3010,15 +3189,17 @@
 		return -3;
 	}

-	CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
-	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
-	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
-	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
-	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
-	CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
+	if(CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, 0xFF)
+		|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE)
+		|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE)
+		|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE)
+		|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE)
+		|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE))
+		return -EFAULT;

 	/* Set the DiagRwEn and Disable ARM bits */
-	CHIPREG_WRITE32(&ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM));
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->Diagnostic, (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM)))
+		return -EFAULT;

 	fwSize = (pFwHeader->ImageSize + 3)/4;
 	ptrFw = (u32 *) pFwHeader;
@@ -3081,10 +3262,10 @@
 		CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);

 	} else /* if((ioc->bus_type == SAS) || (ioc->bus_type == FC)) */ {
-		diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
-		CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val |
-		    MPI_DIAG_CLEAR_FLASH_BAD_SIG);
-
+		if (CHIPREG_READ32(ioc, &ioc->chip->Diagnostic, &diag0val)
+			|| CHIPREG_WRITE32(ioc, &ioc->chip->Diagnostic,
+				 diag0val | MPI_DIAG_CLEAR_FLASH_BAD_SIG))
+			return -EFAULT;
 		/* wait 1 msec */
 		if (sleepFlag == CAN_SLEEP) {
 			msleep_interruptible (1);
@@ -3096,17 +3277,20 @@
 	if (ioc->errata_flag_1064)
 		pci_disable_io_access(ioc->pcidev);

-	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+	if (CHIPREG_READ32(ioc, &ioc->chip->Diagnostic, &diag0val))
+		return -EFAULT;
 	ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, "
 		"turning off PREVENT_IOC_BOOT, DISABLE_ARM, RW_ENABLE\n",
 		ioc->name, diag0val));
 	diag0val &= ~(MPI_DIAG_PREVENT_IOC_BOOT | MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE);
 	ddlprintk((MYIOC_s_INFO_FMT "downloadboot now diag0val=%x\n",
 		ioc->name, diag0val));
-	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->Diagnostic, diag0val))
+		return -EFAULT;

 	/* Write 0xFF to reset the sequencer */
-	CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, 0xFF))
+		return -EFAULT;

 	if (ioc->bus_type == SAS) {
 		ioc_state = mpt_GetIocState(ioc, 0);
@@ -3250,14 +3434,17 @@
 #endif

 	/* Clear any existing interrupts */
-	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->IntStatus, 0))
+		return -1;

 	/* Use "Diagnostic reset" method! (only thing available!) */
-	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+	if (CHIPREG_READ32(ioc, &ioc->chip->Diagnostic, &diag0val))
+		return -1;

 #ifdef MPT_DEBUG
 	if (ioc->alt_ioc)
-		diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
+		if (CHIPREG_READ32(ioc->alt_ioc, &ioc->alt_ioc->chip->Diagnostic, &diag1val))
+			return -1;
 	dprintk((MYIOC_s_INFO_FMT "DbG1: diag0=%08x, diag1=%08x\n",
 			ioc->name, diag0val, diag1val));
 #endif
@@ -3270,12 +3457,13 @@
 			/* Write magic sequence to WriteSequence register
 			 * Loop until in diagnostic mode
 			 */
-			CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
-			CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
-			CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
-			CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
-			CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
-			CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
+			if (CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, 0xFF)
+				|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE)
+				|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE)
+				|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE)
+				|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE)
+				|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE))
+				return -1;

 			/* wait 100 msec */
 			if (sleepFlag == CAN_SLEEP) {
@@ -3292,7 +3480,8 @@

 			}

-			diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+			if (CHIPREG_READ32(ioc, &ioc->chip->Diagnostic, &diag0val))
+				return -1;

 			dprintk((MYIOC_s_INFO_FMT "Wrote magic DiagWriteEn sequence (%x)\n",
 					ioc->name, diag0val));
@@ -3300,7 +3489,8 @@

 #ifdef MPT_DEBUG
 		if (ioc->alt_ioc)
-			diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
+			if (CHIPREG_READ32(ioc->alt_ioc, &ioc->alt_ioc->chip->Diagnostic, &diag1val))
+				return -1;
 		dprintk((MYIOC_s_INFO_FMT "DbG2: diag0=%08x, diag1=%08x\n",
 				ioc->name, diag0val, diag1val));
 #endif
@@ -3308,14 +3498,16 @@
 		 * Disable the ARM (Bug fix)
 		 *
 		 */
-		CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM);
+		if (CHIPREG_WRITE32(ioc, &ioc->chip->Diagnostic, diag0val | MPI_DIAG_DISABLE_ARM))
+			return -1;
 		mdelay(1);

 		/*
 		 * Now hit the reset bit in the Diagnostic register
 		 * (THE BIG HAMMER!) (Clears DRWE bit).
 		 */
-		CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER);
+		if (CHIPREG_WRITE32(ioc, &ioc->chip->Diagnostic, diag0val | MPI_DIAG_RESET_ADAPTER))
+			return -1;
 		hard_reset_done = 1;
 		dprintk((MYIOC_s_INFO_FMT "Diagnostic reset performed\n",
 				ioc->name));
@@ -3351,7 +3543,8 @@
 			 * case.  _diag_reset will return < 0
 			 */
 			for (count = 0; count < 30; count ++) {
-				diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+				if (CHIPREG_READ32(ioc, &ioc->chip->Diagnostic, &diag0val))
+					return -1;
 				if (!(diag0val & MPI_DIAG_RESET_ADAPTER)) {
 					break;
 				}
@@ -3377,7 +3570,8 @@
 			 * with calling program.
 			 */
 			for (count = 0; count < 60; count ++) {
-				doorbell = CHIPREG_READ32(&ioc->chip->Doorbell);
+			  if (CHIPREG_READ32(ioc, &ioc->chip->Doorbell, &doorbell))
+					return -1;
 				doorbell &= MPI_IOC_STATE_MASK;

 				if (doorbell == MPI_IOC_STATE_READY) {
@@ -3394,10 +3588,12 @@
 		}
 	}

-	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+	if (CHIPREG_READ32(ioc, &ioc->chip->Diagnostic, &diag0val))
+		return -1;
 #ifdef MPT_DEBUG
 	if (ioc->alt_ioc)
-		diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
+		if (CHIPREG_READ32(ioc->alt_ioc, &ioc->alt_ioc->chip->Diagnostic, &diag1val))
+			return -1;
 	dprintk((MYIOC_s_INFO_FMT "DbG3: diag0=%08x, diag1=%08x\n",
 		ioc->name, diag0val, diag1val));
 #endif
@@ -3405,18 +3601,20 @@
 	/* Clear RESET_HISTORY bit!  Place board in the
 	 * diagnostic mode to update the diag register.
 	 */
-	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+	if (CHIPREG_READ32(ioc, &ioc->chip->Diagnostic, &diag0val))
+		return -1;
 	count = 0;
 	while ((diag0val & MPI_DIAG_DRWE) == 0) {
 		/* Write magic sequence to WriteSequence register
 		 * Loop until in diagnostic mode
 		 */
-		CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
-		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
-		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
-		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE);
-		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE);
-		CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE);
+		if (CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, 0xFF)
+			|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE)
+			|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE)
+			|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_3RD_KEY_VALUE)
+			|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_4TH_KEY_VALUE)
+			|| CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, MPI_WRSEQ_5TH_KEY_VALUE))
+			return -1;

 		/* wait 100 msec */
 		if (sleepFlag == CAN_SLEEP) {
@@ -3431,11 +3629,15 @@
 					ioc->name, diag0val);
 			break;
 		}
-		diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+		if (CHIPREG_READ32(ioc, &ioc->chip->Diagnostic, &diag0val))
+			return -1;
 	}
 	diag0val &= ~MPI_DIAG_RESET_HISTORY;
-	CHIPREG_WRITE32(&ioc->chip->Diagnostic, diag0val);
-	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->Diagnostic, diag0val))
+		return -1;
+
+	if (CHIPREG_READ32(ioc, &ioc->chip->Diagnostic, &diag0val))
+		return -1;
 	if (diag0val & MPI_DIAG_RESET_HISTORY) {
 		printk(MYIOC_s_WARN_FMT "ResetHistory bit failed to clear!\n",
 				ioc->name);
@@ -3443,11 +3645,13 @@

 	/* Disable Diagnostic Mode
 	 */
-	CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFFFFFFFF);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->WriteSequence, 0xFFFFFFFF))
+		return -1;

 	/* Check FW reload status flags.
 	 */
-	diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
+	if (CHIPREG_READ32(ioc, &ioc->chip->Diagnostic, &diag0val))
+		return -1;
 	if (diag0val & (MPI_DIAG_FLASH_BAD_SIG | MPI_DIAG_RESET_ADAPTER | MPI_DIAG_DISABLE_ARM)) {
 		printk(MYIOC_s_ERR_FMT "Diagnostic reset FAILED! (%02xh)\n",
 				ioc->name, diag0val);
@@ -3456,7 +3660,8 @@

 #ifdef MPT_DEBUG
 	if (ioc->alt_ioc)
-		diag1val = CHIPREG_READ32(&ioc->alt_ioc->chip->Diagnostic);
+		if (CHIPREG_READ32(ioc->alt_ioc, &ioc->alt_ioc->chip->Diagnostic, &diag1val))
+			return -1;
 	dprintk((MYIOC_s_INFO_FMT "DbG4: diag0=%08x, diag1=%08x\n",
 			ioc->name, diag0val, diag1val));
 #endif
@@ -3492,7 +3697,8 @@

 	drsprintk((KERN_INFO MYNAM ": %s: Sending IOC reset(0x%02x)!\n",
 			ioc->name, reset_type));
-	CHIPREG_WRITE32(&ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->Doorbell, reset_type<<MPI_DOORBELL_FUNCTION_SHIFT))
+		return -EFAULT;
 	if ((r = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
 		return r;

@@ -3789,7 +3995,9 @@

 	for (i = 0; i < ioc->reply_depth; i++) {
 		/*  Write each address to the IOC!  */
-		CHIPREG_WRITE32(&ioc->chip->ReplyFifo, alloc_dma);
+		if (CHIPREG_WRITE32(ioc, &ioc->chip->ReplyFifo, alloc_dma))
+			goto out_fail;
+
 		alloc_dma += ioc->reply_sz;
 	}

@@ -3854,10 +4062,11 @@
 	 * then tell IOC that we want to handshake a request of N words.
 	 * (WRITE u32val to Doorbell reg).
 	 */
-	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
-	CHIPREG_WRITE32(&ioc->chip->Doorbell,
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->IntStatus, 0)
+		|| CHIPREG_WRITE32(ioc, &ioc->chip->Doorbell,
 			((MPI_FUNCTION_HANDSHAKE<<MPI_DOORBELL_FUNCTION_SHIFT) |
-			 ((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT)));
+			((reqBytes/4)<<MPI_DOORBELL_ADD_DWORDS_SHIFT))))
+		return -1;

 	/*
 	 * Wait for IOC's doorbell handshake int
@@ -3869,15 +4078,21 @@
 			ioc->name, reqBytes, t, failcnt ? " - MISSING DOORBELL HANDSHAKE!" : ""));

 	/* Read doorbell and check for active bit */
-	if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE))
+	{
+		u32 pa;
+		u16 status;
+		status = CHIPREG_READ32(ioc, &ioc->chip->Doorbell, &pa);
+		if (status || !(pa & MPI_DOORBELL_ACTIVE))
 			return -1;
+	}

 	/*
 	 * Clear doorbell int (WRITE 0 to IntStatus reg),
 	 * then wait for IOC to ACKnowledge that it's ready for
 	 * our handshake request.
 	 */
-	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->IntStatus, 0))
+		return -1;
 	if (!failcnt && (t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
 		failcnt++;

@@ -3895,7 +4110,8 @@
 				    (req_as_bytes[(ii*4) + 2] << 16) |
 				    (req_as_bytes[(ii*4) + 3] << 24));

-			CHIPREG_WRITE32(&ioc->chip->Doorbell, word);
+			if (CHIPREG_WRITE32(ioc, &ioc->chip->Doorbell, word))
+				return -1;
 			if ((t = WaitForDoorbellAck(ioc, 5, sleepFlag)) < 0)
 				failcnt++;
 		}
@@ -3951,7 +4167,8 @@

 	if (sleepFlag == CAN_SLEEP) {
 		while (--cntdn) {
-			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
+			if (CHIPREG_READ32(ioc, &ioc->chip->IntStatus, &intstat))
+				return -1;
 			if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
 				break;
 			msleep_interruptible (1);
@@ -3959,7 +4176,8 @@
 		}
 	} else {
 		while (--cntdn) {
-			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
+			if (CHIPREG_READ32(ioc, &ioc->chip->IntStatus, &intstat))
+				return -1;
 			if (! (intstat & MPI_HIS_IOP_DOORBELL_STATUS))
 				break;
 			mdelay (1);
@@ -4000,7 +4218,8 @@
 	cntdn = 1000 * howlong;
 	if (sleepFlag == CAN_SLEEP) {
 		while (--cntdn) {
-			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
+			if (CHIPREG_READ32(ioc, &ioc->chip->IntStatus, &intstat))
+				return -1;
 			if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
 				break;
 			msleep_interruptible(1);
@@ -4008,7 +4227,8 @@
 		}
 	} else {
 		while (--cntdn) {
-			intstat = CHIPREG_READ32(&ioc->chip->IntStatus);
+			if (CHIPREG_READ32(ioc, &ioc->chip->IntStatus, &intstat))
+				return -1;
 			if (intstat & MPI_HIS_DOORBELL_INTERRUPT)
 				break;
 			mdelay(1);
@@ -4059,13 +4279,27 @@
 	if ((t = WaitForDoorbellInt(ioc, howlong, sleepFlag)) < 0) {
 		failcnt++;
 	} else {
-		hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
-		CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+		{
+			u32 pa;
+			if (CHIPREG_READ32(ioc, &ioc->chip->Doorbell, &pa))
+				return -1;
+			hs_reply[u16cnt++] = le16_to_cpu(pa & 0x0000FFFF);
+		}
+
+		if (CHIPREG_WRITE32(ioc, &ioc->chip->IntStatus, 0))
+			return -1;
 		if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
 			failcnt++;
 		else {
-			hs_reply[u16cnt++] = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
-			CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+			{
+				u32 pa;
+				if (CHIPREG_READ32(ioc, &ioc->chip->Doorbell, &pa))
+					return -1;
+				hs_reply[u16cnt++] = le16_to_cpu(pa & 0x0000FFFF);
+			}
+
+			if (CHIPREG_WRITE32(ioc, &ioc->chip->IntStatus, 0))
+				return -1;
 		}
 	}

@@ -4080,16 +4314,23 @@
 	for (u16cnt=2; !failcnt && u16cnt < (2 * mptReply->MsgLength); u16cnt++) {
 		if ((t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
 			failcnt++;
-		hword = le16_to_cpu(CHIPREG_READ32(&ioc->chip->Doorbell) & 0x0000FFFF);
+		{
+			u32 pa;
+			if (CHIPREG_READ32(ioc, &ioc->chip->Doorbell, &pa))
+				return -1;
+			hword = le16_to_cpu(pa & 0x0000FFFF);
+		}
 		/* don't overflow our IOC hs_reply[] buffer! */
 		if (u16cnt < sizeof(ioc->hs_reply) / sizeof(ioc->hs_reply[0]))
 			hs_reply[u16cnt] = hword;
-		CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+		if (CHIPREG_WRITE32(ioc, &ioc->chip->IntStatus, 0))
+			return -1;
 	}

 	if (!failcnt && (t = WaitForDoorbellInt(ioc, 5, sleepFlag)) < 0)
 		failcnt++;
-	CHIPREG_WRITE32(&ioc->chip->IntStatus, 0);
+	if (CHIPREG_WRITE32(ioc, &ioc->chip->IntStatus, 0))
+		return -1;

 	if (failcnt) {
 		printk(MYIOC_s_ERR_FMT "Handshake reply failure!\n",


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux