Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 75053
b: refs/heads/master
c: 3c615e1
h: refs/heads/master
i:
  75051: 4283801
v: v3
  • Loading branch information
Linus Torvalds committed Dec 18, 2007
1 parent cebdf0d commit f822da5
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 26 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 458cf5e9b666c251b04cb5242fb19fd5114645ba
refs/heads/master: 3c615e19a4c518e349cc81a7f43223c7ec5f9e9a
63 changes: 58 additions & 5 deletions trunk/drivers/mmc/host/sdhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* Thanks to the following companies for their support:
*
* - JMicron (hardware and technical support)
*/

#include <linux/delay.h>
Expand All @@ -26,13 +30,29 @@

static unsigned int debug_quirks = 0;

/*
* Different quirks to handle when the hardware deviates from a strict
* interpretation of the SDHCI specification.
*/

/* Controller doesn't honor resets unless we touch the clock register */
#define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0)
/* Controller has bad caps bits, but really supports DMA */
#define SDHCI_QUIRK_FORCE_DMA (1<<1)
/* Controller doesn't like some resets when there is no card inserted. */
#define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2)
/* Controller doesn't like clearing the power reg before a change */
#define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3)
/* Controller has flaky internal state so reset it on each ios change */
#define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS (1<<4)
/* Controller has an unusable DMA engine */
#define SDHCI_QUIRK_BROKEN_DMA (1<<5)
/* Controller can only DMA from 32-bit aligned addresses */
#define SDHCI_QUIRK_32BIT_DMA_ADDR (1<<6)
/* Controller can only DMA chunk sizes that are a multiple of 32 bits */
#define SDHCI_QUIRK_32BIT_DMA_SIZE (1<<7)
/* Controller needs to be reset after each request to stay stable */
#define SDHCI_QUIRK_RESET_AFTER_REQUEST (1<<8)

static const struct pci_device_id pci_ids[] __devinitdata = {
{
Expand Down Expand Up @@ -97,6 +117,16 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS,
},

{
.vendor = PCI_VENDOR_ID_JMICRON,
.device = PCI_DEVICE_ID_JMICRON_JMB38X_SD,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
.driver_data = SDHCI_QUIRK_32BIT_DMA_ADDR |
SDHCI_QUIRK_32BIT_DMA_SIZE |
SDHCI_QUIRK_RESET_AFTER_REQUEST,
},

{ /* Generic SD host controller */
PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
},
Expand Down Expand Up @@ -419,7 +449,29 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)

writeb(count, host->ioaddr + SDHCI_TIMEOUT_CONTROL);

