firewire: fw-sbp2: let SCSI shutdown commands through before logout
[safe/jmp/linux-2.6] / drivers / firewire / fw-sbp2.c
index e2ffbc8..846aad8 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/device.h>
 #include <linux/scatterlist.h>
 #include <linux/dma-mapping.h>
+#include <linux/blkdev.h>
 #include <linux/timer.h>
 
 #include <scsi/scsi.h>
@@ -207,7 +208,6 @@ struct sbp2_command_orb {
 
        struct sbp2_pointer page_table[SG_ALL];
        dma_addr_t page_table_bus;
-       dma_addr_t request_buffer_bus;
 };
 
 /*
@@ -279,7 +279,7 @@ sbp2_status_write(struct fw_card *card, struct fw_request *request,
        unsigned long flags;
 
        if (tcode != TCODE_WRITE_BLOCK_REQUEST ||
-           length == 0 || length > sizeof status) {
+           length == 0 || length > sizeof(status)) {
                fw_send_response(card, request, RCODE_TYPE_ERROR);
                return;
        }
@@ -340,16 +340,15 @@ sbp2_send_orb(struct sbp2_orb *orb, struct fw_unit *unit,
 
        orb->pointer.high = 0;
        orb->pointer.low = orb->request_bus;
-       fw_memcpy_to_be32(&orb->pointer, &orb->pointer, sizeof orb->pointer);
+       fw_memcpy_to_be32(&orb->pointer, &orb->pointer, sizeof(orb->pointer));
 
        spin_lock_irqsave(&device->card->lock, flags);
        list_add_tail(&orb->link, &sd->orb_list);
        spin_unlock_irqrestore(&device->card->lock, flags);
 
        fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
-                       node_id, generation,
-                       device->node->max_speed, offset,
-                       &orb->pointer, sizeof orb->pointer,
+                       node_id, generation, device->max_speed, offset,
+                       &orb->pointer, sizeof(orb->pointer),
                        complete_transaction, orb);
 }
 
@@ -386,7 +385,7 @@ complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
            (struct sbp2_management_orb *)base_orb;
 
        if (status)
-               memcpy(&orb->status, status, sizeof *status);
+               memcpy(&orb->status, status, sizeof(*status));
        complete(&orb->done);
 }
 
@@ -399,7 +398,7 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
        struct sbp2_management_orb *orb;
        int retval = -ENOMEM;
 
-       orb = kzalloc(sizeof *orb, GFP_ATOMIC);
+       orb = kzalloc(sizeof(*orb), GFP_ATOMIC);
        if (orb == NULL)
                return -ENOMEM;
 
@@ -409,13 +408,13 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
         */
        orb->base.request_bus =
                dma_map_single(device->card->device, &orb->request,
-                              sizeof orb->request, DMA_TO_DEVICE);
+                              sizeof(orb->request), DMA_TO_DEVICE);
        if (dma_mapping_error(orb->base.request_bus))
                goto out;
 
        orb->response_bus =
                dma_map_single(device->card->device, &orb->response,
-                              sizeof orb->response, DMA_FROM_DEVICE);
+                              sizeof(orb->response), DMA_FROM_DEVICE);
        if (dma_mapping_error(orb->response_bus))
                goto out;
 
@@ -427,7 +426,7 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
                MANAGEMENT_ORB_FUNCTION(function) |
                MANAGEMENT_ORB_LUN(lun);
        orb->request.length =
-               MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof orb->response);
+               MANAGEMENT_ORB_RESPONSE_LENGTH(sizeof(orb->response));
 
        orb->request.status_fifo.high = sd->address_handler.offset >> 32;
        orb->request.status_fifo.low  = sd->address_handler.offset;
@@ -443,7 +442,7 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
                        MANAGEMENT_ORB_RECONNECT(0);
        }
 
-       fw_memcpy_to_be32(&orb->request, &orb->request, sizeof orb->request);
+       fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
 
        init_completion(&orb->done);
        orb->base.callback = complete_management_orb;
@@ -478,13 +477,13 @@ sbp2_send_management_orb(struct fw_unit *unit, int node_id, int generation,
        retval = 0;
  out:
        dma_unmap_single(device->card->device, orb->base.request_bus,
-                        sizeof orb->request, DMA_TO_DEVICE);
+                        sizeof(orb->request), DMA_TO_DEVICE);
        dma_unmap_single(device->card->device, orb->response_bus,
-                        sizeof orb->response, DMA_FROM_DEVICE);
+                        sizeof(orb->response), DMA_FROM_DEVICE);
 
        if (response)
                fw_memcpy_from_be32(response,
-                                   orb->response, sizeof orb->response);
+                                   orb->response, sizeof(orb->response));
        kfree(orb);
 
        return retval;
