]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ieee1394/sbp2.c
Input: touchscreens - switch to using input_dev->dev.parent
[linux-2.6-omap-h63xx.git] / drivers / ieee1394 / sbp2.c
index 187e26f0485ddd7003ab4498c15eee7cdc602be2..4edfff46b1e60a8801ef4a1a87a7598a758fd0cd 100644 (file)
  *   - make the parameter serialize_io configurable per device
  *   - move all requests to fetch agent registers into non-atomic context,
  *     replace all usages of sbp2util_node_write_no_wait by true transactions
- *   - convert to generic DMA mapping API to eliminate dependency on PCI
  * Grep for inline FIXME comments below.
  */
 
-#include <linux/blkdev.h>
 #include <linux/compiler.h>
 #include <linux/delay.h>
 #include <linux/device.h>
@@ -63,7 +61,6 @@
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/stat.h>
@@ -261,12 +258,10 @@ static int sbp2_remove(struct device *);
 static int sbp2_update(struct unit_directory *);
 
 static struct hpsb_protocol_driver sbp2_driver = {
-       .name           = "SBP2 Driver",
+       .name           = SBP2_DEVICE_NAME,
        .id_table       = sbp2_id_table,
        .update         = sbp2_update,
        .driver         = {
-               .name           = SBP2_DEVICE_NAME,
-               .bus            = &ieee1394_bus_type,
                .probe          = sbp2_probe,
                .remove         = sbp2_remove,
        },
@@ -308,10 +303,11 @@ static struct scsi_host_template sbp2_shost_template = {
        .use_clustering          = ENABLE_CLUSTERING,
        .cmd_per_lun             = SBP2_MAX_CMDS,
        .can_queue               = SBP2_MAX_CMDS,
-       .emulated                = 1,
        .sdev_attrs              = sbp2_sysfs_sdev_attrs,
 };
 
+/* for match-all entries in sbp2_workarounds_table */
+#define SBP2_ROM_VALUE_WILDCARD 0x1000000
 
 /*
  * List of devices with known bugs.
@@ -333,22 +329,14 @@ static const struct {
        },
        /* Initio bridges, actually only needed for some older ones */ {
                .firmware_revision      = 0x000200,
+               .model_id               = SBP2_ROM_VALUE_WILDCARD,
                .workarounds            = SBP2_WORKAROUND_INQUIRY_36,
        },
        /* Symbios bridge */ {
                .firmware_revision      = 0xa0b800,
+               .model_id               = SBP2_ROM_VALUE_WILDCARD,
                .workarounds            = SBP2_WORKAROUND_128K_MAX_TRANS,
        },
-       /*
-        * Note about the following Apple iPod blacklist entries:
-        *
-        * There are iPods (2nd gen, 3rd gen) with model_id==0.  Since our
-        * matching logic treats 0 as a wildcard, we cannot match this ID
-        * without rewriting the matching routine.  Fortunately these iPods
-        * do not feature the read_capacity bug according to one report.
-        * Read_capacity behaviour as well as model_id could change due to
-        * Apple-supplied firmware updates though.
-        */
        /* iPod 4th generation */ {
                .firmware_revision      = 0x0a2700,
                .model_id               = 0x000021,
@@ -462,17 +450,20 @@ static void sbp2util_notify_fetch_agent(struct sbp2_lu *lu, u64 offset,
 
 static void sbp2util_write_orb_pointer(struct work_struct *work)
 {
+       struct sbp2_lu *lu = container_of(work, struct sbp2_lu, protocol_work);
        quadlet_t data[2];
 
-       data[0] = ORB_SET_NODE_ID((container_of(work, struct sbp2_lu, protocol_work))->hi->host->node_id);
-       data[1] = (container_of(work, struct sbp2_lu, protocol_work))->last_orb_dma;
+       data[0] = ORB_SET_NODE_ID(lu->hi->host->node_id);
+       data[1] = lu->last_orb_dma;
        sbp2util_cpu_to_be32_buffer(data, 8);
-       sbp2util_notify_fetch_agent(container_of(work, struct sbp2_lu, protocol_work), SBP2_ORB_POINTER_OFFSET, data, 8);
+       sbp2util_notify_fetch_agent(lu, SBP2_ORB_POINTER_OFFSET, data, 8);
 }
 
 static void sbp2util_write_doorbell(struct work_struct *work)
 {
-       sbp2util_notify_fetch_agent(container_of(work, struct sbp2_lu, protocol_work), SBP2_DOORBELL_OFFSET, NULL, 4);
+       struct sbp2_lu *lu = container_of(work, struct sbp2_lu, protocol_work);
+
+       sbp2util_notify_fetch_agent(lu, SBP2_DOORBELL_OFFSET, NULL, 4);
 }
 
 static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu)
@@ -491,14 +482,14 @@ static int sbp2util_create_command_orb_pool(struct sbp2_lu *lu)
                        spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
                        return -ENOMEM;
                }
-               cmd->command_orb_dma = pci_map_single(hi->host->pdev,
+               cmd->command_orb_dma = dma_map_single(hi->host->device.parent,
                                                &cmd->command_orb,
                                                sizeof(struct sbp2_command_orb),
-                                               PCI_DMA_TODEVICE);
-               cmd->sge_dma = pci_map_single(hi->host->pdev,
+                                               DMA_TO_DEVICE);
+               cmd->sge_dma = dma_map_single(hi->host->device.parent,
                                        &cmd->scatter_gather_element,
                                        sizeof(cmd->scatter_gather_element),
-                                       PCI_DMA_BIDIRECTIONAL);
+                                       DMA_BIDIRECTIONAL);
                INIT_LIST_HEAD(&cmd->list);
                list_add_tail(&cmd->list, &lu->cmd_orb_completed);
        }
