Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-for-linus-2.6

This commit is contained in:
Linus Torvalds 2005-09-20 08:50:49 -07:00
commit 9600c11ba3
45 changed files with 4234 additions and 1584 deletions

View file

@ -1109,15 +1109,6 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa
return (0);
}
uint64_t
ahc_linux_get_memsize(void)
{
struct sysinfo si;
si_meminfo(&si);
return ((uint64_t)si.totalram << PAGE_SHIFT);
}
/*
* Place the SCSI bus into a known state by either resetting it,
* or forcing transfer negotiations on the next command to any

View file

@ -494,8 +494,6 @@ ahc_insb(struct ahc_softc * ahc, long port, uint8_t *array, int count)
int ahc_linux_register_host(struct ahc_softc *,
struct scsi_host_template *);
uint64_t ahc_linux_get_memsize(void);
/*************************** Pretty Printing **********************************/
struct info_str {
char *buffer;

View file

@ -180,6 +180,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct ahc_pci_identity *entry;
char *name;
int error;
struct device *dev = &pdev->dev;
pci = pdev;
entry = ahc_find_pci_device(pci);
@ -209,11 +210,12 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_master(pdev);
if (sizeof(dma_addr_t) > 4
&& ahc_linux_get_memsize() > 0x80000000
&& pci_set_dma_mask(pdev, mask_39bit) == 0) {
&& ahc->features & AHC_LARGE_SCBS
&& dma_set_mask(dev, mask_39bit) == 0
&& dma_get_required_mask(dev) > DMA_32BIT_MASK) {
ahc->flags |= AHC_39BIT_ADDRESSING;
} else {
if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
if (dma_set_mask(dev, DMA_32BIT_MASK)) {
printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n");
return (-ENODEV);
}

View file

@ -996,6 +996,7 @@ oktosend:
#ifdef ED_DBGP
printk("send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d\n", dev->id[c][target_id].prdaddr,tmpcip,target_id);
#endif
dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus;
outl(dev->id[c][target_id].prdaddr, tmpcip);
tmpcip = tmpcip - 2;
outb(0x06, tmpcip);
@ -2572,7 +2573,7 @@ static void atp870u_free_tables(struct Scsi_Host *host)
for (k = 0; k < 16; k++) {
if (!atp_dev->id[j][k].prd_table)
continue;
pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prdaddr);
pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prd_bus);
atp_dev->id[j][k].prd_table = NULL;
}
}
@ -2584,12 +2585,13 @@ static int atp870u_init_tables(struct Scsi_Host *host)
int c,k;
for(c=0;c < 2;c++) {
for(k=0;k<16;k++) {
atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prdaddr));
atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prd_bus));
if (!atp_dev->id[c][k].prd_table) {
printk("atp870u_init_tables fail\n");
atp870u_free_tables(host);
return -ENOMEM;
}
atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus;
atp_dev->id[c][k].devsp=0x20;
atp_dev->id[c][k].devtype = 0x7f;
atp_dev->id[c][k].curr_req = NULL;

View file

@ -54,8 +54,9 @@ struct atp_unit
unsigned long tran_len;
unsigned long last_len;
unsigned char *prd_pos;
unsigned char *prd_table;
dma_addr_t prdaddr;
unsigned char *prd_table; /* Kernel address of PRD table */
dma_addr_t prd_bus; /* Bus address of PRD */
dma_addr_t prdaddr; /* Dynamically updated in driver */
struct scsi_cmnd *curr_req;
} id[2][16];
struct Scsi_Host *host;

View file

@ -1360,3 +1360,5 @@ static Scsi_Host_Template driver_template = {
.use_clustering = DISABLE_CLUSTERING,
};
#include "scsi_module.c"
MODULE_LICENSE("GPL");

View file

