aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorManuel Lauss <manuel.lauss@googlemail.com>2009-10-13 14:22:35 -0400
committerRalf Baechle <ralf@linux-mips.org>2010-02-27 06:52:55 -0500
commit963accbc82a0912b39de39d59e2fd6741db3aa4b (patch)
tree4ea340b0261ab19f3f0776f47e4fab8708934b5b /drivers
parentea071cc705e8bfba0c8bf84be8d4f9f4e9da6962 (diff)
MIPS: Alchemy: change dbdma to accept physical memory addresses
DMA can only be done from physical addresses; move the "virt_to_phys" source/destination buffer address translation from the dbdma queueing functions (since the hardware can only DMA to/from physical addresses) to their respective users. Signed-off-by: Manuel Lauss <manuel.lauss@gmail.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ide/au1xxx-ide.c8
-rw-r--r--drivers/mmc/host/au1xmmc.c4
-rw-r--r--drivers/spi/au1550_spi.c4
3 files changed, 8 insertions, 8 deletions
diff --git a/drivers/ide/au1xxx-ide.c b/drivers/ide/au1xxx-ide.c
index 377412e1d32b..349a67bf1a36 100644
--- a/drivers/ide/au1xxx-ide.c
+++ b/drivers/ide/au1xxx-ide.c
@@ -56,7 +56,7 @@ static inline void auide_insw(unsigned long port, void *addr, u32 count)
56 chan_tab_t *ctp; 56 chan_tab_t *ctp;
57 au1x_ddma_desc_t *dp; 57 au1x_ddma_desc_t *dp;
58 58
59 if (!au1xxx_dbdma_put_dest(ahwif->rx_chan, (void*)addr, 59 if (!au1xxx_dbdma_put_dest(ahwif->rx_chan, virt_to_phys(addr),
60 count << 1, DDMA_FLAGS_NOIE)) { 60 count << 1, DDMA_FLAGS_NOIE)) {
61 printk(KERN_ERR "%s failed %d\n", __func__, __LINE__); 61 printk(KERN_ERR "%s failed %d\n", __func__, __LINE__);
62 return; 62 return;
@@ -74,7 +74,7 @@ static inline void auide_outsw(unsigned long port, void *addr, u32 count)
74 chan_tab_t *ctp; 74 chan_tab_t *ctp;
75 au1x_ddma_desc_t *dp; 75 au1x_ddma_desc_t *dp;
76 76
77 if (!au1xxx_dbdma_put_source(ahwif->tx_chan, (void*)addr, 77 if (!au1xxx_dbdma_put_source(ahwif->tx_chan, virt_to_phys(addr),
78 count << 1, DDMA_FLAGS_NOIE)) { 78 count << 1, DDMA_FLAGS_NOIE)) {
79 printk(KERN_ERR "%s failed %d\n", __func__, __LINE__); 79 printk(KERN_ERR "%s failed %d\n", __func__, __LINE__);
80 return; 80 return;
@@ -247,13 +247,13 @@ static int auide_build_dmatable(ide_drive_t *drive, struct ide_cmd *cmd)
247 247
248 if (iswrite) { 248 if (iswrite) {
249 if (!au1xxx_dbdma_put_source(ahwif->tx_chan, 249 if (!au1xxx_dbdma_put_source(ahwif->tx_chan,
250 (void *)sg_virt(sg), tc, flags)) { 250 sg_phys(sg), tc, flags)) {
251 printk(KERN_ERR "%s failed %d\n", 251 printk(KERN_ERR "%s failed %d\n",
252 __func__, __LINE__); 252 __func__, __LINE__);
253 } 253 }
254 } else { 254 } else {
255 if (!au1xxx_dbdma_put_dest(ahwif->rx_chan, 255 if (!au1xxx_dbdma_put_dest(ahwif->rx_chan,
256 (void *)sg_virt(sg), tc, flags)) { 256 sg_phys(sg), tc, flags)) {
257 printk(KERN_ERR "%s failed %d\n", 257 printk(KERN_ERR "%s failed %d\n",
258 __func__, __LINE__); 258 __func__, __LINE__);
259 } 259 }
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index d295dc5e4f6b..c8649dfb2d0c 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -651,10 +651,10 @@ static int au1xmmc_prepare_data(struct au1xmmc_host *host,
651 651
652 if (host->flags & HOST_F_XMIT) { 652 if (host->flags & HOST_F_XMIT) {
653 ret = au1xxx_dbdma_put_source(channel, 653 ret = au1xxx_dbdma_put_source(channel,
654 (void *)sg_virt(sg), len, flags); 654 sg_phys(sg), len, flags);
655 } else { 655 } else {
656 ret = au1xxx_dbdma_put_dest(channel, 656 ret = au1xxx_dbdma_put_dest(channel,
657 (void *)sg_virt(sg), len, flags); 657 sg_phys(sg), len, flags);
658 } 658 }
659 659
660 if (!ret) 660 if (!ret)
diff --git a/drivers/spi/au1550_spi.c b/drivers/spi/au1550_spi.c
index 22f7d7294787..ba8ac4f599d3 100644
--- a/drivers/spi/au1550_spi.c
+++ b/drivers/spi/au1550_spi.c
@@ -412,12 +412,12 @@ static int au1550_spi_dma_txrxb(struct spi_device *spi, struct spi_transfer *t)
412 } 412 }
413 413
414 /* put buffers on the ring */ 414 /* put buffers on the ring */
415 res = au1xxx_dbdma_put_dest(hw->dma_rx_ch, hw->rx, 415 res = au1xxx_dbdma_put_dest(hw->dma_rx_ch, virt_to_phys(hw->rx),
416 t->len, DDMA_FLAGS_IE); 416 t->len, DDMA_FLAGS_IE);
417 if (!res) 417 if (!res)
418 dev_err(hw->dev, "rx dma put dest error\n"); 418 dev_err(hw->dev, "rx dma put dest error\n");
419 419
420 res = au1xxx_dbdma_put_source(hw->dma_tx_ch, (void *)hw->tx, 420 res = au1xxx_dbdma_put_source(hw->dma_tx_ch, virt_to_phys(hw->tx),
421 t->len, DDMA_FLAGS_IE); 421 t->len, DDMA_FLAGS_IE);
422 if (!res) 422 if (!res)
423 dev_err(hw->dev, "tx dma put source error\n"); 423 dev_err(hw->dev, "tx dma put source error\n");
ss="hl num">0, NULL); if (rc) DEV_MESSAGE(KERN_WARNING, device, "DIAG ERP unsuccessful, " "rc=%d", rc); } /* Start a given request at the device. Return zero on success, non-zero * otherwise. */ static int dasd_start_diag(struct dasd_ccw_req * cqr) { struct dasd_device *device; struct dasd_diag_private *private; struct dasd_diag_req *dreq; int rc; device = cqr->device; if (cqr->retries < 0) { DEV_MESSAGE(KERN_WARNING, device, "DIAG start_IO: request %p " "- no retry left)", cqr); cqr->status = DASD_CQR_FAILED; return -EIO; } private = (struct dasd_diag_private *) device->private; dreq = (struct dasd_diag_req *) cqr->data; private->iob.dev_nr = private->dev_id.devno; private->iob.key = 0; private->iob.flags = DASD_DIAG_RWFLAG_ASYNC; private->iob.block_count = dreq->block_count; private->iob.interrupt_params = (addr_t) cqr; private->iob.bio_list = dreq->bio; private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT; cqr->startclk = get_clock(); cqr->starttime = jiffies; cqr->retries--; rc = dia250(&private->iob, RW_BIO); switch (rc) { case 0: /* Synchronous I/O finished successfully */ cqr->stopclk = get_clock(); cqr->status = DASD_CQR_DONE; /* Indicate to calling function that only a dasd_schedule_bh() and no timer is needed */ rc = -EACCES; break; case 8: /* Asynchronous I/O was started */ cqr->status = DASD_CQR_IN_IO; rc = 0; break; default: /* Error condition */ cqr->status = DASD_CQR_QUEUED; DEV_MESSAGE(KERN_WARNING, device, "dia250 returned rc=%d", rc); dasd_diag_erp(device); rc = -EIO; break; } return rc; } /* Terminate given request at the device. */ static int dasd_diag_term_IO(struct dasd_ccw_req * cqr) { struct dasd_device *device; device = cqr->device; mdsk_term_io(device); mdsk_init_io(device, device->bp_block, 0, NULL); cqr->status = DASD_CQR_CLEAR; cqr->stopclk = get_clock(); dasd_schedule_bh(device); return 0; } /* Handle external interruption. */ static void dasd_ext_handler(__u16 code) { struct dasd_ccw_req *cqr, *next; struct dasd_device *device; unsigned long long expires; unsigned long flags; u8 int_code, status; addr_t ip; int rc; int_code = *((u8 *) DASD_DIAG_LC_INT_CODE); status = *((u8 *) DASD_DIAG_LC_INT_STATUS); switch (int_code) { case DASD_DIAG_CODE_31BIT: ip = (addr_t) *((u32 *) DASD_DIAG_LC_INT_PARM_31BIT); break; case DASD_DIAG_CODE_64BIT: ip = (addr_t) *((u64 *) DASD_DIAG_LC_INT_PARM_64BIT); break; default: return; } if (!ip) { /* no intparm: unsolicited interrupt */ MESSAGE(KERN_DEBUG, "%s", "caught unsolicited interrupt"); return; } cqr = (struct dasd_ccw_req *) ip; device = (struct dasd_device *) cqr->device; if (strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { DEV_MESSAGE(KERN_WARNING, device, " magic number of dasd_ccw_req 0x%08X doesn't" " match discipline 0x%08X", cqr->magic, *(int *) (&device->discipline->name)); return; } /* get irq lock to modify request queue */ spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); /* Check for a pending clear operation */ if (cqr->status == DASD_CQR_CLEAR) { cqr->status = DASD_CQR_QUEUED; dasd_clear_timer(device); dasd_schedule_bh(device); spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); return; } cqr->stopclk = get_clock(); expires = 0; if (status == 0) { cqr->status = DASD_CQR_DONE; /* Start first request on queue if possible -> fast_io. */ if (!list_empty(&device->ccw_queue)) { next = list_entry(device->ccw_queue.next, struct dasd_ccw_req, list); if (next->status == DASD_CQR_QUEUED) { rc = dasd_start_diag(next); if (rc == 0) expires = next->expires; else if (rc != -EACCES) DEV_MESSAGE(KERN_WARNING, device, "%s", "Interrupt fastpath " "failed!"); } } } else { cqr->status = DASD_CQR_QUEUED; DEV_MESSAGE(KERN_WARNING, device, "interrupt status for " "request %p was %d (%d retries left)", cqr, status, cqr->retries); dasd_diag_erp(device); } if (expires != 0) dasd_set_timer(device, expires); else dasd_clear_timer(device); dasd_schedule_bh(device); spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); } /* Check whether device can be controlled by DIAG discipline. Return zero on * success, non-zero otherwise. */ static int dasd_diag_check_device(struct dasd_device *device) { struct dasd_diag_private *private; struct dasd_diag_characteristics *rdc_data; struct dasd_diag_bio bio; struct vtoc_cms_label *label; blocknum_t end_block; unsigned int sb, bsize; int rc; private = (struct dasd_diag_private *) device->private; if (private == NULL) { private = kzalloc(sizeof(struct dasd_diag_private),GFP_KERNEL); if (private == NULL) { DEV_MESSAGE(KERN_WARNING, device, "%s", "memory allocation failed for private data"); return -ENOMEM; } ccw_device_get_id(device->cdev, &private->dev_id); device->private = (void *) private; } /* Read Device Characteristics */ rdc_data = (void *) &(private->rdc_data); rdc_data->dev_nr = private->dev_id.devno; rdc_data->rdc_len = sizeof (struct dasd_diag_characteristics); rc = diag210((struct diag210 *) rdc_data); if (rc) { DEV_MESSAGE(KERN_WARNING, device, "failed to retrieve device " "information (rc=%d)", rc); return -ENOTSUPP; } /* Figure out position of label block */ switch (private->rdc_data.vdev_class) { case DEV_CLASS_FBA: private->pt_block = 1; break; case DEV_CLASS_ECKD: private->pt_block = 2; break; default: DEV_MESSAGE(KERN_WARNING, device, "unsupported device class " "(class=%d)", private->rdc_data.vdev_class); return -ENOTSUPP; } DBF_DEV_EVENT(DBF_INFO, device, "%04X: %04X on real %04X/%02X", rdc_data->dev_nr, rdc_data->vdev_type, rdc_data->rdev_type, rdc_data->rdev_model); /* terminate all outstanding operations */ mdsk_term_io(device); /* figure out blocksize of device */ label = (struct vtoc_cms_label *) get_zeroed_page(GFP_KERNEL); if (label == NULL) { DEV_MESSAGE(KERN_WARNING, device, "%s", "No memory to allocate initialization request"); return -ENOMEM; } rc = 0; end_block = 0; /* try all sizes - needed for ECKD devices */ for (bsize = 512; bsize <= PAGE_SIZE; bsize <<= 1) { mdsk_init_io(device, bsize, 0, &end_block); memset(&bio, 0, sizeof (struct dasd_diag_bio)); bio.type = MDSK_READ_REQ; bio.block_number = private->pt_block + 1; bio.buffer = label; memset(&private->iob, 0, sizeof (struct dasd_diag_rw_io)); private->iob.dev_nr = rdc_data->dev_nr; private->iob.key = 0; private->iob.flags = 0; /* do synchronous io */ private->iob.block_count = 1; private->iob.interrupt_params = 0; private->iob.bio_list = &bio; private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT; rc = dia250(&private->iob, RW_BIO); if (rc == 3) { DEV_MESSAGE(KERN_WARNING, device, "%s", "DIAG call failed"); rc = -EOPNOTSUPP; goto out; } mdsk_term_io(device); if (rc == 0) break; } if (bsize > PAGE_SIZE) { DEV_MESSAGE(KERN_WARNING, device, "device access failed " "(rc=%d)", rc); rc = -EIO; goto out; } /* check for label block */ if (memcmp(label->label_id, DASD_DIAG_CMS1, sizeof(DASD_DIAG_CMS1)) == 0) { /* get formatted blocksize from label block */ bsize = (unsigned int) label->block_size; device->blocks = (unsigned long) label->block_count; } else device->blocks = end_block; device->bp_block = bsize; device->s2b_shift = 0; /* bits to shift 512 to get a block */ for (sb = 512; sb < bsize; sb = sb << 1) device->s2b_shift++; rc = mdsk_init_io(device, device->bp_block, 0, NULL); if (rc) { DEV_MESSAGE(KERN_WARNING, device, "DIAG initialization " "failed (rc=%d)", rc); rc = -EIO; } else { DEV_MESSAGE(KERN_INFO, device, "(%ld B/blk): %ldkB", (unsigned long) device->bp_block, (unsigned long) (device->blocks << device->s2b_shift) >> 1); } out: free_page((long) label); return rc; } /* Fill in virtual disk geometry for device. Return zero on success, non-zero * otherwise. */ static int dasd_diag_fill_geometry(struct dasd_device *device, struct hd_geometry *geo) { if (dasd_check_blocksize(device->bp_block) != 0) return -EINVAL; geo->cylinders = (device->blocks << device->s2b_shift) >> 10; geo->heads = 16; geo->sectors = 128 >> device->s2b_shift; return 0; } static dasd_era_t dasd_diag_examine_error(struct dasd_ccw_req * cqr, struct irb * stat) { return dasd_era_fatal; } static dasd_erp_fn_t dasd_diag_erp_action(struct dasd_ccw_req * cqr) { return dasd_default_erp_action; }