@@ -506,14 +505,14 @@ static int sbp2_agent_reset(struct fw_unit *unit)
        struct fw_transaction *t;
        static u32 zero;
 
-       t = kzalloc(sizeof *t, GFP_ATOMIC);
+       t = kzalloc(sizeof(*t), GFP_ATOMIC);
        if (t == NULL)
                return -ENOMEM;
 
        fw_send_request(device->card, t, TCODE_WRITE_QUADLET_REQUEST,
                        sd->node_id, sd->generation, SCODE_400,
                        sd->command_block_agent_address + SBP2_AGENT_RESET,
-                       &zero, sizeof zero, complete_agent_reset_write, t);
+                       &zero, sizeof(zero), complete_agent_reset_write, t);
 
        return 0;
 }
@@ -521,17 +520,15 @@ static int sbp2_agent_reset(struct fw_unit *unit)
 static void sbp2_reconnect(struct work_struct *work);
 static struct scsi_host_template scsi_driver_template;
 
-static void
-release_sbp2_device(struct kref *kref)
+static void release_sbp2_device(struct kref *kref)
 {
        struct sbp2_device *sd = container_of(kref, struct sbp2_device, kref);
        struct Scsi_Host *host =
                container_of((void *)sd, struct Scsi_Host, hostdata[0]);
 
+       scsi_remove_host(host);
        sbp2_send_management_orb(sd->unit, sd->node_id, sd->generation,
                                 SBP2_LOGOUT_REQUEST, sd->login_id, NULL);
-
-       scsi_remove_host(host);
        fw_core_remove_address_handler(&sd->address_handler);
        fw_notify("removed sbp2 unit %s\n", sd->unit->device.bus_id);
        put_device(&sd->unit->device);
@@ -870,7 +867,7 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
        }
 
        dma_unmap_single(device->card->device, orb->base.request_bus,
-                        sizeof orb->request, DMA_TO_DEVICE);
+                        sizeof(orb->request), DMA_TO_DEVICE);
 
        if (orb->cmd->use_sg > 0) {
                sg = (struct scatterlist *)orb->cmd->request_buffer;
@@ -880,12 +877,7 @@ complete_command_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
 
        if (orb->page_table_bus != 0)
                dma_unmap_single(device->card->device, orb->page_table_bus,
-                                sizeof orb->page_table_bus, DMA_TO_DEVICE);
-
-       if (orb->request_buffer_bus != 0)
-               dma_unmap_single(device->card->device, orb->request_buffer_bus,
-                                sizeof orb->request_buffer_bus,
-                                DMA_FROM_DEVICE);
+                                sizeof(orb->page_table_bus), DMA_TO_DEVICE);
 
        orb->cmd->result = result;
        orb->done(orb->cmd);
@@ -944,7 +936,7 @@ static int sbp2_command_orb_map_scatterlist(struct sbp2_command_orb *orb)
                }
        }
 
-       size = sizeof orb->page_table[0] * j;
+       size = sizeof(orb->page_table[0]) * j;
 
        /*
         * The data_descriptor pointer is the one case where we need
@@ -991,13 +983,13 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
         * transfer direction not handled.
         */
        if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) {
-               fw_error("Cannot handle DMA_BIDIRECTIONAL - rejecting command");
+               fw_error("Can't handle DMA_BIDIRECTIONAL, rejecting command\n");
                cmd->result = DID_ERROR << 16;
                done(cmd);
                return 0;
        }
 
-       orb = kzalloc(sizeof *orb, GFP_ATOMIC);
+       orb = kzalloc(sizeof(*orb), GFP_ATOMIC);
        if (orb == NULL) {
                fw_notify("failed to alloc orb\n");
                goto fail_alloc;
@@ -1007,7 +999,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
        orb->base.rcode = -1;
        orb->base.request_bus =
                dma_map_single(device->card->device, &orb->request,
-                              sizeof orb->request, DMA_TO_DEVICE);
+                              sizeof(orb->request), DMA_TO_DEVICE);
        if (dma_mapping_error(orb->base.request_bus))
                goto fail_mapping;
 
@@ -1024,8 +1016,8 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
         * if we set this to max_speed + 7, we get the right value.
         */
        orb->request.misc =