@ -98,6 +98,7 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state)
switch (oldstate) {
case SHOST_CREATED:
case SHOST_RUNNING:
case SHOST_CANCEL_RECOVERY:
break;
default:
goto illegal;
@ -107,12 +108,31 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state)
case SHOST_DEL:
switch (oldstate) {
case SHOST_CANCEL:
case SHOST_DEL_RECOVERY:
break;
default:
goto illegal;
}
break;
case SHOST_CANCEL_RECOVERY:
switch (oldstate) {
case SHOST_CANCEL:
case SHOST_RECOVERY:
break;
default:
goto illegal;
}
break;
case SHOST_DEL_RECOVERY:
switch (oldstate) {
case SHOST_CANCEL_RECOVERY:
break;
default:
goto illegal;
}
break;
}
shost->shost_state = state;
return 0;
@ -134,13 +154,24 @@ EXPORT_SYMBOL(scsi_host_set_state);
**/
void scsi_remove_host(struct Scsi_Host *shost)
{
unsigned long flags;
down(&shost->scan_mutex);
scsi_host_set_state(shost, SHOST_CANCEL);
spin_lock_irqsave(shost->host_lock, flags);
if (scsi_host_set_state(shost, SHOST_CANCEL))
if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) {
spin_unlock_irqrestore(shost->host_lock, flags);
up(&shost->scan_mutex);
return;
}
spin_unlock_irqrestore(shost->host_lock, flags);
up(&shost->scan_mutex);
scsi_forget_host(shost);
scsi_proc_host_rm(shost);
scsi_host_set_state(shost, SHOST_DEL);
spin_lock_irqsave(shost->host_lock, flags);
if (scsi_host_set_state(shost, SHOST_DEL))
BUG_ON(scsi_host_set_state(shost, SHOST_DEL_RECOVERY));
spin_unlock_irqrestore(shost->host_lock, flags);
transport_unregister_device(&shost->shost_gendev);
class_device_unregister(&shost->shost_classdev);

View file

@ -460,6 +460,8 @@ MODULE_PARM(adisplay, "1i");
MODULE_PARM(normal, "1i");
MODULE_PARM(ansi, "1i");
#endif
MODULE_LICENSE("GPL");
#endif
/*counter of concurrent disk read/writes, to turn on/off disk led */
static int disk_rw_in_progress = 0;

View file

@ -727,6 +727,16 @@ static void adapter_info_rsp(struct srp_event_struct *evt_struct)
if (hostdata->madapter_info.port_max_txu[0])
hostdata->host->max_sectors =
hostdata->madapter_info.port_max_txu[0] >> 9;
if (hostdata->madapter_info.os_type == 3 &&
strcmp(hostdata->madapter_info.srp_version, "1.6a") <= 0) {
printk("ibmvscsi: host (Ver. %s) doesn't support large"
"transfers\n",
hostdata->madapter_info.srp_version);
printk("ibmvscsi: limiting scatterlists to %d\n",
MAX_INDIRECT_BUFS);
hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS;
}
}
}

View file

@ -1265,9 +1265,8 @@ int scsi_device_cancel(struct scsi_device *sdev, int recovery)
list_for_each_safe(lh, lh_sf, &active_list) {
scmd = list_entry(lh, struct scsi_cmnd, eh_entry);
list_del_init(lh);
if (recovery) {
scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD);
} else {
if (recovery &&
!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD)) {
scmd->result = (DID_ABORT << 16);
scsi_finish_command(scmd);
}

View file

