acer-wmi: Unmark as 'experimental'
[safe/jmp/linux-2.6] / drivers / block / sx8.c
index 9251f41..a18e1ca 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/spinlock.h>
 #include <linux/blkdev.h>
 #include <linux/sched.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/interrupt.h>
 #include <linux/compiler.h>
 #include <linux/workqueue.h>
@@ -27,8 +26,9 @@
 #include <linux/time.h>
 #include <linux/hdreg.h>
 #include <linux/dma-mapping.h>
+#include <linux/completion.h>
+#include <linux/scatterlist.h>
 #include <asm/io.h>
-#include <asm/semaphore.h>
 #include <asm/uaccess.h>
 
 #if 0
@@ -79,9 +79,9 @@ MODULE_PARM_DESC(max_queue, "Maximum number of queued commands. (min==1, max==30
 
 /* note: prints function name for you */
 #ifdef CARM_DEBUG
-#define DPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
+#define DPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)
 #ifdef CARM_VERBOSE_DEBUG
-#define VPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __FUNCTION__, ## args)
+#define VPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)
 #else
 #define VPRINTK(fmt, args...)
 #endif /* CARM_VERBOSE_DEBUG */
@@ -96,7 +96,7 @@ MODULE_PARM_DESC(max_queue, "Maximum number of queued commands. (min==1, max==30
 #define assert(expr) \
         if(unlikely(!(expr))) {                                   \
         printk(KERN_ERR "Assertion failed! %s,%s,%s,line=%d\n", \
-        #expr,__FILE__,__FUNCTION__,__LINE__);          \
+       #expr, __FILE__, __func__, __LINE__);          \
         }
 #endif
 
@@ -279,7 +279,7 @@ struct carm_host {
        unsigned int                    state;
        u32                             fw_ver;
 
-       request_queue_t                 *oob_q;
+       struct request_queue            *oob_q;
        unsigned int                    n_oob;
 
        unsigned int                    hw_sg_used;
@@ -288,7 +288,7 @@ struct carm_host {
 
        unsigned int                    wait_q_prod;
        unsigned int                    wait_q_cons;
-       request_queue_t                 *wait_q[CARM_MAX_WAIT_Q];
+       struct request_queue            *wait_q[CARM_MAX_WAIT_Q];
 
        unsigned int                    n_msgs;
        u64                             msg_alloc;
@@ -303,7 +303,7 @@ struct carm_host {
 
        struct work_struct              fsm_task;
 
-       struct semaphore                probe_sem;
+       struct completion               probe_comp;
 };
 
 struct carm_response {
@@ -407,8 +407,7 @@ struct carm_array_info {
 
 static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
 static void carm_remove_one (struct pci_dev *pdev);
-static int carm_bdev_ioctl(struct inode *ino, struct file *fil,
-                          unsigned int cmd, unsigned long arg);
+static int carm_bdev_getgeo(struct block_device *bdev, struct hd_geometry *geo);
 
 static struct pci_device_id carm_pci_tbl[] = {
        { PCI_VENDOR_ID_PROMISE, 0x8000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
@@ -426,7 +425,7 @@ static struct pci_driver carm_driver = {
 
 static struct block_device_operations carm_bd_ops = {
        .owner          = THIS_MODULE,
-       .ioctl          = carm_bdev_ioctl,
+       .getgeo         = carm_bdev_getgeo,
 };
 
 static unsigned int carm_host_id;
@@ -434,32 +433,14 @@ static unsigned long carm_major_alloc;
 
 
 
-static int carm_bdev_ioctl(struct inode *ino, struct file *fil,
-                          unsigned int cmd, unsigned long arg)
+static int carm_bdev_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-       void __user *usermem = (void __user *) arg;
-       struct carm_port *port = ino->i_bdev->bd_disk->private_data;
-       struct hd_geometry geom;
+       struct carm_port *port = bdev->bd_disk->private_data;
 
-       switch (cmd) {
-       case HDIO_GETGEO:
-               if (!usermem)
-                       return -EINVAL;
-
-               geom.heads = (u8) port->dev_geom_head;
-               geom.sectors = (u8) port->dev_geom_sect;
-               geom.cylinders = port->dev_geom_cyl;
-               geom.start = get_start_sect(ino->i_bdev);
-
-               if (copy_to_user(usermem, &geom, sizeof(geom)))
-                       return -EFAULT;
-               return 0;
-
-       default:
-               break;
-       }
-
-       return -EOPNOTSUPP;
+       geo->heads = (u8) port->dev_geom_head;
+       geo->sectors = (u8) port->dev_geom_sect;
+       geo->cylinders = port->dev_geom_cyl;
+       return 0;
 }
 
 static const u32 msg_sizes[] = { 32, 64, 128, CARM_MSG_SIZE };
@@ -542,6 +523,7 @@ static struct carm_request *carm_get_request(struct carm_host *host)
                        host->n_msgs++;
 
                        assert(host->n_msgs <= CARM_MAX_REQ);
+                       sg_init_table(crq->sg, CARM_MAX_REQ_SG);
                        return crq;
                }
 
@@ -762,21 +744,19 @@ static unsigned int carm_fill_get_fw_ver(struct carm_host *host,
 
 static inline void carm_end_request_queued(struct carm_host *host,
                                           struct carm_request *crq,
-                                          int uptodate)
+                                          int error)
 {
        struct request *req = crq->rq;
        int rc;
 
-       rc = end_that_request_first(req, uptodate, req->hard_nr_sectors);
+       rc = __blk_end_request(req, error, blk_rq_bytes(req));
        assert(rc == 0);
 
-       end_that_request_last(req, uptodate);
-
        rc = carm_put_request(host, crq);
        assert(rc == 0);
 }
 
-static inline void carm_push_q (struct carm_host *host, request_queue_t *q)
+static inline void carm_push_q (struct carm_host *host, struct request_queue *q)
 {
        unsigned int idx = host->wait_q_prod % CARM_MAX_WAIT_Q;
 
@@ -788,7 +768,7 @@ static inline void carm_push_q (struct carm_host *host, request_queue_t *q)
        BUG_ON(host->wait_q_prod == host->wait_q_cons); /* overrun */
 }
 
-static inline request_queue_t *carm_pop_q(struct carm_host *host)
+static inline struct request_queue *carm_pop_q(struct carm_host *host)
 {
        unsigned int idx;
 
@@ -803,7 +783,7 @@ static inline request_queue_t *carm_pop_q(struct carm_host *host)
 
 static inline void carm_round_robin(struct carm_host *host)
 {
-       request_queue_t *q = carm_pop_q(host);
+       struct request_queue *q = carm_pop_q(host);
        if (q) {
                blk_start_queue(q);
                VPRINTK("STARTED QUEUE %p\n", q);
@@ -811,9 +791,9 @@ static inline void carm_round_robin(struct carm_host *host)
 }
 
 static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq,
-                       int is_ok)
+                              int error)
 {
-       carm_end_request_queued(host, crq, is_ok);
+       carm_end_request_queued(host, crq, error);
        if (max_queue == 1)
                carm_round_robin(host);
        else if ((host->n_msgs <= CARM_MSG_LOW_WATER) &&
@@ -822,7 +802,7 @@ static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq,
        }
 }
 
-static void carm_oob_rq_fn(request_queue_t *q)
+static void carm_oob_rq_fn(struct request_queue *q)
 {
        struct carm_host *host = q->queuedata;
        struct carm_request *crq;
@@ -853,7 +833,7 @@ static void carm_oob_rq_fn(request_queue_t *q)
        }
 }
 
-static void carm_rq_fn(request_queue_t *q)
+static void carm_rq_fn(struct request_queue *q)
 {
        struct carm_port *port = q->queuedata;
        struct carm_host *host = port->host;
@@ -891,14 +871,14 @@ queue_one_request:
        sg = &crq->sg[0];
        n_elem = blk_rq_map_sg(q, rq, sg);
        if (n_elem <= 0) {
-               carm_end_rq(host, crq, 0);
+               carm_end_rq(host, crq, -EIO);
                return;         /* request with no s/g entries? */
        }
 
        /* map scatterlist to PCI bus addresses */
        n_elem = pci_map_sg(host->pdev, sg, n_elem, pci_dir);
        if (n_elem <= 0) {
-               carm_end_rq(host, crq, 0);
+               carm_end_rq(host, crq, -EIO);
                return;         /* request with no s/g entries? */
        }
        crq->n_elem = n_elem;
@@ -959,7 +939,7 @@ queue_one_request:
 
 static void carm_handle_array_info(struct carm_host *host,
                                   struct carm_request *crq, u8 *mem,
-                                  int is_ok)
+                                  int error)
 {
        struct carm_port *port;
        u8 *msg_data = mem + sizeof(struct carm_array_info);
@@ -970,9 +950,9 @@ static void carm_handle_array_info(struct carm_host *host,
 
        DPRINTK("ENTER\n");
 
-       carm_end_rq(host, crq, is_ok);
+       carm_end_rq(host, crq, error);
 
-       if (!is_ok)
+       if (error)
                goto out;
        if (le32_to_cpu(desc->array_status) & ARRAY_NO_EXIST)
                goto out;
@@ -1019,7 +999,7 @@ out:
 
 static void carm_handle_scan_chan(struct carm_host *host,
                                  struct carm_request *crq, u8 *mem,
-                                 int is_ok)
+                                 int error)
 {
        u8 *msg_data = mem + IOC_SCAN_CHAN_OFFSET;
        unsigned int i, dev_count = 0;
@@ -1027,9 +1007,9 @@ static void carm_handle_scan_chan(struct carm_host *host,
 
        DPRINTK("ENTER\n");
 
-       carm_end_rq(host, crq, is_ok);
+       carm_end_rq(host, crq, error);
 
-       if (!is_ok) {
+       if (error) {
                new_state = HST_ERROR;
                goto out;
        }
@@ -1051,23 +1031,23 @@ out:
 }
 
 static void carm_handle_generic(struct carm_host *host,
-                               struct carm_request *crq, int is_ok,
+                               struct carm_request *crq, int error,
                                int cur_state, int next_state)
 {
        DPRINTK("ENTER\n");
 
-       carm_end_rq(host, crq, is_ok);
+       carm_end_rq(host, crq, error);
 
        assert(host->state == cur_state);
-       if (is_ok)
-               host->state = next_state;
-       else
+       if (error)
                host->state = HST_ERROR;
+       else
+               host->state = next_state;
        schedule_work(&host->fsm_task);
 }
 
 static inline void carm_handle_rw(struct carm_host *host,
-                                 struct carm_request *crq, int is_ok)
+                                 struct carm_request *crq, int error)
 {
        int pci_dir;
 
@@ -1080,7 +1060,7 @@ static inline void carm_handle_rw(struct carm_host *host,
 
        pci_unmap_sg(host->pdev, &crq->sg[0], crq->n_elem, pci_dir);
 
-       carm_end_rq(host, crq, is_ok);
+       carm_end_rq(host, crq, error);
 }
 
 static inline void carm_handle_resp(struct carm_host *host,
@@ -1089,7 +1069,7 @@ static inline void carm_handle_resp(struct carm_host *host,
        u32 handle = le32_to_cpu(ret_handle_le);
        unsigned int msg_idx;
        struct carm_request *crq;
-       int is_ok = (status == RMSG_OK);
+       int error = (status == RMSG_OK) ? 0 : -EIO;
        u8 *mem;
 
        VPRINTK("ENTER, handle == 0x%x\n", handle);
@@ -1108,7 +1088,7 @@ static inline void carm_handle_resp(struct carm_host *host,
        /* fast path */
        if (likely(crq->msg_type == CARM_MSG_READ ||
                   crq->msg_type == CARM_MSG_WRITE)) {
-               carm_handle_rw(host, crq, is_ok);
+               carm_handle_rw(host, crq, error);
                return;
        }
 
@@ -1118,7 +1098,7 @@ static inline void carm_handle_resp(struct carm_host *host,
        case CARM_MSG_IOCTL: {
                switch (crq->msg_subtype) {
                case CARM_IOC_SCAN_CHAN:
-                       carm_handle_scan_chan(host, crq, mem, is_ok);
+                       carm_handle_scan_chan(host, crq, mem, error);
                        break;
                default:
                        /* unknown / invalid response */
@@ -1130,21 +1110,21 @@ static inline void carm_handle_resp(struct carm_host *host,
        case CARM_MSG_MISC: {
                switch (crq->msg_subtype) {
                case MISC_ALLOC_MEM:
-                       carm_handle_generic(host, crq, is_ok,
+                       carm_handle_generic(host, crq, error,
                                            HST_ALLOC_BUF, HST_SYNC_TIME);
                        break;
                case MISC_SET_TIME:
-                       carm_handle_generic(host, crq, is_ok,
+                       carm_handle_generic(host, crq, error,
                                            HST_SYNC_TIME, HST_GET_FW_VER);
                        break;
                case MISC_GET_FW_VER: {
                        struct carm_fw_ver *ver = (struct carm_fw_ver *)
                                mem + sizeof(struct carm_msg_get_fw_ver);
-                       if (is_ok) {
+                       if (!error) {
                                host->fw_ver = le32_to_cpu(ver->version);
                                host->flags |= (ver->features & FL_FW_VER_MASK);
                        }
-                       carm_handle_generic(host, crq, is_ok,
+                       carm_handle_generic(host, crq, error,
                                            HST_GET_FW_VER, HST_PORT_SCAN);
                        break;
                }
@@ -1158,7 +1138,7 @@ static inline void carm_handle_resp(struct carm_host *host,
        case CARM_MSG_ARRAY: {
                switch (crq->msg_subtype) {
                case CARM_ARRAY_INFO:
-                       carm_handle_array_info(host, crq, mem, is_ok);
+                       carm_handle_array_info(host, crq, mem, error);
                        break;
                default:
                        /* unknown / invalid response */
@@ -1177,7 +1157,7 @@ static inline void carm_handle_resp(struct carm_host *host,
 err_out:
        printk(KERN_WARNING DRV_NAME "(%s): BUG: unhandled message type %d/%d\n",
               pci_name(host->pdev), crq->msg_type, crq->msg_subtype);
-       carm_end_rq(host, crq, 0);
+       carm_end_rq(host, crq, -EIO);
 }
 
 static inline void carm_handle_responses(struct carm_host *host)
@@ -1220,7 +1200,7 @@ static inline void carm_handle_responses(struct carm_host *host)
        host->resp_idx += work;
 }
 
-static irqreturn_t carm_interrupt(int irq, void *__host, struct pt_regs *regs)
+static irqreturn_t carm_interrupt(int irq, void *__host)
 {
        struct carm_host *host = __host;
        void __iomem *mmio;
@@ -1264,9 +1244,10 @@ out:
        return IRQ_RETVAL(handled);
 }
 
-static void carm_fsm_task (void *_data)
+static void carm_fsm_task (struct work_struct *work)
 {
-       struct carm_host *host = _data;
+       struct carm_host *host =
+               container_of(work, struct carm_host, fsm_task);
        unsigned long flags;
        unsigned int state;
        int rc, i, next_dev;
@@ -1365,7 +1346,7 @@ static void carm_fsm_task (void *_data)
        }
 
        case HST_PROBE_FINISHED:
-               up(&host->probe_sem);
+               complete(&host->probe_comp);
                break;
 
        case HST_ERROR:
@@ -1513,7 +1494,7 @@ static int carm_init_disks(struct carm_host *host)
 
        for (i = 0; i < CARM_MAX_PORTS; i++) {
                struct gendisk *disk;
-               request_queue_t *q;
+               struct request_queue *q;
                struct carm_port *port;
 
                port = &host->port[i];
@@ -1529,7 +1510,6 @@ static int carm_init_disks(struct carm_host *host)
                port->disk = disk;
                sprintf(disk->disk_name, DRV_NAME "/%u",
                        (unsigned int) (host->id * CARM_MAX_PORTS) + i);
-               sprintf(disk->devfs_name, DRV_NAME "/%u_%u", host->id, i);
                disk->major = host->major;
                disk->first_minor = i * CARM_MINORS_PER_MAJOR;
                disk->fops = &carm_bd_ops;
@@ -1558,7 +1538,7 @@ static void carm_free_disks(struct carm_host *host)
        for (i = 0; i < CARM_MAX_PORTS; i++) {
                struct gendisk *disk = host->port[i].disk;
                if (disk) {
-                       request_queue_t *q = disk->queue;
+                       struct request_queue *q = disk->queue;
 
                        if (disk->flags & GENHD_FL_UP)
                                del_gendisk(disk);
@@ -1591,7 +1571,7 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        struct carm_host *host;
        unsigned int pci_dac;
        int rc;
-       request_queue_t *q;
+       struct request_queue *q;
        unsigned int i;
 
        if (!printed_version++)
@@ -1628,7 +1608,7 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        }
 #endif
 
-       host = kmalloc(sizeof(*host), GFP_KERNEL);
+       host = kzalloc(sizeof(*host), GFP_KERNEL);
        if (!host) {
                printk(KERN_ERR DRV_NAME "(%s): memory alloc failure\n",
                       pci_name(pdev));
@@ -1636,12 +1616,11 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_out_regions;
        }
 
-       memset(host, 0, sizeof(*host));
        host->pdev = pdev;
        host->flags = pci_dac ? FL_DAC : 0;
        spin_lock_init(&host->lock);
-       INIT_WORK(&host->fsm_task, carm_fsm_task, host);
-       init_MUTEX_LOCKED(&host->probe_sem);
+       INIT_WORK(&host->fsm_task, carm_fsm_task);
+       init_completion(&host->probe_comp);
 
        for (i = 0; i < ARRAY_SIZE(host->req); i++)
                host->req[i].tag = i;
@@ -1691,15 +1670,13 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        if (host->flags & FL_DYN_MAJOR)
                host->major = rc;
 
-       devfs_mk_dir(DRV_NAME);
-
        rc = carm_init_disks(host);
        if (rc)
                goto err_out_blkdev_disks;
 
        pci_set_master(pdev);
 
-       rc = request_irq(pdev->irq, carm_interrupt, SA_SHIRQ, DRV_NAME, host);
+       rc = request_irq(pdev->irq, carm_interrupt, IRQF_SHARED, DRV_NAME, host);
        if (rc) {
                printk(KERN_ERR DRV_NAME "(%s): irq alloc failure\n",
                       pci_name(pdev));
@@ -1710,12 +1687,13 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc)
                goto err_out_free_irq;
 
-       DPRINTK("waiting for probe_sem\n");
-       down(&host->probe_sem);
+       DPRINTK("waiting for probe_comp\n");
+       wait_for_completion(&host->probe_comp);
 
-       printk(KERN_INFO "%s: pci %s, ports %d, io %lx, irq %u, major %d\n",
+       printk(KERN_INFO "%s: pci %s, ports %d, io %llx, irq %u, major %d\n",
               host->name, pci_name(pdev), (int) CARM_MAX_PORTS,
-              pci_resource_start(pdev, 0), pdev->irq, host->major);
+              (unsigned long long)pci_resource_start(pdev, 0),
+                  pdev->irq, host->major);
 
        carm_host_id++;
        pci_set_drvdata(pdev, host);
@@ -1757,7 +1735,6 @@ static void carm_remove_one (struct pci_dev *pdev)
 
        free_irq(pdev->irq, host);
        carm_free_disks(host);
-       devfs_remove(DRV_NAME);
        unregister_blkdev(host->major, host->name);
        if (host->major == 160)
                clear_bit(0, &carm_major_alloc);
@@ -1774,7 +1751,7 @@ static void carm_remove_one (struct pci_dev *pdev)
 
 static int __init carm_init(void)
 {
-       return pci_module_init(&carm_driver);
+       return pci_register_driver(&carm_driver);
 }
 
 static void __exit carm_exit(void)