#include <linux/device.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
+#include <linux/timer.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
int address_high;
int generation;
+ /* Timer for flushing ORBs. */
+ struct timer_list orb_timer;
+
struct work_struct work;
struct Scsi_Host *scsi_host;
};
#define SBP2_MAX_SG_ELEMENT_LENGTH 0xf000
#define SBP2_MAX_SECTORS 255 /* Max sectors supported */
+#define SBP2_ORB_TIMEOUT 2000 /* Timeout in ms */
#define SBP2_ORB_NULL 0x80000000
list_add_tail(&orb->link, &sd->orb_list);
spin_unlock_irqrestore(&device->card->lock, flags);
+ mod_timer(&sd->orb_timer,
+ jiffies + DIV_ROUND_UP(SBP2_ORB_TIMEOUT * HZ, 1000));
+
fw_send_request(device->card, &orb->t, TCODE_WRITE_BLOCK_REQUEST,
node_id, generation,
device->node->max_speed, offset,
}
}
+static void orb_timer_callback(unsigned long data)
+{
+ struct sbp2_device *sd = (struct sbp2_device *)data;
+
+ sbp2_cancel_orbs(sd->unit);
+}
+
static void
complete_management_orb(struct sbp2_orb *base_orb, struct sbp2_status *status)
{
struct fw_device *device = fw_device(unit->device.parent);
struct sbp2_device *sd = unit->device.driver_data;
struct sbp2_management_orb *orb;
- unsigned long timeout;
int retval = -ENOMEM;
orb = kzalloc(sizeof *orb, GFP_ATOMIC);
sbp2_send_orb(&orb->base, unit,
node_id, generation, sd->management_agent_address);
- timeout = wait_for_completion_timeout(&orb->done, 10 * HZ);
+ wait_for_completion(&orb->done);
/* FIXME: Handle bus reset race here. */
goto out;
}
- if (timeout == 0) {
+ if (orb->base.rcode == RCODE_CANCELLED) {
fw_error("orb reply timed out, rcode=0x%02x\n",
orb->base.rcode);
goto out;
unit->device.driver_data = sd;
sd->unit = unit;
INIT_LIST_HEAD(&sd->orb_list);
+ setup_timer(&sd->orb_timer, orb_timer_callback, (unsigned long)sd);
sd->address_handler.length = 0x100;
sd->address_handler.address_callback = sbp2_status_write;
if (sbp2_send_management_orb(unit, node_id, generation,
SBP2_LOGIN_REQUEST, lun, &response) < 0) {
fw_core_remove_address_handler(&sd->address_handler);
+ del_timer_sync(&sd->orb_timer);
kfree(sd);
return -EBUSY;
}
SBP2_LOGOUT_REQUEST, sd->login_id,
NULL);
fw_core_remove_address_handler(&sd->address_handler);
+ del_timer_sync(&sd->orb_timer);
kfree(sd);
return retval;
}
SBP2_LOGOUT_REQUEST, sd->login_id, NULL);
remove_scsi_devices(unit);
+ del_timer_sync(&sd->orb_timer);
fw_core_remove_address_handler(&sd->address_handler);
kfree(sd);