@ -110,6 +110,7 @@ static struct {
{"RELISYS", "Scorpio", NULL, BLIST_NOLUN}, /* responds to all lun */
{"SANKYO", "CP525", "6.64", BLIST_NOLUN}, /* causes failed REQ SENSE, extra reset */
{"TEXEL", "CD-ROM", "1.06", BLIST_NOLUN},
{"transtec", "T5008", "0001", BLIST_NOREPORTLUN },
{"YAMAHA", "CDR100", "1.00", BLIST_NOLUN}, /* locks up */
{"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* locks up */
{"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN}, /* locks up */

View file

@ -50,7 +50,7 @@
void scsi_eh_wakeup(struct Scsi_Host *shost)
{
if (shost->host_busy == shost->host_failed) {
up(shost->eh_wait);
wake_up_process(shost->ehandler);
SCSI_LOG_ERROR_RECOVERY(5,
printk("Waking error handler thread\n"));
}
@ -68,19 +68,24 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag)
{
struct Scsi_Host *shost = scmd->device->host;
unsigned long flags;
int ret = 0;
if (shost->eh_wait == NULL)
if (!shost->ehandler)
return 0;
spin_lock_irqsave(shost->host_lock, flags);
if (scsi_host_set_state(shost, SHOST_RECOVERY))
if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY))
goto out_unlock;
ret = 1;
scmd->eh_eflags |= eh_flag;
list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q);
scsi_host_set_state(shost, SHOST_RECOVERY);
shost->host_failed++;
scsi_eh_wakeup(shost);
out_unlock:
spin_unlock_irqrestore(shost->host_lock, flags);
return 1;
return ret;
}
/**
@ -176,8 +181,8 @@ void scsi_times_out(struct scsi_cmnd *scmd)
}
if (unlikely(!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) {
panic("Error handler thread not present at %p %p %s %d",
scmd, scmd->device->host, __FILE__, __LINE__);
scmd->result |= DID_TIME_OUT << 16;
__scsi_done(scmd);
}
}
@ -196,8 +201,7 @@ int scsi_block_when_processing_errors(struct scsi_device *sdev)
{
int online;
wait_event(sdev->host->host_wait, (sdev->host->shost_state !=
SHOST_RECOVERY));
wait_event(sdev->host->host_wait, !scsi_host_in_recovery(sdev->host));
online = scsi_device_online(sdev);
@ -1441,6 +1445,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev)
static void scsi_restart_operations(struct Scsi_Host *shost)
{
struct scsi_device *sdev;
unsigned long flags;
/*
* If the door was locked, we need to insert a door lock request
@ -1460,7 +1465,11 @@ static void scsi_restart_operations(struct Scsi_Host *shost)
SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n",
__FUNCTION__));
scsi_host_set_state(shost, SHOST_RUNNING);
spin_lock_irqsave(shost->host_lock, flags);
if (scsi_host_set_state(shost, SHOST_RUNNING))
if (scsi_host_set_state(shost, SHOST_CANCEL))
BUG_ON(scsi_host_set_state(shost, SHOST_DEL));
spin_unlock_irqrestore(shost->host_lock, flags);
wake_up(&shost->host_wait);
@ -1582,40 +1591,31 @@ int scsi_error_handler(void *data)
{
struct Scsi_Host *shost = (struct Scsi_Host *) data;
int rtn;
DECLARE_MUTEX_LOCKED(sem);
current->flags |= PF_NOFREEZE;
shost->eh_wait = &sem;
/*
* Wake up the thread that created us.
* Note - we always use TASK_INTERRUPTIBLE even if the module
* was loaded as part of the kernel. The reason is that
* UNINTERRUPTIBLE would cause this thread to be counted in
* the load average as a running process, and an interruptible
* wait doesn't.
*/
SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent of"
" scsi_eh_%d\n",shost->host_no));
while (1) {
/*
* If we get a signal, it means we are supposed to go
* away and die. This typically happens if the user is
* trying to unload a module.
*/
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
" scsi_eh_%d"
" sleeping\n",shost->host_no));
/*
* Note - we always use down_interruptible with the semaphore
* even if the module was loaded as part of the kernel. The
* reason is that down() will cause this thread to be counted
* in the load average as a running process, and down
* interruptible doesn't. Given that we need to allow this
* thread to die if the driver was loaded as a module, using
* semaphores isn't unreasonable.
*/
down_interruptible(&sem);
if (kthread_should_stop())
break;
set_current_state(TASK_INTERRUPTIBLE);
while (!kthread_should_stop()) {
if (shost->host_failed == 0 ||
shost->host_failed != shost->host_busy) {
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
" scsi_eh_%d"
" sleeping\n",
shost->host_no));
schedule();
set_current_state(TASK_INTERRUPTIBLE);
continue;
}
__set_current_state(TASK_RUNNING);
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler"
" scsi_eh_%d waking"
" up\n",shost->host_no));
@ -1642,7 +1642,7 @@ int scsi_error_handler(void *data)
* which are still online.
*/
scsi_restart_operations(shost);
set_current_state(TASK_INTERRUPTIBLE);
}
SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d"
@ -1651,7 +1651,7 @@ int scsi_error_handler(void *data)
/*
* Make sure that nobody tries to wake us up again.
*/
shost->eh_wait = NULL;
shost->ehandler = NULL;
return 0;
}

