netfilter: nf_conntrack: restrict runtime expect hashsize modifications
[safe/jmp/linux-2.6] / drivers / firewire / sbp2.c
index d41cb6e..d485cdd 100644 (file)
@@ -180,22 +180,26 @@ struct sbp2_target {
        int blocked;    /* ditto */
 };
 
+static struct fw_device *target_device(struct sbp2_target *tgt)
+{
+       return fw_parent_device(tgt->unit);
+}
+
 /* Impossible login_id, to detect logout attempt before successful login */
 #define INVALID_LOGIN_ID 0x10000
 
-/*
- * Per section 7.4.8 of the SBP-2 spec, a mgt_ORB_timeout value can be
- * provided in the config rom. Most devices do provide a value, which
- * we'll use for login management orbs, but with some sane limits.
- */
-#define SBP2_MIN_LOGIN_ORB_TIMEOUT     5000U   /* Timeout in ms */
-#define SBP2_MAX_LOGIN_ORB_TIMEOUT     40000U  /* Timeout in ms */
-#define SBP2_ORB_TIMEOUT               2000U   /* Timeout in ms */
+#define SBP2_ORB_TIMEOUT               2000U           /* Timeout in ms */
 #define SBP2_ORB_NULL                  0x80000000
 #define SBP2_RETRY_LIMIT               0xf             /* 15 retries */
 #define SBP2_CYCLE_LIMIT               (0xc8 << 12)    /* 200 125us cycles */
 
 /*
+ * There is no transport protocol limit to the CDB length,  but we implement
+ * a fixed length only.  16 bytes is enough for disks larger than 2 TB.
+ */
+#define SBP2_MAX_CDB_SIZE              16
+
+/*
  * The default maximum s/g segment size of a FireWire controller is
  * usually 0x10000, but SBP-2 only allows 0xffff. Since buffers have to
  * be quadlet-aligned, we set the length limit to 0xffff & ~3.
@@ -307,7 +311,7 @@ struct sbp2_command_orb {
                struct sbp2_pointer next;
                struct sbp2_pointer data_descriptor;
                __be32 misc;
-               u8 command_block[12];
+               u8 command_block[SBP2_MAX_CDB_SIZE];
        } request;
        struct scsi_cmnd *cmd;
        scsi_done_fn_t done;
@@ -343,8 +347,7 @@ static const struct {
        /* DViCO Momobay FX-3A with TSB42AA9A bridge */ {
                .firmware_revision      = 0x002800,
                .model                  = 0x000000,
-               .workarounds            = SBP2_WORKAROUND_DELAY_INQUIRY |
-                                         SBP2_WORKAROUND_POWER_CONDITION,
+               .workarounds            = SBP2_WORKAROUND_POWER_CONDITION,
        },
        /* Initio bridges, actually only needed for some older ones */ {
                .firmware_revision      = 0x000200,
@@ -414,19 +417,20 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request,
        struct sbp2_logical_unit *lu = callback_data;
        struct sbp2_orb *orb;
        struct sbp2_status status;
-       size_t header_size;
        unsigned long flags;
 
        if (tcode != TCODE_WRITE_BLOCK_REQUEST ||
-           length == 0 || length > sizeof(status)) {
+           length < 8 || length > sizeof(status)) {
                fw_send_response(card, request, RCODE_TYPE_ERROR);
                return;
        }
 
-       header_size = min(length, 2 * sizeof(u32));
-       fw_memcpy_from_be32(&status, payload, header_size);
-       if (length > header_size)
-               memcpy(status.data, payload + 8, length - header_size);
+       status.status  = be32_to_cpup(payload);
+       status.orb_low = be32_to_cpup(payload + 4);
+       memset(status.data, 0, sizeof(status.data));
+       if (length > 8)
+               memcpy(status.data, payload + 8, length - 8);
+
        if (STATUS_GET_SOURCE(status) == 2 || STATUS_GET_SOURCE(status) == 3) {
                fw_notify("non-orb related status write, not handled\n");
                fw_send_response(card, request, RCODE_COMPLETE);
@@ -445,12 +449,12 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request,
        }
        spin_unlock_irqrestore(&card->lock, flags);
 
-       if (&orb->link != &lu->orb_list)
+       if (&orb->link != &lu->orb_list) {
                orb->callback(orb, &status);
-       else
+               kref_put(&orb->kref, free_orb);
+       } else {
                fw_error("status write for unknown orb\n");
-
-       kref_put(&orb->kref, free_orb);
+       }
 
        fw_send_response(card, request, RCODE_COMPLETE);
 }