-               COMMAND_ORB_MAX_PAYLOAD(device->node->max_speed + 7) |
-               COMMAND_ORB_SPEED(device->node->max_speed) |
+               COMMAND_ORB_MAX_PAYLOAD(device->max_speed + 7) |
+               COMMAND_ORB_SPEED(device->max_speed) |
                COMMAND_ORB_NOTIFY;
 
        if (cmd->sc_data_direction == DMA_FROM_DEVICE)
@@ -1038,10 +1030,10 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
        if (cmd->use_sg && sbp2_command_orb_map_scatterlist(orb) < 0)
                goto fail_map_payload;
 
-       fw_memcpy_to_be32(&orb->request, &orb->request, sizeof orb->request);
+       fw_memcpy_to_be32(&orb->request, &orb->request, sizeof(orb->request));
 
        memset(orb->request.command_block,
-              0, sizeof orb->request.command_block);
+              0, sizeof(orb->request.command_block));
        memcpy(orb->request.command_block, cmd->cmnd, COMMAND_SIZE(*cmd->cmnd));
 
        orb->base.callback = complete_command_orb;
@@ -1053,7 +1045,7 @@ static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
 
  fail_map_payload:
        dma_unmap_single(device->card->device, orb->base.request_bus,
-                        sizeof orb->request, DMA_TO_DEVICE);
+                        sizeof(orb->request), DMA_TO_DEVICE);
  fail_mapping:
        kfree(orb);
  fail_alloc:
@@ -1087,7 +1079,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
                fw_notify("setting fix_capacity for %s\n", unit->device.bus_id);
                sdev->fix_capacity = 1;
        }
-
+       if (sd->workarounds & SBP2_WORKAROUND_128K_MAX_TRANS)
+               blk_queue_max_sectors(sdev->request_queue, 128 * 1024 / 512);
        return 0;
 }
 
@@ -1108,6 +1101,58 @@ static int sbp2_scsi_abort(struct scsi_cmnd *cmd)
        return SUCCESS;
 }
 
+/*
+ * Format of /sys/bus/scsi/devices/.../ieee1394_id:
+ * u64 EUI-64 : u24 directory_ID : u16 LUN  (all printed in hexadecimal)
+ *
+ * This is the concatenation of target port identifier and logical unit
+ * identifier as per SAM-2...SAM-4 annex A.
+ */
+static ssize_t
+sbp2_sysfs_ieee1394_id_show(struct device *dev, struct device_attribute *attr,
+                           char *buf)
+{
+       struct scsi_device *sdev = to_scsi_device(dev);
+       struct sbp2_device *sd;
+       struct fw_unit *unit;
+       struct fw_device *device;
+       u32 directory_id;
+       struct fw_csr_iterator ci;
+       int key, value, lun;
+
+       if (!sdev)
+               return 0;
+       sd = (struct sbp2_device *)sdev->host->hostdata;
+       unit = sd->unit;
+       device = fw_device(unit->device.parent);
+
+       /* implicit directory ID */
+       directory_id = ((unit->directory - device->config_rom) * 4
+                       + CSR_CONFIG_ROM) & 0xffffff;
+
+       /* explicit directory ID, overrides implicit ID if present */
+       fw_csr_iterator_init(&ci, unit->directory);
+       while (fw_csr_iterator_next(&ci, &key, &value))
+               if (key == CSR_DIRECTORY_ID) {
+                       directory_id = value;
+                       break;
+               }
+
+       /* FIXME: Make this work for multi-lun devices. */
+       lun = 0;
+
+       return sprintf(buf, "%08x%08x:%06x:%04x\n",
+                       device->config_rom[3], device->config_rom[4],
+                       directory_id, lun);
+}
+
+static DEVICE_ATTR(ieee1394_id, S_IRUGO, sbp2_sysfs_ieee1394_id_show, NULL);
+
+static struct device_attribute *sbp2_scsi_sysfs_attrs[] = {
+       &dev_attr_ieee1394_id,
+       NULL
+};
+
 static struct scsi_host_template scsi_driver_template = {
        .module                 = THIS_MODULE,
        .name                   = "SBP-2 IEEE-1394",
@@ -1121,6 +1166,7 @@ static struct scsi_host_template scsi_driver_template = {
        .use_clustering         = ENABLE_CLUSTERING,
        .cmd_per_lun            = 1,
        .can_queue              = 1,
+       .sdev_attrs             = sbp2_scsi_sysfs_attrs,
 };
 
 MODULE_AUTHOR("Kristian Hoegsberg <krh@bitplanet.net>");