View file

@ -458,7 +458,7 @@ int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
* error processing, as long as the device was opened
* non-blocking */
if (filp && filp->f_flags & O_NONBLOCK) {
if (sdev->host->shost_state == SHOST_RECOVERY)
if (scsi_host_in_recovery(sdev->host))
return -ENODEV;
} else if (!scsi_block_when_processing_errors(sdev))
return -ENODEV;

View file

@ -118,7 +118,6 @@ static void scsi_unprep_request(struct request *req)
req->flags &= ~REQ_DONTPREP;
req->special = (req->flags & REQ_SPECIAL) ? cmd->sc_request : NULL;
scsi_release_buffers(cmd);
scsi_put_command(cmd);
}
@ -140,14 +139,12 @@ static void scsi_unprep_request(struct request *req)
* commands.
* Notes: This could be called either from an interrupt context or a
* normal process context.
* Notes: Upon return, cmd is a stale pointer.
*/
int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
{
struct Scsi_Host *host = cmd->device->host;
struct scsi_device *device = cmd->device;
struct request_queue *q = device->request_queue;
struct request *req = cmd->request;
unsigned long flags;
SCSI_LOG_MLQUEUE(1,
@ -188,9 +185,8 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)
* function. The SCSI request function detects the blocked condition
* and plugs the queue appropriately.
*/
scsi_unprep_request(req);
spin_lock_irqsave(q->queue_lock, flags);
blk_requeue_request(q, req);
blk_requeue_request(q, cmd->request);
spin_unlock_irqrestore(q->queue_lock, flags);
scsi_run_queue(q);
@ -451,7 +447,7 @@ void scsi_device_unbusy(struct scsi_device *sdev)
spin_lock_irqsave(shost->host_lock, flags);
shost->host_busy--;
if (unlikely((shost->shost_state == SHOST_RECOVERY) &&
if (unlikely(scsi_host_in_recovery(shost) &&
shost->host_failed))
scsi_eh_wakeup(shost);
spin_unlock(shost->host_lock);
@ -1268,6 +1264,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
}
} else {
memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd));
cmd->cmd_len = req->cmd_len;
if (rq_data_dir(req) == WRITE)
cmd->sc_data_direction = DMA_TO_DEVICE;
else if (req->data_len)
@ -1342,7 +1339,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q,
struct Scsi_Host *shost,
struct scsi_device *sdev)
{
if (shost->shost_state == SHOST_RECOVERY)
if (scsi_host_in_recovery(shost))
return 0;
if (shost->host_busy == 0 && shost->host_blocked) {
/*
@ -1514,7 +1511,6 @@ static void scsi_request_fn(struct request_queue *q)
* cases (host limits or settings) should run the queue at some
* later time.
*/
scsi_unprep_request(req);
spin_lock_irq(q->queue_lock);
blk_requeue_request(q, req);
sdev->device_busy--;

View file

@ -1466,23 +1466,17 @@ EXPORT_SYMBOL(scsi_scan_single_target);
void scsi_forget_host(struct Scsi_Host *shost)
{
struct scsi_target *starget, *tmp;
struct scsi_device *sdev;
unsigned long flags;
/*
* Ok, this look a bit strange. We always look for the first device
* on the list as scsi_remove_device removes them from it - thus we
* also have to release the lock.
* We don't need to get another reference to the device before
* releasing the lock as we already own the reference from
* scsi_register_device that's release in scsi_remove_device. And
* after that we don't look at sdev anymore.
*/
restart:
spin_lock_irqsave(shost->host_lock, flags);
list_for_each_entry_safe(starget, tmp, &shost->__targets, siblings) {
list_for_each_entry(sdev, &shost->__devices, siblings) {
if (sdev->sdev_state == SDEV_DEL)
continue;
spin_unlock_irqrestore(shost->host_lock, flags);
scsi_remove_target(&starget->dev);
spin_lock_irqsave(shost->host_lock, flags);
__scsi_remove_device(sdev);
goto restart;
}
spin_unlock_irqrestore(shost->host_lock, flags);
}

View file

@ -57,6 +57,8 @@ static struct {
{ SHOST_CANCEL, "cancel" },
{ SHOST_DEL, "deleted" },
{ SHOST_RECOVERY, "recovery" },
{ SHOST_CANCEL_RECOVERY, "cancel/recovery" },
{ SHOST_DEL_RECOVERY, "deleted/recovery", },
};
const char *scsi_host_state_name(enum scsi_host_state state)
{
@ -707,9 +709,11 @@ void __scsi_remove_device(struct scsi_device *sdev)
**/
void scsi_remove_device(struct scsi_device *sdev)
{
down(&sdev->host->scan_mutex);
struct Scsi_Host *shost = sdev->host;
down(&shost->scan_mutex);
__scsi_remove_device(sdev);
up(&sdev->host->scan_mutex);
up(&shost->scan_mutex);
}
EXPORT_SYMBOL(scsi_remove_device);
@ -717,17 +721,20 @@ void __scsi_remove_target(struct scsi_target *starget)
{
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
unsigned long flags;
struct scsi_device *sdev, *tmp;
struct scsi_device *sdev;
spin_lock_irqsave(shost->host_lock, flags);
starget->reap_ref++;
list_for_each_entry_safe(sdev, tmp, &shost->__devices, siblings) {
restart:
list_for_each_entry(sdev, &shost->__devices, siblings) {
if (sdev->channel != starget->channel ||
sdev->id != starget->id)
sdev->id != starget->id ||
sdev->sdev_state == SDEV_DEL)
continue;
spin_unlock_irqrestore(shost->host_lock, flags);
scsi_remove_device(sdev);
spin_lock_irqsave(shost->host_lock, flags);
goto restart;
}
spin_unlock_irqrestore(shost->host_lock, flags);
scsi_target_reap(starget);

View file

@ -235,6 +235,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt)
return 0;
memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
SCpnt->cmd_len = rq->cmd_len;
if (rq_data_dir(rq) == WRITE)
SCpnt->sc_data_direction = DMA_TO_DEVICE;
else if (rq->data_len)

View file

@ -1027,7 +1027,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
if (sdp->detached)
return -ENODEV;
if (filp->f_flags & O_NONBLOCK) {
if (sdp->device->host->shost_state == SHOST_RECOVERY)
if (scsi_host_in_recovery(sdp->device->host))
return -EBUSY;
} else if (!scsi_block_when_processing_errors(sdp->device))
return -EBUSY;

View file

@ -326,6 +326,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt)
return 0;
memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
SCpnt->cmd_len = rq->cmd_len;
if (!rq->data_len)
SCpnt->sc_data_direction = DMA_NONE;
else if (rq_data_dir(rq) == WRITE)

View file

@ -4206,6 +4206,7 @@ static int st_init_command(struct scsi_cmnd *SCpnt)
return 0;
memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd));
SCpnt->cmd_len = rq->cmd_len;
if (rq_data_dir(rq) == WRITE)
SCpnt->sc_data_direction = DMA_TO_DEVICE;