Merge branch 'master'
authorJeff Garzik <jgarzik@pobox.com>
Sat, 24 Dec 2005 14:28:21 +0000 (09:28 -0500)
committerJeff Garzik <jgarzik@pobox.com>
Sat, 24 Dec 2005 14:28:21 +0000 (09:28 -0500)
Makefile
drivers/char/drm/radeon_cp.c
drivers/ieee1394/hosts.h
drivers/ieee1394/nodemgr.c
drivers/mtd/onenand/generic.c
drivers/mtd/onenand/onenand_base.c
drivers/mtd/onenand/onenand_bbt.c
include/linux/mtd/onenand.h

index ad457e1bd0d25707febd5f6f53934357c86d1326..f4218b5db827cc28f29d4aac842dac360a0d436d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 15
-EXTRAVERSION =-rc5
-NAME=Affluent Albatross
+EXTRAVERSION =-rc6
+NAME=Sliding Snow Leopard
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
index 95ae9e0892ac32d5c0aafd7c7fca1062c8b2508f..501e557cbc868f6feba2210cc16de25131b6c087 100644 (file)
@@ -1311,7 +1311,7 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
 
 static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init)
 {
-       drm_radeon_private_t *dev_priv = dev->dev_private;;
+       drm_radeon_private_t *dev_priv = dev->dev_private;
        unsigned int mem_size;
 
        DRM_DEBUG("\n");
index 38f42112dff0f8b48782e038b10db69bb1241a84..ae9b02cc013fe252d4c109c2b85dec1c1677cf0d 100644 (file)
@@ -41,6 +41,7 @@ struct hpsb_host {
         /* this nodes state */
         unsigned in_bus_reset:1;
         unsigned is_shutdown:1;
+       unsigned resume_packet_sent:1;
 
         /* this nodes' duties on the bus */
         unsigned is_root:1;
index 7fff5a1d2ea4c7abc8713df31f2222a5cfb6c4b2..0ea37b1bccb27c13d1ae81392fad02c48dbd8923 100644 (file)
@@ -1349,6 +1349,33 @@ static void nodemgr_update_pdrv(struct node_entry *ne)
 }
 
 
+/* Write the BROADCAST_CHANNEL as per IEEE1394a 8.3.2.3.11 and 8.4.2.3.  This
+ * seems like an optional service but in the end it is practically mandatory
+ * as a consequence of these clauses.
+ *
+ * Note that we cannot do a broadcast write to all nodes at once because some
+ * pre-1394a devices would hang. */
+static void nodemgr_irm_write_bc(struct node_entry *ne, int generation)
+{
+       const u64 bc_addr = (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL);
+       quadlet_t bc_remote, bc_local;
+       int ret;
+
+       if (!ne->host->is_irm || ne->generation != generation ||
+           ne->nodeid == ne->host->node_id)
+               return;
+
+       bc_local = cpu_to_be32(ne->host->csr.broadcast_channel);
+
+       /* Check if the register is implemented and 1394a compliant. */
+       ret = hpsb_read(ne->host, ne->nodeid, generation, bc_addr, &bc_remote,
+                       sizeof(bc_remote));
+       if (!ret && bc_remote & cpu_to_be32(0x80000000) &&
+           bc_remote != bc_local)
+               hpsb_node_write(ne, bc_addr, &bc_local, sizeof(bc_local));
+}
+
+
 static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int generation)
 {
        struct device *dev;
@@ -1360,6 +1387,8 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge
        if (!dev)
                return;
 
+       nodemgr_irm_write_bc(ne, generation);
+
        /* If "needs_probe", then this is either a new or changed node we
         * rescan totally. If the generation matches for an existing node
         * (one that existed prior to the bus reset) we send update calls
@@ -1413,9 +1442,25 @@ static void nodemgr_node_probe(struct host_info *hi, int generation)
        return;
 }
 
-/* Because we are a 1394a-2000 compliant IRM, we need to inform all the other
- * nodes of the broadcast channel.  (Really we're only setting the validity
- * bit). Other IRM responsibilities go in here as well. */
+static int nodemgr_send_resume_packet(struct hpsb_host *host)
+{
+       struct hpsb_packet *packet;
+       int ret = 1;
+
+       packet = hpsb_make_phypacket(host,
+                       0x003c0000 | NODEID_TO_NODE(host->node_id) << 24);
+       if (packet) {
+               packet->no_waiter = 1;
+               packet->generation = get_hpsb_generation(host);
+               ret = hpsb_send_packet(packet);
+       }
+       if (ret)
+               HPSB_WARN("fw-host%d: Failed to broadcast resume packet",
+                         host->id);
+       return ret;
+}
+
+/* Perform a few high-level IRM responsibilities. */
 static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles)
 {
        quadlet_t bc;
@@ -1424,13 +1469,8 @@ static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles)
        if (!host->is_irm || host->irm_id == (nodeid_t)-1)
                return 1;
 
