summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2003-04-21 18:34:12 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2003-04-21 18:34:12 -0700
commitdf42471d85d64d8f54eeb842ad079cfba7564a11 (patch)
tree2046ad2e0eed81640616151fc82163c5e71ae408
parentcacf648951e1833a362c38fb45243e988cee8e0f (diff)
parent2c8e5e76127d3fb3d6a435b234ed08836683f091 (diff)
Merge bk://kernel.bkbits.net/davem/sparc-2.5
into home.transmeta.com:/home/torvalds/v2.5/linux
-rw-r--r--drivers/block/ll_rw_blk.c6
-rw-r--r--drivers/block/umem.c89
-rw-r--r--fs/jfs/jfs_txnmgr.c15
-rw-r--r--include/linux/umem.h7
4 files changed, 91 insertions, 26 deletions
diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
index 74d8e2e0f8db..ad6e7b62e66f 100644
--- a/drivers/block/ll_rw_blk.c
+++ b/drivers/block/ll_rw_blk.c
@@ -2164,8 +2164,7 @@ int end_that_request_chunk(struct request *req, int uptodate, int nr_bytes)
void end_that_request_last(struct request *req)
{
struct gendisk *disk = req->rq_disk;
- if (req->waiting)
- complete(req->waiting);
+ struct completion *waiting = req->waiting;
if (disk) {
unsigned long duration = jiffies - req->start_time;
@@ -2183,6 +2182,9 @@ void end_that_request_last(struct request *req)
disk_stat_dec(disk, in_flight);
}
__blk_put_request(req->q, req);
+ /* Do this LAST! The structure may be freed immediately afterwards */
+ if (waiting)
+ complete(waiting);
}
int __init blk_dev_init(void)
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index edb915b60ceb..ddfe3bb53b32 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -149,6 +149,7 @@ struct cardinfo {
spinlock_t lock;
int check_batteries;
+ int flags;
};
static struct cardinfo cards[MM_MAXCARDS];
@@ -573,7 +574,7 @@ static int mm_make_request(request_queue_t *q, struct bio *bio)
-- mm_interrupt
-----------------------------------------------------------------------------------
*/
-static void mm_interrupt(int irq, void *__card, struct pt_regs *regs)
+static irqreturn_t mm_interrupt(int irq, void *__card, struct pt_regs *regs)
{
struct cardinfo *card = (struct cardinfo *) __card;
unsigned int dma_status;
@@ -585,13 +586,16 @@ HW_TRACE(0x30);
if (!(dma_status & (DMASCR_ERROR_MASK | DMASCR_CHAIN_COMPLETE))) {
/* interrupt wasn't for me ... */
- return;
+ return IRQ_NONE;
}
/* clear COMPLETION interrupts */
- writel(cpu_to_le32(DMASCR_DMA_COMPLETE|DMASCR_CHAIN_COMPLETE),
- card->csr_remap+ DMA_STATUS_CTRL);
-
+ if (card->flags & UM_FLAG_NO_BYTE_STATUS)
+ writel(cpu_to_le32(DMASCR_DMA_COMPLETE|DMASCR_CHAIN_COMPLETE),
+ card->csr_remap+ DMA_STATUS_CTRL);
+ else
+ writeb((DMASCR_DMA_COMPLETE|DMASCR_CHAIN_COMPLETE) >> 16,
+ card->csr_remap+ DMA_STATUS_CTRL + 2);
/* log errors and clear interrupt status */
if (dma_status & DMASCR_ANY_ERR) {
@@ -663,6 +667,7 @@ HW_TRACE(0x30);
HW_TRACE(0x36);
+ return IRQ_HANDLED;
}
/*
-----------------------------------------------------------------------------------
@@ -755,15 +760,16 @@ static void check_all_batteries(unsigned long ptr)
{
int i;
- for (i = 0; i < num_cards; i++) {
- struct cardinfo *card = &cards[i];
- spin_lock_bh(&card->lock);
- if (card->Active >= 0)
- card->check_batteries = 1;
- else
- check_batteries(card);
- spin_unlock_bh(&card->lock);
- }
+ for (i = 0; i < num_cards; i++)
+ if (!(cards[i].flags & UM_FLAG_NO_BATT)) {
+ struct cardinfo *card = &cards[i];
+ spin_lock_bh(&card->lock);
+ if (card->Active >= 0)
+ card->check_batteries = 1;
+ else
+ check_batteries(card);
+ spin_unlock_bh(&card->lock);
+ }
init_battery_timer();
}
@@ -869,6 +875,7 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i
unsigned char mem_present;
unsigned char batt_status;
unsigned int saved_bar, data;
+ int magic_number;
if (pci_enable_device(dev) < 0)
return -ENODEV;
@@ -933,12 +940,33 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i
printk(KERN_INFO "MM%d: MEM area not remapped (CONFIG_MM_MAP_MEMORY not set)\n",
card->card_number);
#endif
- if (readb(card->csr_remap + MEMCTRLSTATUS_MAGIC) != MM_MAGIC_VALUE) {
+ switch(card->dev->device) {
+ case 0x5415:
+ card->flags |= UM_FLAG_NO_BYTE_STATUS | UM_FLAG_NO_BATTREG;
+ magic_number = 0x59;
+ break;
+
+ case 0x5425:
+ card->flags |= UM_FLAG_NO_BYTE_STATUS;
+ magic_number = 0x5C;
+ break;
+
+ case 0x6155:
+ card->flags |= UM_FLAG_NO_BYTE_STATUS | UM_FLAG_NO_BATTREG | UM_FLAG_NO_BATT;
+ magic_number = 0x99;
+ break;
+
+ default:
+ magic_number = 0x100;
+ break;
+ }
+
+ if (readb(card->csr_remap + MEMCTRLSTATUS_MAGIC) != magic_number) {
printk(KERN_ERR "MM%d: Magic number invalid\n", card->card_number);
ret = -ENOMEM;
-
goto failed_magic;
}
+
card->mm_pages[0].desc = pci_alloc_consistent(card->dev,
PAGE_SIZE*2,
&card->mm_pages[0].page_dma);
@@ -997,14 +1025,19 @@ static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_i
card->battery[1].good = !(batt_status & BATTERY_2_FAILURE);
card->battery[0].last_change = card->battery[1].last_change = jiffies;
- printk(KERN_INFO "MM%d: Size %d KB, Battery 1 %s (%s), Battery 2 %s (%s)\n",
- card->card_number, card->mm_size,
- (batt_status & BATTERY_1_DISABLED ? "Disabled" : "Enabled"),
- card->battery[0].good ? "OK" : "FAILURE",
- (batt_status & BATTERY_2_DISABLED ? "Disabled" : "Enabled"),
- card->battery[1].good ? "OK" : "FAILURE");
+ if (card->flags & UM_FLAG_NO_BATT)
+ printk(KERN_INFO "MM%d: Size %d KB\n",
+ card->card_number, card->mm_size);
+ else {
+ printk(KERN_INFO "MM%d: Size %d KB, Battery 1 %s (%s), Battery 2 %s (%s)\n",
+ card->card_number, card->mm_size,
+ (batt_status & BATTERY_1_DISABLED ? "Disabled" : "Enabled"),
+ card->battery[0].good ? "OK" : "FAILURE",
+ (batt_status & BATTERY_2_DISABLED ? "Disabled" : "Enabled"),
+ card->battery[1].good ? "OK" : "FAILURE");
- set_fault_to_battery_status(card);
+ set_fault_to_battery_status(card);
+ }
pci_read_config_dword(dev, PCI_BASE_ADDRESS_1, &saved_bar);
data = 0xffffffff;
@@ -1117,6 +1150,16 @@ static const struct pci_device_id __devinitdata mm_pci_ids[] = { {
}, {
.vendor = PCI_VENDOR_ID_MICRO_MEMORY,
.device = PCI_DEVICE_ID_MICRO_MEMORY_5425CN,
+ }, {
+ .vendor = PCI_VENDOR_ID_MICRO_MEMORY,
+ .device = PCI_DEVICE_ID_MICRO_MEMORY_6155,
+ }, {
+ .vendor = 0x8086,
+ .device = 0xB555,
+ .subvendor= 0x1332,
+ .subdevice= 0x5460,
+ .class = 0x050000,
+ .class_mask= 0,
}, { /* end: all zeroes */ }
};
diff --git a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
index 5d013b2d6d25..d7740cc3fb37 100644
--- a/fs/jfs/jfs_txnmgr.c
+++ b/fs/jfs/jfs_txnmgr.c
@@ -1240,8 +1240,21 @@ int txCommit(tid_t tid, /* transaction identifier */
* Ensure that inode isn't reused before
* lazy commit thread finishes processing
*/
- if (tblk->xflag & (COMMIT_CREATE | COMMIT_DELETE))
+ if (tblk->xflag & (COMMIT_CREATE | COMMIT_DELETE)) {
atomic_inc(&tblk->ip->i_count);
+ /*
+ * Avoid a rare deadlock
+ *
+ * If the inode is locked, we may be blocked in
+ * jfs_commit_inode. If so, we don't want the
+ * lazy_commit thread doing the last iput() on the inode
+ * since that may block on the locked inode. Instead,
+ * commit the transaction synchronously, so the last iput
+ * will be done by the calling thread (or later)
+ */
+ if (tblk->ip->i_state & I_LOCK)
+ tblk->xflag &= ~COMMIT_LAZY;
+ }
ASSERT((!(tblk->xflag & COMMIT_DELETE)) ||
((tblk->ip->i_nlink == 0) &&
diff --git a/include/linux/umem.h b/include/linux/umem.h
index d6e89299de31..2eb1f55644cc 100644
--- a/include/linux/umem.h
+++ b/include/linux/umem.h
@@ -128,4 +128,11 @@ struct mm_dma_desc {
#define PCI_VENDOR_ID_MICRO_MEMORY 0x1332
#define PCI_DEVICE_ID_MICRO_MEMORY_5415CN 0x5415
#define PCI_DEVICE_ID_MICRO_MEMORY_5425CN 0x5425
+#define PCI_DEVICE_ID_MICRO_MEMORY_6155 0x6155
+
+/* bits for card->flags */
+#define UM_FLAG_DMA_IN_REGS 1
+#define UM_FLAG_NO_BYTE_STATUS 2
+#define UM_FLAG_NO_BATTREG 4
+#define UM_FLAG_NO_BATT 8
#endif