I just checked this into the 'sil-lbt' branch of libata-dev.git:
I had written a previous version of this patch, but it never worked. I
finally figured out my dumb bug, so I dusted off the patch, finished it,
and verified it works.
This will probably head upstream.
NOTE: This conflicts with the sata_sil interrupt handling patch I
posted yesterday. Applying both patches is fine, but you'll have to fix
up some trivial patch rejections.
drivers/scsi/sata_sil.c | 116 ++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 103 insertions(+), 13 deletions(-)
[libata sata_sil] Greatly improve DMA handling
311x hardware includes a vendor-specific scatter/gather format which
eliminates the traditional 64k boundary limit found in PCI IDE DMA.
Since implementing this feature required custom implementations
of the bmdma_xxx hooks, I took the opportunity to eliminate a few
unnecessary MMIO register reads/writes.
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 3609186..5f7220d 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -80,11 +80,20 @@ enum {
SIL_QUIRK_UDMA5MAX = (1 << 1),
};
+enum {
+ SIL_DMA_BOUNDARY = 0xffffffffU,
+};
+
static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
static void sil_dev_config(struct ata_port *ap, struct ata_device *dev);
static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg);
static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
static void sil_post_set_mode (struct ata_port *ap);
+static void sil_qc_prep(struct ata_queued_cmd *qc);
+static void sil_bmdma_setup (struct ata_queued_cmd *qc);
+static void sil_bmdma_start (struct ata_queued_cmd *qc);
+static void sil_bmdma_stop(struct ata_queued_cmd *qc);
+
static const struct pci_device_id sil_pci_tbl[] = {
@@ -138,13 +147,13 @@ static struct scsi_host_template sil_sht
.eh_strategy_handler = ata_scsi_error,
.can_queue = ATA_DEF_QUEUE,
.this_id = ATA_SHT_THIS_ID,
- .sg_tablesize = LIBATA_MAX_PRD,
+ .sg_tablesize = ATA_MAX_PRD,
.max_sectors = ATA_MAX_SECTORS,
.cmd_per_lun = ATA_SHT_CMD_PER_LUN,
.emulated = ATA_SHT_EMULATED,
.use_clustering = ATA_SHT_USE_CLUSTERING,
.proc_name = DRV_NAME,
- .dma_boundary = ATA_DMA_BOUNDARY,
+ .dma_boundary = SIL_DMA_BOUNDARY,
.slave_configure = ata_scsi_slave_config,
.bios_param = ata_std_bios_param,
.ordered_flush = 1,
@@ -160,11 +169,11 @@ static const struct ata_port_operations
.dev_select = ata_std_dev_select,
.phy_reset = sata_phy_reset,
.post_set_mode = sil_post_set_mode,
- .bmdma_setup = ata_bmdma_setup,
- .bmdma_start = ata_bmdma_start,
- .bmdma_stop = ata_bmdma_stop,
+ .bmdma_setup = sil_bmdma_setup,
+ .bmdma_start = sil_bmdma_start,
+ .bmdma_stop = sil_bmdma_stop,
.bmdma_status = ata_bmdma_status,
- .qc_prep = ata_qc_prep,
+ .qc_prep = sil_qc_prep,
.qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout,
.irq_handler = ata_interrupt,
@@ -214,16 +223,18 @@ static const struct {
unsigned long tf; /* ATA taskfile register block */
unsigned long ctl; /* ATA control/altstatus register block */
unsigned long bmdma; /* DMA register block */
+ unsigned long bmdma_lbt;/* Large block DMA register block */
unsigned long scr; /* SATA control register block */
unsigned long sien; /* SATA Interrupt Enable register */
unsigned long xfer_mode;/* data transfer mode register */
} sil_port[] = {
- /* port 0 ... */
- { 0x80, 0x8A, 0x00, 0x100, 0x148, 0xb4 },
- { 0xC0, 0xCA, 0x08, 0x180, 0x1c8, 0xf4 },
- { 0x280, 0x28A, 0x200, 0x300, 0x348, 0x2b4 },
- { 0x2C0, 0x2CA, 0x208, 0x380, 0x3c8, 0x2f4 },
- /* ... port 3 */
+
+ /* tf ctl bmdma lbt scr sien mode */
+ { 0x80, 0x8A, 0x0, 0x10, 0x100, 0x148, 0xb4 }, /* port 0 */
+ { 0xC0, 0xCA, 0x8, 0x18, 0x180, 0x1c8, 0xf4 }, /* port 1 */
+ { 0x280, 0x28A, 0x200, 0x210, 0x300, 0x348, 0x2b4 }, /* port 2 */
+ { 0x2C0, 0x2CA, 0x208, 0x218, 0x380, 0x3c8, 0x2f4 }, /* port 3 */
+
};
MODULE_AUTHOR("Jeff Garzik");
@@ -233,6 +244,85 @@ MODULE_DEVICE_TABLE(pci, sil_pci_tbl);
MODULE_VERSION(DRV_VERSION);
+static void sil_bmdma_stop(struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
+ u32 val;
+
+ /* clear start/stop bit */
+ if (ap->port_no == 2)
+ val = SIL_INTR_STEERING;
+ else
+ val = 0;
+ writeb(val, mmio + ATA_DMA_CMD);
+
+ /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
+ ata_altstatus(ap); /* dummy read */
+}
+
+static void sil_bmdma_setup (struct ata_queued_cmd *qc)
+{
+ struct ata_port *ap = qc->ap;
+ void __iomem *mmio;
+
+ mmio = ap->host_set->mmio_base + sil_port[ap->port_no].bmdma;
+
+ /* load PRD table addr. */
+ mb(); /* make sure PRD table writes are visible to controller */
+ writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS);
+
+ /* issue r/w command */
+ ata_exec_command(ap, &qc->tf);
+}
+
+static void sil_bmdma_start (struct ata_queued_cmd *qc)
+{
+ unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
+ struct ata_port *ap = qc->ap;
+ void __iomem *mmio;
+ u8 dmactl;
+
+ mmio = ap->host_set->mmio_base + sil_port[ap->port_no].bmdma_lbt;
+
+ /* set transfer direction, start host DMA transaction */
+ dmactl = readb(mmio + ATA_DMA_CMD);
+ dmactl &= ~ATA_DMA_WR;
+ if (!rw)
+ dmactl |= ATA_DMA_WR;
+ writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
+}
+
+/* The way God intended PCI IDE scatter/gather lists to look and behave... */
+static inline void sil_fill_sg(struct ata_queued_cmd *qc)
+{
+ struct scatterlist *sg;
+ struct ata_port *ap = qc->ap;
+ struct ata_prd *prd;
+
+ prd = &ap->prd[0];
+ ata_for_each_sg(sg, qc) {
+ u32 addr = sg_dma_address(sg);
+ u32 sg_len = sg_dma_len(sg);
+
+ prd->addr = cpu_to_le32(addr);
+ prd->flags_len = cpu_to_le32(sg_len);
+
+ if (ata_sg_is_last(sg, qc))
+ prd->flags_len |= cpu_to_le32(ATA_PRD_EOT);
+
+ prd++;
+ }
+}
+
+static void sil_qc_prep(struct ata_queued_cmd *qc)
+{
+ if (!(qc->flags & ATA_QCFLAG_DMAMAP))
+ return;
+
+ sil_fill_sg(qc);
+}
+
static unsigned char sil_get_device_cache_line(struct pci_dev *pdev)
{
u8 cache_line = 0;
@@ -442,7 +532,7 @@ static int sil_init_one (struct pci_dev
probe_ent->port[i].cmd_addr = base + sil_port[i].tf;
probe_ent->port[i].altstatus_addr =
probe_ent->port[i].ctl_addr = base + sil_port[i].ctl;
- probe_ent->port[i].bmdma_addr = base + sil_port[i].bmdma;
+ probe_ent->port[i].bmdma_addr = base + sil_port[i].bmdma_lbt;
probe_ent->port[i].scr_addr = base + sil_port[i].scr;
ata_std_ports(&probe_ent->port[i]);
}
Jeff Garzik wrote:
>
> To make it easy for others to test, since there are merge conflicts,
> I've combined the two previous sata_sil patches into a single patch.
>
> Verified here on my 3112 (Adaptec 1210SA).
>
> I'm especially interested to hear from anyone willing to test on a
> SI 3114 (4-port).
>
>
Please cc me as I'm not subscribed....
ASUS K8N-E-Deluxe, nForce3 250Gb chipset, AMD Athlon64 3200+ running x86_64
Sil 3114A with 3 Maxtor MaxLine III+ 250GBSATA disks running in linux raid1,
linux raid0 and linux LVM2
Boots and runs without problem with 2.6.15-rc5-git1,
Applying this patch lets it boot, but I cant login either locally or with
ssh, no output on VT12 or in the logs, but the hd led is lit all the
time...
only way to reboot is the reset button...
Distribution is Mandriva Linux 2006 x86_64, gcc 4.0.1
attached are config and /var/log/messages parts that got logged
--
Regards
Thomas
Thomas Backlund wrote:
> Jeff Garzik wrote:
>
>
>>To make it easy for others to test, since there are merge conflicts,
>>I've combined the two previous sata_sil patches into a single patch.
>>
>>Verified here on my 3112 (Adaptec 1210SA).
>>
>>I'm especially interested to hear from anyone willing to test on a
>>SI 3114 (4-port).
>>
>>
>
>
> Please cc me as I'm not subscribed....
>
>
> ASUS K8N-E-Deluxe, nForce3 250Gb chipset, AMD Athlon64 3200+ running x86_64
>
> Sil 3114A with 3 Maxtor MaxLine III+ 250GBSATA disks running in linux raid1,
> linux raid0 and linux LVM2
>
> Boots and runs without problem with 2.6.15-rc5-git1,
>
> Applying this patch lets it boot, but I cant login either locally or with
> ssh, no output on VT12 or in the logs, but the hd led is lit all the
> time...
Thanks for testing.
> only way to reboot is the reset button...
>
>
> Distribution is Mandriva Linux 2006 x86_64, gcc 4.0.1
>
> attached are config and /var/log/messages parts that got logged
Didn't receive any attachments...
Jeff
tisdag 06 december 2005 11:06 skrev Jeff Garzik:
> Thomas Backlund wrote:
> > Jeff Garzik wrote:
> >>To make it easy for others to test, since there are merge conflicts,
> >>I've combined the two previous sata_sil patches into a single patch.
> >>
> >>Verified here on my 3112 (Adaptec 1210SA).
> >>
> >>I'm especially interested to hear from anyone willing to test on a
> >>SI 3114 (4-port).
> >
> > Please cc me as I'm not subscribed....
> >
> >
> > ASUS K8N-E-Deluxe, nForce3 250Gb chipset, AMD Athlon64 3200+ running
> > x86_64
> >
> > Sil 3114A with 3 Maxtor MaxLine III+ 250GBSATA disks running in linux
> > raid1, linux raid0 and linux LVM2
> >
> > Boots and runs without problem with 2.6.15-rc5-git1,
> >
> > Applying this patch lets it boot, but I cant login either locally or with
> > ssh, no output on VT12 or in the logs, but the hd led is lit all the
> > time...
>
> Thanks for testing.
>
> > only way to reboot is the reset button...
> >
> >
> > Distribution is Mandriva Linux 2006 x86_64, gcc 4.0.1
> >
> > attached are config and /var/log/messages parts that got logged
>
> Didn't receive any attachments...
>
> Jeff
Sorry, my misstake ....
Here they are...
--
--
Regards
Thomas
tisdag 06 december 2005 11:06 skrev Jeff Garzik:
> Thomas Backlund wrote:
> > Jeff Garzik wrote:
> >>To make it easy for others to test, since there are merge conflicts,
> >>I've combined the two previous sata_sil patches into a single patch.
> >>
> >>Verified here on my 3112 (Adaptec 1210SA).
> >>
> >>I'm especially interested to hear from anyone willing to test on a
> >>SI 3114 (4-port).
> >
> > Please cc me as I'm not subscribed....
> >
> >
> > ASUS K8N-E-Deluxe, nForce3 250Gb chipset, AMD Athlon64 3200+ running
> > x86_64
> >
> > Sil 3114A with 3 Maxtor MaxLine III+ 250GBSATA disks running in linux
> > raid1, linux raid0 and linux LVM2
> >
> > Boots and runs without problem with 2.6.15-rc5-git1,
> >
> > Applying this patch lets it boot, but I cant login either locally or with
> > ssh, no output on VT12 or in the logs, but the hd led is lit all the
> > time...
>
> Thanks for testing.
>
> > only way to reboot is the reset button...
> >
> >
> > Distribution is Mandriva Linux 2006 x86_64, gcc 4.0.1
> >
> > attached are config and /var/log/messages parts that got logged
>
> Didn't receive any attachments...
>
> Jeff
And just to add...
as you can see from the messages file the kernel is capable of writing logging
of the whole bootup to the disks, but it stopped logging pretty much directly
as the kernel was fully started...
Any more tests you want?? more debugging enabled? or what?...
--
Regards
Thomas