-       host->csr.broadcast_channel |= 0x40000000;  /* set validity bit */
-
-       bc = cpu_to_be32(host->csr.broadcast_channel);
-
-       hpsb_write(host, LOCAL_BUS | ALL_NODES, get_hpsb_generation(host),
-                  (CSR_REGISTER_BASE | CSR_BROADCAST_CHANNEL),
-                  &bc, sizeof(quadlet_t));
+       /* We are a 1394a-2000 compliant IRM. Set the validity bit. */
+       host->csr.broadcast_channel |= 0x40000000;
 
        /* If there is no bus manager then we should set the root node's
         * force_root bit to promote bus stability per the 1394
@@ -1463,6 +1503,13 @@ static int nodemgr_do_irm_duties(struct hpsb_host *host, int cycles)
                }
        }
 
+       /* Some devices suspend their ports while being connected to an inactive
+        * host adapter, i.e. if connected before the low-level driver is
+        * loaded.  They become visible either when physically unplugged and
+        * replugged, or when receiving a resume packet.  Send one once. */
+       if (!host->resume_packet_sent && !nodemgr_send_resume_packet(host))
+               host->resume_packet_sent = 1;
+
        return 1;
 }
 
index 48cce431f89f3ebe498fc8673ee69606c5017848..45c077d0f0630289f9763e35beeccf11ca285cc4 100644 (file)
@@ -12,9 +12,9 @@
  *   This is a device driver for the OneNAND flash for generic boards.
  */
 
-#include <linux/device.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/onenand.h>
 #include <linux/mtd/partitions.h>
@@ -39,7 +39,7 @@ static int __devinit generic_onenand_probe(struct device *dev)
 {
        struct onenand_info *info;
        struct platform_device *pdev = to_platform_device(dev);
-       struct onenand_platform_data *pdata = pdev->dev.platform_data;
+       struct flash_platform_data *pdata = pdev->dev.platform_data;
        struct resource *res = pdev->resource;
        unsigned long size = res->end - res->start + 1;
        int err;
index f67d5d6eb9a68aa1f290b4e580429c13017cd5c1..a53a73fc2a5af0d0a07a8f880793e2b8c37c4489 100644 (file)
@@ -940,7 +940,7 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
        u_char *eccbuf, struct nand_oobinfo *oobsel)
 {
        struct onenand_chip *this = mtd->priv;
-       unsigned char buffer[MAX_ONENAND_PAGESIZE], *pbuf;
+       unsigned char *pbuf;
        size_t total_len, len;
        int i, written = 0;
        int ret = 0;
@@ -975,7 +975,7 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
        /* Loop until all keve's data has been written */
        len = 0;
        while (count) {
-               pbuf = buffer;
+               pbuf = this->page_buf;
                /*
                 * If the given tuple is >= pagesize then
                 * write it out from the iov
@@ -995,7 +995,7 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
                        int cnt = 0, thislen;
                        while (cnt < mtd->oobblock) {
                                thislen = min_t(int, mtd->oobblock - cnt, vecs->iov_len - len);
-                               memcpy(buffer + cnt, vecs->iov_base + len, thislen);
+                               memcpy(this->page_buf + cnt, vecs->iov_base + len, thislen);
                                cnt += thislen;
                                len += thislen;
 
@@ -1296,6 +1296,12 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
 
        /* Block lock scheme */
        for (block = start; block < end; block++) {
+               /* Set block address */
+               value = onenand_block_address(this, block);
+               this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
+               /* Select DataRAM for DDP */
+               value = onenand_bufferram_address(this, block);
+               this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2);
                /* Set start block address */
                this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS);
                /* Write unlock command */
@@ -1309,10 +1315,6 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
                    & ONENAND_CTRL_ONGO)
                        continue;
 
-               /* Set block address for read block status */
-               value = onenand_block_address(this, block);
-               this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1);
-
                /* Check lock status */
                status = this->read_word(this->base + ONENAND_REG_WP_STATUS);
                if (!(status & ONENAND_WP_US))