@@ -517,12 +508,13 @@ static void sbp2util_remove_command_orb_pool(struct sbp2_lu *lu)
        if (!list_empty(&lu->cmd_orb_completed))
                list_for_each_safe(lh, next, &lu->cmd_orb_completed) {
                        cmd = list_entry(lh, struct sbp2_command_info, list);
-                       pci_unmap_single(host->pdev, cmd->command_orb_dma,
+                       dma_unmap_single(host->device.parent,
+                                        cmd->command_orb_dma,
                                         sizeof(struct sbp2_command_orb),
-                                        PCI_DMA_TODEVICE);
-                       pci_unmap_single(host->pdev, cmd->sge_dma,
+                                        DMA_TO_DEVICE);
+                       dma_unmap_single(host->device.parent, cmd->sge_dma,
                                         sizeof(cmd->scatter_gather_element),
-                                        PCI_DMA_BIDIRECTIONAL);
+                                        DMA_BIDIRECTIONAL);
                        kfree(cmd);
                }
        spin_unlock_irqrestore(&lu->cmd_orb_lock, flags);
@@ -591,47 +583,31 @@ static struct sbp2_command_info *sbp2util_allocate_command_orb(
        return cmd;
 }
 
-static void sbp2util_free_command_dma(struct sbp2_command_info *cmd)
+/*
+ * Unmaps the DMAs of a command and moves the command to the completed ORB list.
+ * Must be called with lu->cmd_orb_lock held.
+ */
+static void sbp2util_mark_command_completed(struct sbp2_lu *lu,
+                                           struct sbp2_command_info *cmd)
 {
-       struct sbp2_lu *lu = (struct sbp2_lu *)
-                       cmd->Current_SCpnt->device->host->hostdata[0];
-       struct hpsb_host *host;
-
-       if (!lu) {
-               SBP2_ERR("%s: lu == NULL", __FUNCTION__);
-               return;
-       }
-
-       host = lu->ud->ne->host;
+       struct hpsb_host *host = lu->ud->ne->host;
 
        if (cmd->cmd_dma) {
                if (cmd->dma_type == CMD_DMA_SINGLE)
-                       pci_unmap_single(host->pdev, cmd->cmd_dma,
+                       dma_unmap_single(host->device.parent, cmd->cmd_dma,
                                         cmd->dma_size, cmd->dma_dir);
                else if (cmd->dma_type == CMD_DMA_PAGE)
-                       pci_unmap_page(host->pdev, cmd->cmd_dma,
+                       dma_unmap_page(host->device.parent, cmd->cmd_dma,
                                       cmd->dma_size, cmd->dma_dir);
                /* XXX: Check for CMD_DMA_NONE bug */
                cmd->dma_type = CMD_DMA_NONE;
                cmd->cmd_dma = 0;
        }
-
        if (cmd->sge_buffer) {
-               pci_unmap_sg(host->pdev, cmd->sge_buffer,
+               dma_unmap_sg(host->device.parent, cmd->sge_buffer,
                             cmd->dma_size, cmd->dma_dir);
                cmd->sge_buffer = NULL;
        }
-}
-
-/*
- * This function moves a command to the completed orb list.
- * Must be called with lu->cmd_orb_lock held.
- */
-static void sbp2util_mark_command_completed(
-               struct sbp2_lu *lu,
-               struct sbp2_command_info *cmd)
-{
-       sbp2util_free_command_dma(cmd);
        list_move_tail(&cmd->list, &lu->cmd_orb_completed);
 }
 
@@ -853,39 +829,39 @@ static int sbp2_start_device(struct sbp2_lu *lu)
        struct sbp2_fwhost_info *hi = lu->hi;
        int error;
 
-       lu->login_response = pci_alloc_consistent(hi->host->pdev,
+       lu->login_response = dma_alloc_coherent(hi->host->device.parent,
                                     sizeof(struct sbp2_login_response),
-                                    &lu->login_response_dma);
+                                    &lu->login_response_dma, GFP_KERNEL);
        if (!lu->login_response)
                goto alloc_fail;
 
-       lu->query_logins_orb = pci_alloc_consistent(hi->host->pdev,
+       lu->query_logins_orb = dma_alloc_coherent(hi->host->device.parent,
                                     sizeof(struct sbp2_query_logins_orb),
-                                    &lu->query_logins_orb_dma);
+                                    &lu->query_logins_orb_dma, GFP_KERNEL);
        if (!lu->query_logins_orb)
                goto alloc_fail;
 
-       lu->query_logins_response = pci_alloc_consistent(hi->host->pdev,
+       lu->query_logins_response = dma_alloc_coherent(hi->host->device.parent,
                                     sizeof(struct sbp2_query_logins_response),
-                                    &lu->query_logins_response_dma);
+                                    &lu->query_logins_response_dma, GFP_KERNEL);
        if (!lu->query_logins_response)
                goto alloc_fail;
 
-       lu->reconnect_orb = pci_alloc_consistent(hi->host->pdev,
+       lu->reconnect_orb = dma_alloc_coherent(hi->host->device.parent,
                                     sizeof(struct sbp2_reconnect_orb),
-                                    &lu->reconnect_orb_dma);
+                                    &lu->reconnect_orb_dma, GFP_KERNEL);
        if (!lu->reconnect_orb)
                goto alloc_fail;
 
-       lu->logout_orb = pci_alloc_consistent(hi->host->pdev,
+       lu->logout_orb = dma_alloc_coherent(hi->host->device.parent,
                                     sizeof(struct sbp2_logout_orb),
-                                    &lu->logout_orb_dma);
+                                    &lu->logout_orb_dma, GFP_KERNEL);
        if (!lu->logout_orb)
                goto alloc_fail;
 
-       lu->login_orb = pci_alloc_consistent(hi->host->pdev,
+       lu->login_orb = dma_alloc_coherent(hi->host->device.parent,
                                     sizeof(struct sbp2_login_orb),
-                                    &lu->login_orb_dma);
+                                    &lu->login_orb_dma, GFP_KERNEL);
        if (!lu->login_orb)
                goto alloc_fail;
 
@@ -946,32 +922,32 @@ static void sbp2_remove_device(struct sbp2_lu *lu)
        list_del(&lu->lu_list);
 
        if (lu->login_response)
-               pci_free_consistent(hi->host->pdev,
+               dma_free_coherent(hi->host->device.parent,
                                    sizeof(struct sbp2_login_response),
                                    lu->login_response,
                                    lu->login_response_dma);
        if (lu->login_orb)
-               pci_free_consistent(hi->host->pdev,
+               dma_free_coherent(hi->host->device.parent,
                                    sizeof(struct sbp2_login_orb),
                                    lu->login_orb,
                                    lu->login_orb_dma);
        if (lu->reconnect_orb)
-               pci_free_consistent(hi->host->pdev,
+               dma_free_coherent(hi->host->device.parent,
                                    sizeof(struct sbp2_reconnect_orb),
                                    lu->reconnect_orb,
                                    lu->reconnect_orb_dma);
        if (lu->logout_orb)
-               pci_free_consistent(hi->host->pdev,
+               dma_free_coherent(hi->host->device.parent,
                                    sizeof(struct sbp2_logout_orb),
                                    lu->logout_orb,
                                    lu->logout_orb_dma);
        if (lu->query_logins_orb)
-               pci_free_consistent(hi->host->pdev,
+               dma_free_coherent(hi->host->device.parent,
                                    sizeof(struct sbp2_query_logins_orb),
                                    lu->query_logins_orb,
                                    lu->query_logins_orb_dma);
        if (lu->query_logins_response)
-               pci_free_consistent(hi->host->pdev,
+               dma_free_coherent(hi->host->device.parent,
                                    sizeof(struct sbp2_query_logins_response),
                                    lu->query_logins_response,
                                    lu->query_logins_response_dma);
@@ -1323,11 +1299,13 @@ static void sbp2_parse_unit_directory(struct sbp2_lu *lu,
 
        if (!(workarounds & SBP2_WORKAROUND_OVERRIDE))
                for (i = 0; i < ARRAY_SIZE(sbp2_workarounds_table); i++) {
-                       if (sbp2_workarounds_table[i].firmware_revision &&
+                       if (sbp2_workarounds_table[i].firmware_revision !=
+                           SBP2_ROM_VALUE_WILDCARD &&
                            sbp2_workarounds_table[i].firmware_revision !=
                            (firmware_revision & 0xffff00))
                                continue;
-                       if (sbp2_workarounds_table[i].model_id &&
+                       if (sbp2_workarounds_table[i].model_id !=
+                           SBP2_ROM_VALUE_WILDCARD &&
                            sbp2_workarounds_table[i].model_id != ud->model_id)
                                continue;
                        workarounds |= sbp2_workarounds_table[i].workarounds;
@@ -1419,7 +1397,7 @@ static int sbp2_agent_reset(struct sbp2_lu *lu, int wait)
        int retval;
        unsigned long flags;
 
-       /* cancel_delayed_work(&lu->protocol_work); */
+       /* flush lu->protocol_work */
        if (wait)
                flush_scheduled_work();
 
@@ -1462,7 +1440,7 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
 
                cmd->dma_size = sgpnt[0].length;
                cmd->dma_type = CMD_DMA_PAGE;
-               cmd->cmd_dma = pci_map_page(hi->host->pdev,
+               cmd->cmd_dma = dma_map_page(hi->host->device.parent,
                                            sgpnt[0].page, sgpnt[0].offset,
                                            cmd->dma_size, cmd->dma_dir);
 
@@ -1474,8 +1452,8 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
                                                &cmd->scatter_gather_element[0];
                u32 sg_count, sg_len;
                dma_addr_t sg_addr;
-               int i, count = pci_map_sg(hi->host->pdev, sgpnt, scsi_use_sg,
-                                         dma_dir);
+               int i, count = dma_map_sg(hi->host->device.parent, sgpnt,
+                                         scsi_use_sg, dma_dir);
 
                cmd->dma_size = scsi_use_sg;
                cmd->sge_buffer = sgpnt;
@@ -1525,7 +1503,8 @@ static void sbp2_prep_command_orb_no_sg(struct sbp2_command_orb *orb,
        cmd->dma_dir = dma_dir;
        cmd->dma_size = scsi_request_bufflen;
        cmd->dma_type = CMD_DMA_SINGLE;
-       cmd->cmd_dma = pci_map_single(hi->host->pdev, scsi_request_buffer,
+       cmd->cmd_dma = dma_map_single(hi->host->device.parent,
+                                     scsi_request_buffer,
                                      cmd->dma_size, cmd->dma_dir);
        orb->data_descriptor_hi = ORB_SET_NODE_ID(hi->host->node_id);
        orb->misc |= ORB_SET_DIRECTION(orb_direction);
@@ -1643,12 +1622,13 @@ static void sbp2_link_orb_command(struct sbp2_lu *lu,
        size_t length;
        unsigned long flags;
 
-       pci_dma_sync_single_for_device(hi->host->pdev, cmd->command_orb_dma,
-                                      sizeof(struct sbp2_command_orb),
-                                      PCI_DMA_TODEVICE);
-       pci_dma_sync_single_for_device(hi->host->pdev, cmd->sge_dma,
-                                      sizeof(cmd->scatter_gather_element),
-                                      PCI_DMA_BIDIRECTIONAL);
+       dma_sync_single_for_device(hi->host->device.parent,
+                                  cmd->command_orb_dma,
+                                  sizeof(struct sbp2_command_orb),
+                                  DMA_TO_DEVICE);
+       dma_sync_single_for_device(hi->host->device.parent, cmd->sge_dma,
+                                  sizeof(cmd->scatter_gather_element),
+                                  DMA_BIDIRECTIONAL);
 
        /* check to see if there are any previous orbs to use */
        spin_lock_irqsave(&lu->cmd_orb_lock, flags);
@@ -1672,16 +1652,17 @@ static void sbp2_link_orb_command(struct sbp2_lu *lu,
                 * The target's fetch agent may or may not have read this
                 * previous ORB yet.
                 */
-               pci_dma_sync_single_for_cpu(hi->host->pdev, last_orb_dma,
-                                           sizeof(struct sbp2_command_orb),
-                                           PCI_DMA_TODEVICE);
+               dma_sync_single_for_cpu(hi->host->device.parent, last_orb_dma,
+                                       sizeof(struct sbp2_command_orb),
+                                       DMA_TO_DEVICE);
                last_orb->next_ORB_lo = cpu_to_be32(cmd->command_orb_dma);
                wmb();
                /* Tells hardware that this pointer is valid */
                last_orb->next_ORB_hi = 0;
-               pci_dma_sync_single_for_device(hi->host->pdev, last_orb_dma,
-                                              sizeof(struct sbp2_command_orb),
-                                              PCI_DMA_TODEVICE);
+               dma_sync_single_for_device(hi->host->device.parent,
+                                          last_orb_dma,
+                                          sizeof(struct sbp2_command_orb),
+                                          DMA_TO_DEVICE);
                addr += SBP2_DOORBELL_OFFSET;
                data[0] = 0;
                length = 4;
@@ -1702,8 +1683,7 @@ static void sbp2_link_orb_command(struct sbp2_lu *lu,
                scsi_block_requests(lu->shost);
                PREPARE_WORK(&lu->protocol_work,
                             last_orb ? sbp2util_write_doorbell:
-                                       sbp2util_write_orb_pointer
-                            /* */);
+                                       sbp2util_write_orb_pointer);
                schedule_work(&lu->protocol_work);
        }
 }
@@ -1808,14 +1788,13 @@ static int sbp2_handle_status_write(struct hpsb_host *host, int nodeid,
        else
                cmd = sbp2util_find_command_for_orb(lu, sb->ORB_offset_lo);
        if (cmd) {
-               pci_dma_sync_single_for_cpu(hi->host->pdev,
-                               cmd->command_orb_dma,
-                               sizeof(struct sbp2_command_orb),
-                               PCI_DMA_TODEVICE);
-               pci_dma_sync_single_for_cpu(hi->host->pdev,
-                               cmd->sge_dma,
-                               sizeof(cmd->scatter_gather_element),
-                               PCI_DMA_BIDIRECTIONAL);
+               dma_sync_single_for_cpu(hi->host->device.parent,
+                                       cmd->command_orb_dma,
+                                       sizeof(struct sbp2_command_orb),
+                                       DMA_TO_DEVICE);
+               dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma,
+                                       sizeof(cmd->scatter_gather_element),
+                                       DMA_BIDIRECTIONAL);
                /* Grab SCSI command pointers and check status. */
                /*
                 * FIXME: If the src field in the status is 1, the ORB DMA must
@@ -1902,16 +1881,6 @@ static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
        if (unlikely(SCpnt->device->lun))
                goto done;
 
-       /* handle the request sense command here (auto-request sense) */
-       if (SCpnt->cmnd[0] == REQUEST_SENSE) {
-               memcpy(SCpnt->request_buffer, SCpnt->sense_buffer,
-                      SCpnt->request_bufflen);
-               memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
-               sbp2scsi_complete_command(lu, SBP2_SCSI_STATUS_GOOD, SCpnt,
-                                         done);
-               return 0;
-       }
-
        if (unlikely(!hpsb_node_entry_valid(lu->ne))) {
                SBP2_ERR("Bus reset in progress - rejecting command");
                result = DID_BUS_BUSY << 16;
@@ -1951,13 +1920,13 @@ static void sbp2scsi_complete_all_commands(struct sbp2_lu *lu, u32 status)
        while (!list_empty(&lu->cmd_orb_inuse)) {
                lh = lu->cmd_orb_inuse.next;
                cmd = list_entry(lh, struct sbp2_command_info, list);
-               pci_dma_sync_single_for_cpu(hi->host->pdev,
-                               cmd->command_orb_dma,
-                               sizeof(struct sbp2_command_orb),
-                               PCI_DMA_TODEVICE);
-               pci_dma_sync_single_for_cpu(hi->host->pdev, cmd->sge_dma,
-                               sizeof(cmd->scatter_gather_element),
-                               PCI_DMA_BIDIRECTIONAL);
+               dma_sync_single_for_cpu(hi->host->device.parent,
+                                       cmd->command_orb_dma,
+                                       sizeof(struct sbp2_command_orb),
+                                       DMA_TO_DEVICE);
+               dma_sync_single_for_cpu(hi->host->device.parent, cmd->sge_dma,
+                                       sizeof(cmd->scatter_gather_element),
+                                       DMA_BIDIRECTIONAL);
                sbp2util_mark_command_completed(lu, cmd);
                if (cmd->Current_SCpnt) {
                        cmd->Current_SCpnt->result = status << 16;
@@ -2042,9 +2011,10 @@ static int sbp2scsi_slave_configure(struct scsi_device *sdev)
 {
        struct sbp2_lu *lu = (struct sbp2_lu *)sdev->host->hostdata[0];
 
-       blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
        sdev->use_10_for_rw = 1;
 
+       if (sdev->type == TYPE_ROM)
+               sdev->use_10_for_ms = 1;
        if (sdev->type == TYPE_DISK &&
            lu->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
                sdev->skip_ms_page_8 = 1;
@@ -2080,14 +2050,14 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
                spin_lock_irqsave(&lu->cmd_orb_lock, flags);
                cmd = sbp2util_find_command_for_SCpnt(lu, SCpnt);
                if (cmd) {
-                       pci_dma_sync_single_for_cpu(hi->host->pdev,
+                       dma_sync_single_for_cpu(hi->host->device.parent,
                                        cmd->command_orb_dma,
                                        sizeof(struct sbp2_command_orb),
-                                       PCI_DMA_TODEVICE);
-                       pci_dma_sync_single_for_cpu(hi->host->pdev,
+                                       DMA_TO_DEVICE);
+                       dma_sync_single_for_cpu(hi->host->device.parent,
                                        cmd->sge_dma,
                                        sizeof(cmd->scatter_gather_element),
-                                       PCI_DMA_BIDIRECTIONAL);
+                                       DMA_BIDIRECTIONAL);
                        sbp2util_mark_command_completed(lu, cmd);
                        if (cmd->Current_SCpnt) {
                                cmd->Current_SCpnt->result = DID_ABORT << 16;