#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/dma-mapping.h>
-#include "scsi.h"
+#include <linux/device.h>
#include <scsi/scsi_host.h>
+#include <scsi/scsi_cmnd.h>
#include <linux/libata.h>
#include <asm/io.h>
PORT_IRQ_D2H_REG_FIS,
/* PORT_CMD bits */
+ PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */
PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */
PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */
PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */
static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
static void ahci_qc_prep(struct ata_queued_cmd *qc);
static u8 ahci_check_status(struct ata_port *ap);
-static u8 ahci_check_err(struct ata_port *ap);
static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
static void ahci_remove_one (struct pci_dev *pdev);
-static Scsi_Host_Template ahci_sht = {
+static struct scsi_host_template ahci_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
.ioctl = ata_scsi_ioctl,
.ordered_flush = 1,
};
-static struct ata_port_operations ahci_ops = {
+static const struct ata_port_operations ahci_ops = {
.port_disable = ata_port_disable,
.check_status = ahci_check_status,
.check_altstatus = ahci_check_status,
- .check_err = ahci_check_err,
.dev_select = ata_noop_dev_select,
.tf_read = ahci_tf_read,
},
};
-static struct pci_device_id ahci_pci_tbl[] = {
+static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VENDOR_ID_INTEL, 0x2652, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
board_ahci }, /* ICH6 */
{ PCI_VENDOR_ID_INTEL, 0x2653, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
void *mem;
dma_addr_t mem_dma;
+ int rc;
pp = kmalloc(sizeof(*pp), GFP_KERNEL);
if (!pp)
return -ENOMEM;
memset(pp, 0, sizeof(*pp));
+ rc = ata_pad_alloc(ap, dev);
+ if (rc) {
+ kfree(pp);
+ return rc;
+ }
+
mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL);
if (!mem) {
+ ata_pad_free(ap, dev);
kfree(pp);
return -ENOMEM;
}
ap->private_data = NULL;
dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ,
pp->cmd_slot, pp->cmd_slot_dma);
+ ata_pad_free(ap, dev);
kfree(pp);
}
void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
struct ata_taskfile tf;
struct ata_device *dev = &ap->device[0];
- u32 tmp;
+ u32 new_tmp, tmp;
__sata_phy_reset(ap);
tf.nsect = (tmp) & 0xff;
dev->class = ata_dev_classify(&tf);
- if (!ata_dev_present(dev))
+ if (!ata_dev_present(dev)) {
ata_port_disable(ap);
+ return;
+ }
+
+ /* Make sure port's ATAPI bit is set appropriately */
+ new_tmp = tmp = readl(port_mmio + PORT_CMD);
+ if (dev->class == ATA_DEV_ATAPI)
+ new_tmp |= PORT_CMD_ATAPI;
+ else
+ new_tmp &= ~PORT_CMD_ATAPI;
+ if (new_tmp != tmp) {
+ writel(new_tmp, port_mmio + PORT_CMD);
+ readl(port_mmio + PORT_CMD); /* flush */
+ }
}
static u8 ahci_check_status(struct ata_port *ap)
return readl(mmio + PORT_TFDATA) & 0xFF;
}
-static u8 ahci_check_err(struct ata_port *ap)
-{
- void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr;
-
- return (readl(mmio + PORT_TFDATA) >> 8) & 0xFF;
-}
-
static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
{
struct ahci_port_priv *pp = ap->private_data;
ata_tf_from_fis(d2h_fis, tf);
}
-static void ahci_fill_sg(struct ata_queued_cmd *qc)
+static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc)
{
struct ahci_port_priv *pp = qc->ap->private_data;
- unsigned int i;
+ struct scatterlist *sg;
+ struct ahci_sg *ahci_sg;
+ unsigned int n_sg = 0;
VPRINTK("ENTER\n");
/*
* Next, the S/G list.
*/
- for (i = 0; i < qc->n_elem; i++) {
- u32 sg_len;
- dma_addr_t addr;
+ ahci_sg = pp->cmd_tbl_sg;
+ ata_for_each_sg(sg, qc) {
+ dma_addr_t addr = sg_dma_address(sg);
+ u32 sg_len = sg_dma_len(sg);
- addr = sg_dma_address(&qc->sg[i]);
- sg_len = sg_dma_len(&qc->sg[i]);
+ ahci_sg->addr = cpu_to_le32(addr & 0xffffffff);
+ ahci_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16);
+ ahci_sg->flags_size = cpu_to_le32(sg_len - 1);
- pp->cmd_tbl_sg[i].addr = cpu_to_le32(addr & 0xffffffff);
- pp->cmd_tbl_sg[i].addr_hi = cpu_to_le32((addr >> 16) >> 16);
- pp->cmd_tbl_sg[i].flags_size = cpu_to_le32(sg_len - 1);
+ ahci_sg++;
+ n_sg++;
}
+
+ return n_sg;
}
static void ahci_qc_prep(struct ata_queued_cmd *qc)
struct ahci_port_priv *pp = ap->private_data;
u32 opts;
const u32 cmd_fis_len = 5; /* five dwords */
+ unsigned int n_elem;
/*
* Fill in command slot information (currently only one slot,
* slot 0, is currently since we don't do queueing)
*/
- opts = (qc->n_elem << 16) | cmd_fis_len;
+ opts = cmd_fis_len;
if (qc->tf.flags & ATA_TFLAG_WRITE)
opts |= AHCI_CMD_WRITE;
if (is_atapi_taskfile(&qc->tf))
if (!(qc->flags & ATA_QCFLAG_DMAMAP))
return;
- ahci_fill_sg(qc);
+ n_elem = ahci_fill_sg(qc);
+
+ pp->cmd_slot[0].opts |= cpu_to_le32(n_elem << 16);
}
static void ahci_intr_error(struct ata_port *ap, u32 irq_stat)
* not being called from the SCSI EH.
*/
qc->scsidone = scsi_finish_command;
- ata_qc_complete(qc, ATA_ERR);
+ ata_qc_complete(qc, AC_ERR_OTHER);
}
spin_unlock_irqrestore(&host_set->lock, flags);
if (status & PORT_IRQ_FATAL) {
ahci_intr_error(ap, status);
if (qc)
- ata_qc_complete(qc, ATA_ERR);
+ ata_qc_complete(qc, AC_ERR_OTHER);
}
return 1;
if (!ahci_host_intr(ap, qc))
if (ata_ratelimit()) {
struct pci_dev *pdev =
- to_pci_dev(ap->host_set->dev);
- printk(KERN_WARNING
- "ahci(%s): unhandled interrupt on port %u\n",
- pci_name(pdev), i);
+ to_pci_dev(ap->host_set->dev);
+ dev_printk(KERN_WARNING, &pdev->dev,
+ "unhandled interrupt on port %u\n",
+ i);
}
VPRINTK("port %u\n", i);
VPRINTK("port %u (no irq)\n", i);
if (ata_ratelimit()) {
struct pci_dev *pdev =
- to_pci_dev(ap->host_set->dev);
- printk(KERN_WARNING
- "ahci(%s): interrupt on disabled port %u\n",
- pci_name(pdev), i);
+ to_pci_dev(ap->host_set->dev);
+ dev_printk(KERN_WARNING, &pdev->dev,
+ "interrupt on disabled port %u\n", i);
}
}
tmp = readl(mmio + HOST_CTL);
if (tmp & HOST_RESET) {
- printk(KERN_ERR DRV_NAME "(%s): controller reset failed (0x%x)\n",
- pci_name(pdev), tmp);
+ dev_printk(KERN_ERR, &pdev->dev,
+ "controller reset failed (0x%x)\n", tmp);
return -EIO;
}
if (rc) {
rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
- printk(KERN_ERR DRV_NAME "(%s): 64-bit DMA enable failed\n",
- pci_name(pdev));
+ dev_printk(KERN_ERR, &pdev->dev,
+ "64-bit DMA enable failed\n");
return rc;
}
}
} else {
rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
- printk(KERN_ERR DRV_NAME "(%s): 32-bit DMA enable failed\n",
- pci_name(pdev));
+ dev_printk(KERN_ERR, &pdev->dev,
+ "32-bit DMA enable failed\n");
return rc;
}
rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
if (rc) {
- printk(KERN_ERR DRV_NAME "(%s): 32-bit consistent DMA enable failed\n",
- pci_name(pdev));
+ dev_printk(KERN_ERR, &pdev->dev,
+ "32-bit consistent DMA enable failed\n");
return rc;
}
}
else
scc_s = "unknown";
- printk(KERN_INFO DRV_NAME "(%s) AHCI %02x%02x.%02x%02x "
+ dev_printk(KERN_INFO, &pdev->dev,
+ "AHCI %02x%02x.%02x%02x "
"%u slots %u ports %s Gbps 0x%x impl %s mode\n"
,
- pci_name(pdev),
(vers >> 24) & 0xff,
(vers >> 16) & 0xff,
impl,
scc_s);
- printk(KERN_INFO DRV_NAME "(%s) flags: "
+ dev_printk(KERN_INFO, &pdev->dev,
+ "flags: "
"%s%s%s%s%s%s"
"%s%s%s%s%s%s%s\n"
,
- pci_name(pdev),
cap & (1 << 31) ? "64bit " : "",
cap & (1 << 30) ? "ncq " : "",
VPRINTK("ENTER\n");
if (!printed_version++)
- printk(KERN_DEBUG DRV_NAME " version " DRV_VERSION "\n");
+ dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
rc = pci_enable_device(pdev);
if (rc)