if (host->flags & SDHCI_USE_DMA) {
if (host->flags & SDHCI_USE_DMA)
host->flags |= SDHCI_REQ_USE_DMA;

if (unlikely((host->flags & SDHCI_REQ_USE_DMA) &&
(host->chip->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) &&
((data->blksz * data->blocks) & 0x3))) {
DBG("Reverting to PIO because of transfer size (%d)\n",
data->blksz * data->blocks);
host->flags &= ~SDHCI_REQ_USE_DMA;
}

/*
* The assumption here being that alignment is the same after
* translation to device address space.
*/
if (unlikely((host->flags & SDHCI_REQ_USE_DMA) &&
(host->chip->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) &&
(data->sg->offset & 0x3))) {
DBG("Reverting to PIO because of bad alignment\n");
host->flags &= ~SDHCI_REQ_USE_DMA;
}

if (host->flags & SDHCI_REQ_USE_DMA) {
int count;

count = pci_map_sg(host->chip->pdev, data->sg, data->sg_len,
Expand Down Expand Up @@ -456,7 +508,7 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,
mode |= SDHCI_TRNS_MULTI;
if (data->flags & MMC_DATA_READ)
mode |= SDHCI_TRNS_READ;
if (host->flags & SDHCI_USE_DMA)
if (host->flags & SDHCI_REQ_USE_DMA)
mode |= SDHCI_TRNS_DMA;

writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE);
Expand All @@ -472,7 +524,7 @@ static void sdhci_finish_data(struct sdhci_host *host)
data = host->data;
host->data = NULL;

if (host->flags & SDHCI_USE_DMA) {
if (host->flags & SDHCI_REQ_USE_DMA) {
pci_unmap_sg(host->chip->pdev, data->sg, data->sg_len,
(data->flags & MMC_DATA_READ)?PCI_DMA_FROMDEVICE:PCI_DMA_TODEVICE);
}
Expand Down Expand Up @@ -886,7 +938,8 @@ static void sdhci_tasklet_finish(unsigned long param)
*/
if (mrq->cmd->error ||
(mrq->data && (mrq->data->error ||
(mrq->data->stop && mrq->data->stop->error)))) {
(mrq->data->stop && mrq->data->stop->error))) ||
(host->chip->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)) {

/* Some controllers need this kick or reset won't work here */
if (host->chip->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) {
Expand Down Expand Up @@ -1284,7 +1337,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)

version = readw(host->ioaddr + SDHCI_HOST_VERSION);
version = (version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT;
if (version != 0) {
if (version > 1) {
printk(KERN_ERR "%s: Unknown controller version (%d). "
"You may experience problems.\n", host->slot_descr,
version);
Expand Down
3 changes: 2 additions & 1 deletion trunk/drivers/mmc/host/sdhci.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ struct sdhci_host {
spinlock_t lock; /* Mutex */

int flags; /* Host attributes */
#define SDHCI_USE_DMA (1<<0)
#define SDHCI_USE_DMA (1<<0) /* Host is DMA capable */
#define SDHCI_REQ_USE_DMA (1<<1) /* Use DMA for this req. */

unsigned int max_clk; /* Max possible freq (MHz) */
unsigned int timeout_clk; /* Timeout freq (KHz) */
Expand Down
4 changes: 2 additions & 2 deletions trunk/fs/xfs/linux-2.6/xfs_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -356,13 +356,13 @@ xfs_file_readdir(

reclen = sizeof(struct hack_dirent) + de->namlen;
size -= reclen;
curr_offset = de->offset /* & 0x7fffffff */;
de = (struct hack_dirent *)((char *)de + reclen);
curr_offset = de->offset /* & 0x7fffffff */;
}
}

done:
if (!error) {
if (!error) {
if (size == 0)
filp->f_pos = offset & 0x7fffffff;
else if (de)
Expand Down
6 changes: 2 additions & 4 deletions trunk/fs/xfs/xfs_dir2_block.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ xfs_dir2_block_getdents(
continue;

cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
ptr - (char *)block);
(char *)dep - (char *)block);
ino = be64_to_cpu(dep->inumber);
#if XFS_BIG_INUMS
ino += mp->m_inoadd;
Expand All @@ -519,9 +519,7 @@ xfs_dir2_block_getdents(
*/
if (filldir(dirent, dep->name, dep->namelen, cook,
ino, DT_UNKNOWN)) {
*offset = xfs_dir2_db_off_to_dataptr(mp,
mp->m_dirdatablk,
(char *)dep - (char *)block);
*offset = cook;
xfs_da_brelse(NULL, bp);
return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/xfs/xfs_dir2_leaf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1091,7 +1091,7 @@ xfs_dir2_leaf_getdents(
* Won't fit. Return to caller.
*/
if (filldir(dirent, dep->name, dep->namelen,
xfs_dir2_byte_to_dataptr(mp, curoff + length),
xfs_dir2_byte_to_dataptr(mp, curoff),
ino, DT_UNKNOWN))
break;

Expand Down
9 changes: 3 additions & 6 deletions trunk/fs/xfs/xfs_dir2_sf.c
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ xfs_dir2_sf_getdents(
#if XFS_BIG_INUMS
ino += mp->m_inoadd;
#endif
if (filldir(dirent, ".", 1, dotdot_offset, ino, DT_DIR)) {
if (filldir(dirent, ".", 1, dot_offset, ino, DT_DIR)) {
*offset = dot_offset;
return 0;
}
Expand All @@ -762,13 +762,11 @@ xfs_dir2_sf_getdents(
* Put .. entry unless we're starting past it.
*/
if (*offset <= dotdot_offset) {
off = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk,
XFS_DIR2_DATA_FIRST_OFFSET);
ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent);
#if XFS_BIG_INUMS
ino += mp->m_inoadd;
#endif
if (filldir(dirent, "..", 2, off, ino, DT_DIR)) {
if (filldir(dirent, "..", 2, dotdot_offset, ino, DT_DIR)) {
*offset = dotdot_offset;
return 0;
}
Expand All @@ -793,8 +791,7 @@ xfs_dir2_sf_getdents(
#endif

if (filldir(dirent, sfep->name, sfep->namelen,
off + xfs_dir2_data_entsize(sfep->namelen),
ino, DT_UNKNOWN)) {
off, ino, DT_UNKNOWN)) {
*offset = off;
return 0;
}
Expand Down
6 changes: 4 additions & 2 deletions trunk/fs/xfs/xfs_inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1459,8 +1459,10 @@ xfs_itruncate_start(
mp = ip->i_mount;
vp = XFS_ITOV(ip);

vn_iowait(ip); /* wait for the completion of any pending DIOs */

/* wait for the completion of any pending DIOs */
if (new_size < ip->i_size)
vn_iowait(ip);

/*
* Call toss_pages or flushinval_pages to get rid of pages
* overlapping the region being removed. We have to use
Expand Down
4 changes: 0 additions & 4 deletions trunk/include/linux/mmc/host.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,6 @@ struct mmc_host {
unsigned int removed:1; /* host is being removed */
#endif

unsigned int mode; /* current card mode of host */
#define MMC_MODE_MMC 0
#define MMC_MODE_SD 1

struct mmc_card *card; /* device attached to this host */

wait_queue_head_t wq;
Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/pci_ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -2148,6 +2148,7 @@
#define PCI_DEVICE_ID_JMICRON_JMB365 0x2365
#define PCI_DEVICE_ID_JMICRON_JMB366 0x2366
#define PCI_DEVICE_ID_JMICRON_JMB368 0x2368
#define PCI_DEVICE_ID_JMICRON_JMB38X_SD 0x2381

#define PCI_VENDOR_ID_KORENIX 0x1982
#define PCI_DEVICE_ID_KORENIX_JETCARDF0 0x1600
Expand Down

0 comments on commit f822da5

Please sign in to comment.