* but the code needs additional debugging.
*/
+#include <linux/blkdev.h>
+#include <linux/compiler.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gfp.h>
+#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/list.h>
-#include <linux/string.h>
-#include <linux/stringify.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/fs.h>
-#include <linux/poll.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/blkdev.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/stringify.h>
+#include <linux/types.h>
#include <linux/wait.h>
-#include <asm/current.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
#include <asm/byteorder.h>
-#include <asm/system.h>
+#include <asm/errno.h>
+#include <asm/param.h>
#include <asm/scatterlist.h>
+#include <asm/system.h>
+#include <asm/types.h>
+
+#ifdef CONFIG_IEEE1394_SBP2_PHYS_DMA
+#include <asm/io.h> /* for bus_to_virt */
+#endif
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_host.h>
#include "csr1212.h"
+#include "highlevel.h"
+#include "hosts.h"
#include "ieee1394.h"
-#include "ieee1394_types.h"
#include "ieee1394_core.h"
-#include "nodemgr.h"
-#include "hosts.h"
-#include "highlevel.h"
+#include "ieee1394_hotplug.h"
#include "ieee1394_transactions.h"
+#include "ieee1394_types.h"
+#include "nodemgr.h"
#include "sbp2.h"
/*
* There is a small window after a bus reset within which the node
* entry's generation is current but the reconnect wasn't completed.
*/
- if (atomic_read(&scsi_id->unfinished_reset))
+ if (unlikely(atomic_read(&scsi_id->state) == SBP2LU_STATE_IN_RESET))
return;
if (hpsb_node_write(scsi_id->ne,
* Now accept new SCSI commands, unless a bus reset happended during
* hpsb_node_write.
*/
- if (!atomic_read(&scsi_id->unfinished_reset))
+ if (likely(atomic_read(&scsi_id->state) != SBP2LU_STATE_IN_RESET))
scsi_unblock_requests(scsi_id->scsi_host);
}
-static void sbp2util_write_orb_pointer(void *p)
+static void sbp2util_write_orb_pointer(struct work_struct *work)
{
+ struct scsi_id_instance_data *scsi_id =
+ container_of(work, struct scsi_id_instance_data,
+ protocol_work.work);
quadlet_t data[2];
- data[0] = ORB_SET_NODE_ID(
- ((struct scsi_id_instance_data *)p)->hi->host->node_id);
- data[1] = ((struct scsi_id_instance_data *)p)->last_orb_dma;
+ data[0] = ORB_SET_NODE_ID(scsi_id->hi->host->node_id);
+ data[1] = scsi_id->last_orb_dma;
sbp2util_cpu_to_be32_buffer(data, 8);
- sbp2util_notify_fetch_agent(p, SBP2_ORB_POINTER_OFFSET, data, 8);
+ sbp2util_notify_fetch_agent(scsi_id, SBP2_ORB_POINTER_OFFSET, data, 8);
}
-static void sbp2util_write_doorbell(void *p)
+static void sbp2util_write_doorbell(struct work_struct *work)
{
- sbp2util_notify_fetch_agent(p, SBP2_DOORBELL_OFFSET, NULL, 4);
+ struct scsi_id_instance_data *scsi_id =
+ container_of(work, struct scsi_id_instance_data,
+ protocol_work.work);
+ sbp2util_notify_fetch_agent(scsi_id, SBP2_DOORBELL_OFFSET, NULL, 4);
}
/*
sbp2scsi_complete_all_commands(scsi_id, DID_NO_CONNECT);
/* scsi_remove_device() will trigger shutdown functions of SCSI
* highlevel drivers which would deadlock if blocked. */
- atomic_set(&scsi_id->unfinished_reset, 0);
+ atomic_set(&scsi_id->state, SBP2LU_STATE_IN_SHUTDOWN);
scsi_unblock_requests(scsi_id->scsi_host);
}
sdev = scsi_id->sdev;
/* Accept new commands unless there was another bus reset in the
* meantime. */
if (hpsb_node_entry_valid(scsi_id->ne)) {
- atomic_set(&scsi_id->unfinished_reset, 0);
+ atomic_set(&scsi_id->state, SBP2LU_STATE_RUNNING);
scsi_unblock_requests(scsi_id->scsi_host);
}
return 0;
INIT_LIST_HEAD(&scsi_id->sbp2_command_orb_completed);
INIT_LIST_HEAD(&scsi_id->scsi_list);
spin_lock_init(&scsi_id->sbp2_command_orb_lock);
- atomic_set(&scsi_id->unfinished_reset, 0);
- INIT_WORK(&scsi_id->protocol_work, NULL, NULL);
+ atomic_set(&scsi_id->state, SBP2LU_STATE_RUNNING);
+ INIT_DELAYED_WORK(&scsi_id->protocol_work, NULL);
ud->device.driver_data = scsi_id;
struct scsi_id_instance_data *scsi_id;
hi = hpsb_get_hostinfo(&sbp2_highlevel, host);
-
- if (hi) {
- list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list) {
- atomic_set(&scsi_id->unfinished_reset, 1);
+ if (!hi)
+ return;
+ list_for_each_entry(scsi_id, &hi->scsi_ids, scsi_list)
+ if (likely(atomic_read(&scsi_id->state) !=
+ SBP2LU_STATE_IN_SHUTDOWN)) {
+ atomic_set(&scsi_id->state, SBP2LU_STATE_IN_RESET);
scsi_block_requests(scsi_id->scsi_host);
}
- }
}
/*
* connected to the sbp2 device being removed. That host would
* have a certain amount of time to relogin before the sbp2 device
* allows someone else to login instead. One second makes sense. */
- msleep_interruptible(1000);
- if (signal_pending(current)) {
+ if (msleep_interruptible(1000)) {
sbp2_remove_device(scsi_id);
return -EINTR;
}
* We do not accept new commands until the job is over.
*/
scsi_block_requests(scsi_id->scsi_host);
- PREPARE_WORK(&scsi_id->protocol_work,
+ PREPARE_DELAYED_WORK(&scsi_id->protocol_work,
last_orb ? sbp2util_write_doorbell:
- sbp2util_write_orb_pointer,
- scsi_id);
- schedule_work(&scsi_id->protocol_work);
+ sbp2util_write_orb_pointer);
+ schedule_delayed_work(&scsi_id->protocol_work, 0);
}
}
(struct scsi_id_instance_data *)sdev->host->hostdata[0];
scsi_id->sdev = sdev;
+ sdev->allow_restart = 1;
if (scsi_id->workarounds & SBP2_WORKAROUND_INQUIRY_36)
sdev->inquiry_len = 36;
blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
sdev->use_10_for_rw = 1;
- sdev->use_10_for_ms = 1;
if (sdev->type == TYPE_DISK &&
scsi_id->workarounds & SBP2_WORKAROUND_MODE_SENSE_8)
sdev->skip_ms_page_8 = 1;
if (scsi_id->workarounds & SBP2_WORKAROUND_FIX_CAPACITY)
sdev->fix_capacity = 1;
- if (scsi_id->ne->guid_vendor_id == 0x0010b9 && /* Maxtor's OUI */
- (sdev->type == TYPE_DISK || sdev->type == TYPE_RBC))
- sdev->allow_restart = 1;
return 0;
}