@@ -1346,7 +1348,6 @@ static void onenand_print_device_info(int device)
 
 static const struct onenand_manufacturers onenand_manuf_ids[] = {
         {ONENAND_MFR_SAMSUNG, "Samsung"},
-        {ONENAND_MFR_UNKNOWN, "Unknown"}
 };
 
 /**
@@ -1357,17 +1358,22 @@ static const struct onenand_manufacturers onenand_manuf_ids[] = {
  */
 static int onenand_check_maf(int manuf)
 {
+       int size = ARRAY_SIZE(onenand_manuf_ids);
+       char *name;
         int i;
 
-        for (i = 0; onenand_manuf_ids[i].id; i++) {
+       for (i = 0; i < size; i++)
                 if (manuf == onenand_manuf_ids[i].id)
                         break;
-        }
 
-        printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n",
-                onenand_manuf_ids[i].name, manuf);
+       if (i < size)
+               name = onenand_manuf_ids[i].name;
+       else
+               name = "Unknown";
+
+       printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n", name, manuf);
 
-        return (i != ONENAND_MFR_UNKNOWN);
+       return (i == size);
 }
 
 /**
@@ -1513,6 +1519,18 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
                this->read_bufferram = onenand_sync_read_bufferram;
        }
 
+       /* Allocate buffers, if necessary */
+       if (!this->page_buf) {
+               size_t len;
+               len = mtd->oobblock + mtd->oobsize;
+               this->page_buf = kmalloc(len, GFP_KERNEL);
+               if (!this->page_buf) {
+                       printk(KERN_ERR "onenand_scan(): Can't allocate page_buf\n");
+                       return -ENOMEM;
+               }
+               this->options |= ONENAND_PAGEBUF_ALLOC;
+       }
+
        this->state = FL_READY;
        init_waitqueue_head(&this->wq);
        spin_lock_init(&this->chip_lock);
@@ -1574,12 +1592,21 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
  */
 void onenand_release(struct mtd_info *mtd)
 {
+       struct onenand_chip *this = mtd->priv;
+
 #ifdef CONFIG_MTD_PARTITIONS
        /* Deregister partitions */
        del_mtd_partitions (mtd);
 #endif
        /* Deregister the device */
        del_mtd_device (mtd);
+
+       /* Free bad block table memory, if allocated */
+       if (this->bbm)
+               kfree(this->bbm);
+       /* Buffer allocated by onenand_scan */
+       if (this->options & ONENAND_PAGEBUF_ALLOC)
+               kfree(this->page_buf);
 }
 
 EXPORT_SYMBOL_GPL(onenand_scan);
index f40190f499e120416f9ba795a210ad357d8ad203..4510d3361eaa82f77ddca510bb4fa460a26cb3f1 100644 (file)
@@ -118,10 +118,10 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
  */
 static inline int onenand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
-       unsigned char data_buf[MAX_ONENAND_PAGESIZE];
+       struct onenand_chip *this = mtd->priv;
 
         bd->options &= ~NAND_BBT_SCANEMPTY;
-        return create_bbt(mtd, data_buf, bd, -1);
+       return create_bbt(mtd, this->page_buf, bd, -1);
 }
 
 /**
index f1fd4215686acc2b7655c6a5e63f974115c3ff78..7419b5fab1337a8f55899f219e2d297faef5a064 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/mtd/bbm.h>
 
 #define MAX_BUFFERRAM          2
-#define MAX_ONENAND_PAGESIZE   (2048 + 64)
 
 /* Scan and identify a OneNAND device */
 extern int onenand_scan(struct mtd_info *mtd, int max_chips);
@@ -110,6 +109,7 @@ struct onenand_chip {
        spinlock_t              chip_lock;
        wait_queue_head_t       wq;
        onenand_state_t         state;
+       unsigned char           *page_buf;
 
        struct nand_oobinfo     *autooob;
 
@@ -134,13 +134,12 @@ struct onenand_chip {
  * Options bits
  */
 #define ONENAND_CONT_LOCK              (0x0001)
-
+#define ONENAND_PAGEBUF_ALLOC          (0x1000)
 
 /*
  * OneNAND Flash Manufacturer ID Codes
  */
 #define ONENAND_MFR_SAMSUNG    0xec
-#define ONENAND_MFR_UNKNOWN    0x00
 
 /**
  * struct nand_manufacturers - NAND Flash Manufacturer ID Structure