@@ -488,7 +492,7 @@ static void complete_transaction(struct fw_card *card, int rcode,
 static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
                          int node_id, int generation, u64 offset)
 {
-       struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+       struct fw_device *device = target_device(lu->tgt);
        unsigned long flags;
 
        orb->pointer.high = 0;
@@ -510,7 +514,7 @@ static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu,
 
 static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu)
 {
-       struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+       struct fw_device *device = target_device(lu->tgt);
        struct sbp2_orb *orb, *next;
        struct list_head list;
        unsigned long flags;
@@ -548,7 +552,7 @@ static int sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
                                    int generation, int function,
                                    int lun_or_login_id, void *response)
 {
-       struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+       struct fw_device *device = target_device(lu->tgt);
        struct sbp2_management_orb *orb;
        unsigned int timeout;
        int retval = -ENOMEM;
@@ -644,7 +648,7 @@ static int sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id,
 
 static void sbp2_agent_reset(struct sbp2_logical_unit *lu)
 {
-       struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+       struct fw_device *device = target_device(lu->tgt);
        __be32 d = 0;
 
        fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST,
@@ -661,7 +665,7 @@ static void complete_agent_reset_write_no_wait(struct fw_card *card,
 
 static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu)
 {
-       struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+       struct fw_device *device = target_device(lu->tgt);
        struct fw_transaction *t;
        static __be32 d;
 
@@ -700,7 +704,7 @@ static inline void sbp2_allow_block(struct sbp2_logical_unit *lu)
 static void sbp2_conditionally_block(struct sbp2_logical_unit *lu)
 {
        struct sbp2_target *tgt = lu->tgt;
-       struct fw_card *card = fw_device(tgt->unit->device.parent)->card;
+       struct fw_card *card = target_device(tgt)->card;
        struct Scsi_Host *shost =
                container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
        unsigned long flags;
@@ -724,7 +728,7 @@ static void sbp2_conditionally_block(struct sbp2_logical_unit *lu)
 static void sbp2_conditionally_unblock(struct sbp2_logical_unit *lu)
 {
        struct sbp2_target *tgt = lu->tgt;
-       struct fw_card *card = fw_device(tgt->unit->device.parent)->card;
+       struct fw_card *card = target_device(tgt)->card;
        struct Scsi_Host *shost =
                container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
        unsigned long flags;
@@ -749,7 +753,7 @@ static void sbp2_conditionally_unblock(struct sbp2_logical_unit *lu)
  */
 static void sbp2_unblock(struct sbp2_target *tgt)
 {
-       struct fw_card *card = fw_device(tgt->unit->device.parent)->card;
+       struct fw_card *card = target_device(tgt)->card;
        struct Scsi_Host *shost =
                container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
        unsigned long flags;
@@ -779,7 +783,7 @@ static void sbp2_release_target(struct kref *kref)
        struct Scsi_Host *shost =
                container_of((void *)tgt, struct Scsi_Host, hostdata[0]);
        struct scsi_device *sdev;
-       struct fw_device *device = fw_device(tgt->unit->device.parent);
+       struct fw_device *device = target_device(tgt);
 
        /* prevent deadlocks */
        sbp2_unblock(tgt);
@@ -816,20 +820,25 @@ static void sbp2_release_target(struct kref *kref)
        fw_device_put(device);
 }
 
-static struct workqueue_struct *sbp2_wq;
+static void sbp2_target_get(struct sbp2_target *tgt)
+{
+       kref_get(&tgt->kref);
+}
 
 static void sbp2_target_put(struct sbp2_target *tgt)
 {
        kref_put(&tgt->kref, sbp2_release_target);
 }
 
+static struct workqueue_struct *sbp2_wq;
+
 /*
  * Always get the target's kref when scheduling work on one its units.
  * Each workqueue job is responsible to call sbp2_target_put() upon return.
  */
 static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
 {
-       kref_get(&lu->tgt->kref);
+       sbp2_target_get(lu->tgt);
        if (!queue_delayed_work(sbp2_wq, &lu->work, delay))
                sbp2_target_put(lu->tgt);
 }
@@ -852,7 +861,7 @@ static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay)
  */
 static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu)
 {
-       struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+       struct fw_device *device = target_device(lu->tgt);
        __be32 d = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT);
 
        fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST,
@@ -868,7 +877,7 @@ static void sbp2_login(struct work_struct *work)
        struct sbp2_logical_unit *lu =
                container_of(work, struct sbp2_logical_unit, work.work);
        struct sbp2_target *tgt = lu->tgt;
-       struct fw_device *device = fw_device(tgt->unit->device.parent);
+       struct fw_device *device = target_device(tgt);
        struct Scsi_Host *shost;
        struct scsi_device *sdev;
        struct sbp2_login_response response;
@@ -1023,7 +1032,6 @@ static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
 {
        struct fw_csr_iterator ci;
        int key, value;
-       unsigned int timeout;
 
        fw_csr_iterator_init(&ci, directory);
        while (fw_csr_iterator_next(&ci, &key, &value)) {
@@ -1048,17 +1056,7 @@ static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
 
                case SBP2_CSR_UNIT_CHARACTERISTICS:
                        /* the timeout value is stored in 500ms units */
-                       timeout = ((unsigned int) value >> 8 & 0xff) * 500;
-                       timeout = max(timeout, SBP2_MIN_LOGIN_ORB_TIMEOUT);
-                       tgt->mgt_orb_timeout =
-                                 min(timeout, SBP2_MAX_LOGIN_ORB_TIMEOUT);
-
-                       if (timeout > tgt->mgt_orb_timeout)
-                               fw_notify("%s: config rom contains %ds "
-                                         "management ORB timeout, limiting "
-                                         "to %ds\n", tgt->bus_id,
-                                         timeout / 1000,
-                                         tgt->mgt_orb_timeout / 1000);
+                       tgt->mgt_orb_timeout = (value >> 8 & 0xff) * 500;
                        break;
 
                case SBP2_CSR_LOGICAL_UNIT_NUMBER:
@@ -1076,6 +1074,22 @@ static int sbp2_scan_unit_dir(struct sbp2_target *tgt, u32 *directory,
        return 0;
 }
 
+/*
+ * Per section 7.4.8 of the SBP-2 spec, a mgt_ORB_timeout value can be
+ * provided in the config rom. Most devices do provide a value, which
+ * we'll use for login management orbs, but with some sane limits.
+ */
+static void sbp2_clamp_management_orb_timeout(struct sbp2_target *tgt)
+{
+       unsigned int timeout = tgt->mgt_orb_timeout;
+
+       if (timeout > 40000)
+               fw_notify("%s: %ds mgt_ORB_timeout limited to 40s\n",
+                         tgt->bus_id, timeout / 1000);
+
+       tgt->mgt_orb_timeout = clamp_val(timeout, 5000, 40000);
+}
+
 static void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model,
                                  u32 firmware_revision)
 {
@@ -1116,7 +1130,7 @@ static struct scsi_host_template scsi_driver_template;
 static int sbp2_probe(struct device *dev)
 {
        struct fw_unit *unit = fw_unit(dev);
-       struct fw_device *device = fw_device(unit->device.parent);
+       struct fw_device *device = fw_parent_device(unit);
        struct sbp2_target *tgt;
        struct sbp2_logical_unit *lu;
        struct Scsi_Host *shost;
@@ -1131,7 +1145,7 @@ static int sbp2_probe(struct device *dev)
                return -ENOMEM;
 
        tgt = (struct sbp2_target *)shost->hostdata;
-       unit->device.driver_data = tgt;
+       dev_set_drvdata(&unit->device, tgt);
        tgt->unit = unit;
        kref_init(&tgt->kref);
        INIT_LIST_HEAD(&tgt->lu_list);
@@ -1141,6 +1155,8 @@ static int sbp2_probe(struct device *dev)
        if (fw_device_enable_phys_dma(device) < 0)
                goto fail_shost_put;
 
+       shost->max_cmd_len = SBP2_MAX_CDB_SIZE;
+
        if (scsi_add_host(shost, &unit->device) < 0)
                goto fail_shost_put;
 
@@ -1158,6 +1174,7 @@ static int sbp2_probe(struct device *dev)
                               &firmware_revision) < 0)
                goto fail_tgt_put;
 
+       sbp2_clamp_management_orb_timeout(tgt);
        sbp2_init_workarounds(tgt, model, firmware_revision);
 
        /*
@@ -1186,7 +1203,7 @@ static int sbp2_probe(struct device *dev)
 static int sbp2_remove(struct device *dev)
 {
        struct fw_unit *unit = fw_unit(dev);
-       struct sbp2_target *tgt = unit->device.driver_data;
+       struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
 
        sbp2_target_put(tgt);
        return 0;
@@ -1197,7 +1214,7 @@ static void sbp2_reconnect(struct work_struct *work)
        struct sbp2_logical_unit *lu =
                container_of(work, struct sbp2_logical_unit, work.work);
        struct sbp2_target *tgt = lu->tgt;
-       struct fw_device *device = fw_device(tgt->unit->device.parent);
+       struct fw_device *device = target_device(tgt);
        int generation, node_id, local_node_id;
 
        if (fw_device_is_shutdown(device))
@@ -1246,10 +1263,10 @@ static void sbp2_reconnect(struct work_struct *work)
 
 static void sbp2_update(struct fw_unit *unit)
 {
-       struct sbp2_target *tgt = unit->device.driver_data;
+       struct sbp2_target *tgt = dev_get_drvdata(&unit->device);
        struct sbp2_logical_unit *lu;
 
-       fw_device_enable_phys_dma(fw_device(unit->device.parent));
+       fw_device_enable_phys_dma(fw_parent_device(unit));
 
        /*
         * Fw-core serializes sbp2_update() against sbp2_remove().
@@ -1342,7 +1359,7 @@ static void complete_command_orb(struct sbp2_orb *base_orb,
 {
        struct sbp2_command_orb *orb =
                container_of(base_orb, struct sbp2_command_orb, base);
-       struct fw_device *device = fw_device(orb->lu->tgt->unit->device.parent);
+       struct fw_device *device = target_device(orb->lu->tgt);
        int result;
 
        if (status != NULL) {
@@ -1449,7 +1466,7 @@ static int sbp2_map_scatterlist(struct sbp2_command_orb *orb,
 static int sbp2_scsi_queuecommand(struct scsi_cmnd *cmd, scsi_done_fn_t done)
 {
        struct sbp2_logical_unit *lu = cmd->device->hostdata;
-       struct fw_device *device = fw_device(lu->tgt->unit->device.parent);
+       struct fw_device *device = target_device(lu->tgt);
        struct sbp2_command_orb *orb;
        int generation, retval = SCSI_MLQUEUE_HOST_BUSY;