** Low PCI traffic for command handling when on-chip RAM is present.
** Aggressive SCSI SCRIPTS optimizations.
**
+** 2005 by Matthew Wilcox and James Bottomley
+** PCI-ectomy. This driver now supports only the 720 chip (see the
+** NCR_Q720 and zalon drivers for the bus probe logic).
+**
*******************************************************************************
*/
#define SCSI_NCR_DEBUG_FLAGS (0)
-/*==========================================================
-**
-** Include files
-**
-**==========================================================
-*/
-
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_transport.h>
#include "ncr53c8xx.h"
-#define NAME53C "ncr53c"
#define NAME53C8XX "ncr53c8xx"
-
/*==========================================================
**
** Debugging tags
** power of 2 cache line size.
** Enhanced in linux-2.3.44 to provide a memory pool
** per pcidev to support dynamic dma mapping. (I would
-** have preferred a real bus astraction, btw).
+** have preferred a real bus abstraction, btw).
**
**==========================================================
*/
{
switch(cmd->__data_mapped) {
case 2:
- dma_unmap_sg(dev, cmd->buffer, cmd->use_sg,
- cmd->sc_data_direction);
- break;
- case 1:
- dma_unmap_single(dev, cmd->__data_mapping,
- cmd->request_bufflen,
- cmd->sc_data_direction);
+ scsi_dma_unmap(cmd);
break;
}
cmd->__data_mapped = 0;
}
-static u_long __map_scsi_single_data(struct device *dev, struct scsi_cmnd *cmd)
-{
- dma_addr_t mapping;
-
- if (cmd->request_bufflen == 0)
- return 0;
-
- mapping = dma_map_single(dev, cmd->request_buffer,
- cmd->request_bufflen,
- cmd->sc_data_direction);
- cmd->__data_mapped = 1;
- cmd->__data_mapping = mapping;
-
- return mapping;
-}
-
static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd)
{
int use_sg;
- if (cmd->use_sg == 0)
+ use_sg = scsi_dma_map(cmd);
+ if (!use_sg)
return 0;
- use_sg = dma_map_sg(dev, cmd->buffer, cmd->use_sg,
- cmd->sc_data_direction);
cmd->__data_mapped = 2;
cmd->__data_mapping = use_sg;
}
#define unmap_scsi_data(np, cmd) __unmap_scsi_data(np->dev, cmd)
-#define map_scsi_single_data(np, cmd) __map_scsi_single_data(np->dev, cmd)
#define map_scsi_sg_data(np, cmd) __map_scsi_sg_data(np->dev, cmd)
/*==========================================================
static struct ncr_driver_setup
driver_setup = SCSI_NCR_DRIVER_SETUP;
+#ifndef MODULE
#ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
static struct ncr_driver_setup
driver_safe_setup __initdata = SCSI_NCR_DRIVER_SAFE_SETUP;
#endif
+#endif /* !MODULE */
#define initverbose (driver_setup.verbose)
#define bootverbose (np->verbose)
#define OPT_IARB 26
#endif
+#ifdef MODULE
+#define ARG_SEP ' '
+#else
+#define ARG_SEP ','
+#endif
+
+#ifndef MODULE
static char setup_token[] __initdata =
"tags:" "mpar:"
"spar:" "disc:"
#endif
; /* DONNOT REMOVE THIS ';' */
-#ifdef MODULE
-#define ARG_SEP ' '
-#else
-#define ARG_SEP ','
-#endif
-
static int __init get_setup_token(char *p)
{
char *cur = setup_token;
return 0;
}
-
static int __init sym53c8xx__setup(char *str)
{
#ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
#endif /* SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT */
return 1;
}
+#endif /* !MODULE */
/*===================================================================
**
** The first four bytes (scr_st[4]) are used inside the script by
** "COPY" commands.
** Because source and destination must have the same alignment
-** in a DWORD, the fields HAVE to be at the choosen offsets.
+** in a DWORD, the fields HAVE to be at the chosen offsets.
** xerr_st 0 (0x34) scratcha
** sync_st 1 (0x05) sxfer
** wide_st 3 (0x03) scntl3
** the DSA (data structure address) register points
** to this substructure of the ccb.
** This substructure contains the header with
-** the script-processor-changable data and
+** the script-processor-changeable data and
** data blocks for the indirect move commands.
**
**----------------------------------------------------------
*/
/*
- ** The M_REJECT problem seems to be due to a selection
+ ** The MESSAGE_REJECT problem seems to be due to a selection
** timing problem.
** Wait immediately for the selection to complete.
** (2.5x behaves so)
/*
** Selection complete.
** Send the IDENTIFY and SIMPLE_TAG messages
- ** (and the M_X_SYNC_REQ message)
+ ** (and the EXTENDED_SDTR message)
*/
SCR_MOVE_TBL ^ SCR_MSG_OUT,
offsetof (struct dsb, smsg),
/*
** Initialize the msgout buffer with a NOOP message.
*/
- SCR_LOAD_REG (scratcha, M_NOOP),
+ SCR_LOAD_REG (scratcha, NOP),
0,
SCR_COPY (1),
RADDR (scratcha),
/*
** Handle this message.
*/
- SCR_JUMP ^ IFTRUE (DATA (M_COMPLETE)),
+ SCR_JUMP ^ IFTRUE (DATA (COMMAND_COMPLETE)),
PADDR (complete),
- SCR_JUMP ^ IFTRUE (DATA (M_DISCONNECT)),
+ SCR_JUMP ^ IFTRUE (DATA (DISCONNECT)),
PADDR (disconnect),
- SCR_JUMP ^ IFTRUE (DATA (M_SAVE_DP)),
+ SCR_JUMP ^ IFTRUE (DATA (SAVE_POINTERS)),
PADDR (save_dp),
- SCR_JUMP ^ IFTRUE (DATA (M_RESTORE_DP)),
+ SCR_JUMP ^ IFTRUE (DATA (RESTORE_POINTERS)),
PADDR (restore_dp),
- SCR_JUMP ^ IFTRUE (DATA (M_EXTENDED)),
+ SCR_JUMP ^ IFTRUE (DATA (EXTENDED_MESSAGE)),
PADDRH (msg_extended),
- SCR_JUMP ^ IFTRUE (DATA (M_NOOP)),
+ SCR_JUMP ^ IFTRUE (DATA (NOP)),
PADDR (clrack),
- SCR_JUMP ^ IFTRUE (DATA (M_REJECT)),
+ SCR_JUMP ^ IFTRUE (DATA (MESSAGE_REJECT)),
PADDRH (msg_reject),
- SCR_JUMP ^ IFTRUE (DATA (M_IGN_RESIDUE)),
+ SCR_JUMP ^ IFTRUE (DATA (IGNORE_WIDE_RESIDUE)),
PADDRH (msg_ign_residue),
/*
** Rest of the messages left as
*/
SCR_INT,
SIR_REJECT_SENT,
- SCR_LOAD_REG (scratcha, M_REJECT),
+ SCR_LOAD_REG (scratcha, MESSAGE_REJECT),
0,
}/*-------------------------< SETMSG >----------------------*/,{
SCR_COPY (1),
/*
** If it was no ABORT message ...
*/
- SCR_JUMP ^ IFTRUE (DATA (M_ABORT)),
+ SCR_JUMP ^ IFTRUE (DATA (ABORT_TASK_SET)),
PADDRH (msg_out_abort),
/*
** ... wait for the next phase
/*
** ... else clear the message ...
*/
- SCR_LOAD_REG (scratcha, M_NOOP),
+ SCR_LOAD_REG (scratcha, NOP),
0,
SCR_COPY (4),
RADDR (scratcha),
*/
SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
NADDR (msgin[2]),
- SCR_JUMP ^ IFTRUE (DATA (M_X_WIDE_REQ)),
+ SCR_JUMP ^ IFTRUE (DATA (EXTENDED_WDTR)),
PADDRH (msg_wdtr),
/*
** unknown extended message
}/*-------------------------< SEND_WDTR >----------------*/,{
/*
- ** Send the M_X_WIDE_REQ
+ ** Send the EXTENDED_WDTR
*/
SCR_MOVE_ABS (4) ^ SCR_MSG_OUT,
NADDR (msgout),
*/
SCR_MOVE_ABS (1) ^ SCR_MSG_IN,
NADDR (msgin[2]),
- SCR_JUMP ^ IFTRUE (DATA (M_X_SYNC_REQ)),
+ SCR_JUMP ^ IFTRUE (DATA (EXTENDED_SDTR)),
PADDRH (msg_sdtr),
/*
** unknown extended message
}/*-------------------------< SEND_SDTR >-------------*/,{
/*
- ** Send the M_X_SYNC_REQ
+ ** Send the EXTENDED_SDTR
*/
SCR_MOVE_ABS (5) ^ SCR_MSG_OUT,
NADDR (msgout),
}/*-------------------------< RESET >----------------------*/,{
/*
- ** Send a M_RESET message if bad IDENTIFY
+ ** Send a TARGET_RESET message if bad IDENTIFY
** received on reselection.
*/
- SCR_LOAD_REG (scratcha, M_ABORT_TAG),
+ SCR_LOAD_REG (scratcha, ABORT_TASK),
0,
SCR_JUMP,
PADDRH (abort_resel),
/*
** Abort a wrong tag received on reselection.
*/
- SCR_LOAD_REG (scratcha, M_ABORT_TAG),
+ SCR_LOAD_REG (scratcha, ABORT_TASK),
0,
SCR_JUMP,
PADDRH (abort_resel),
/*
** Abort a reselection when no active CCB.
*/
- SCR_LOAD_REG (scratcha, M_ABORT),
+ SCR_LOAD_REG (scratcha, ABORT_TASK_SET),
0,
}/*-------------------------< ABORT_RESEL >----------------*/,{
SCR_COPY (1),
** Read the message, since we got it directly
** from the SCSI BUS data lines.
** Signal problem to C code for logging the event.
- ** Send a M_ABORT to clear all pending tasks.
+ ** Send an ABORT_TASK_SET to clear all pending tasks.
*/
SCR_INT,
SIR_RESEL_BAD_LUN,
/*
** We donnot have a task for that I_T_L.
** Signal problem to C code for logging the event.
- ** Send a M_ABORT message.
+ ** Send an ABORT_TASK_SET message.
*/
SCR_INT,
SIR_RESEL_BAD_I_T_L,
/*
** We donnot have a task that matches the tag.
** Signal problem to C code for logging the event.
- ** Send a M_ABORTTAG message.
+ ** Send an ABORT_TASK message.
*/
SCR_INT,
SIR_RESEL_BAD_I_T_L_Q,
** We donnot know the target that reselected us.
** Grab the first message if any (IDENTIFY).
** Signal problem to C code for logging the event.
- ** M_RESET message.
+ ** TARGET_RESET message.
*/
SCR_INT,
SIR_RESEL_BAD_TARGET,
switch (nego) {
case NS_SYNC:
- msgptr[msglen++] = M_EXTENDED;
- msgptr[msglen++] = 3;
- msgptr[msglen++] = M_X_SYNC_REQ;
- msgptr[msglen++] = tp->maxoffs ? tp->minsync : 0;
- msgptr[msglen++] = tp->maxoffs;
+ msglen += spi_populate_sync_msg(msgptr + msglen,
+ tp->maxoffs ? tp->minsync : 0, tp->maxoffs);
break;
case NS_WIDE:
- msgptr[msglen++] = M_EXTENDED;
- msgptr[msglen++] = 2;
- msgptr[msglen++] = M_X_WIDE_REQ;
- msgptr[msglen++] = tp->usrwide;
+ msglen += spi_populate_width_msg(msgptr + msglen, tp->usrwide);
break;
}
**
**----------------------------------------------------
*/
- if (np->settle_time && cmd->timeout_per_command >= HZ) {
- u_long tlimit = jiffies + cmd->timeout_per_command - HZ;
+ if (np->settle_time && cmd->request->timeout >= HZ) {
+ u_long tlimit = jiffies + cmd->request->timeout - HZ;
if (time_after(np->settle_time, tlimit))
np->settle_time = tlimit;
}
**----------------------------------------------------
*/
- idmsg = M_IDENTIFY | sdev->lun;
+ idmsg = IDENTIFY(0, sdev->lun);
if (cp ->tag != NO_TAG ||
(cp != np->ccb && np->disc && !(tp->usrflag & UF_NODISC)))
*/
if (lp && time_after(jiffies, lp->tags_stime)) {
if (lp->tags_smap) {
- order = M_ORDERED_TAG;
+ order = ORDERED_QUEUE_TAG;
if ((DEBUG_FLAGS & DEBUG_TAGS)||bootverbose>2){
PRINT_ADDR(cmd,
"ordered tag forced.\n");
case 0x08: /* READ_SMALL (6) */
case 0x28: /* READ_BIG (10) */
case 0xa8: /* READ_HUGE (12) */
- order = M_SIMPLE_TAG;
+ order = SIMPLE_QUEUE_TAG;
break;
default:
- order = M_ORDERED_TAG;
+ order = ORDERED_QUEUE_TAG;
}
}
msgptr[msglen++] = order;
** Copy back sense data to caller's buffer.
*/
memcpy(cmd->sense_buffer, cp->sense_buf,
- min(sizeof(cmd->sense_buffer), sizeof(cp->sense_buf)));
+ min_t(size_t, SCSI_SENSE_BUFFERSIZE,
+ sizeof(cp->sense_buf)));
if (DEBUG_FLAGS & (DEBUG_RESULT|DEBUG_TINY)) {
- u_char * p = (u_char*) & cmd->sense_buffer;
+ u_char *p = cmd->sense_buffer;
int i;
PRINT_ADDR(cmd, "sense data:");
for (i=0; i<14; i++) printk (" %x", *p++);
/*
** This CCB has been skipped by the NCR.
-** Queue it in the correponding unit queue.
+** Queue it in the corresponding unit queue.
*/
static void ncr_ccb_skipped(struct ncb *np, struct ccb *cp)
{
cp->host_status &= ~HS_SKIPMASK;
cp->start.schedule.l_paddr =
cpu_to_scr(NCB_SCRIPT_PHYS (np, select));
- list_del(&cp->link_ccbq);
- list_add_tail(&cp->link_ccbq, &lp->skip_ccbq);
+ list_move_tail(&cp->link_ccbq, &lp->skip_ccbq);
if (cp->queued) {
--lp->queuedccbs;
}
** input speed faster than the period.
*/
kpc = per * clk;
- while (--div >= 0)
+ while (--div > 0)
if (kpc >= (div_10M[div] << 2)) break;
/*
**
** In normal cases, interrupt conditions occur one at a
** time. The ncr is able to stack in some extra registers
-** other interrupts that will occurs after the first one.
-** But severall interrupts may occur at the same time.
+** other interrupts that will occur after the first one.
+** But, several interrupts may occur at the same time.
**
** We probably should only try to deal with the normal
** case, but it seems that multiple interrupts occur in
if (!(dbc & 0xc0000000))
phase = (dbc >> 24) & 7;
if (phase == 7)
- msg = M_PARITY;
+ msg = MSG_PARITY_ERROR;
else
- msg = M_ID_ERROR;
+ msg = INITIATOR_ERROR;
/*
** we force a SIR_NEGO_PROTO interrupt (it is a hack that avoids
** bloat for such a should_not_happen situation).
** In all other situation, we reset the BUS.
- ** Are these assumptions reasonnable ? (Wait and see ...)
+ ** Are these assumptions reasonable ? (Wait and see ...)
*/
unexpected_phase:
dsp -= 8;
/*-----------------------------------------------------------------------------
**
** Was Sie schon immer ueber transfermode negotiation wissen wollten ...
+** ("Everything you've always wanted to know about transfer mode
+** negotiation")
**
** We try to negotiate sync and wide transfer only after
** a successful inquire command. We look at byte 7 of the
** The host status field is set to HS_NEGOTIATE to mark this
** situation.
**
-** If the target doesn't answer this message immidiately
+** If the target doesn't answer this message immediately
** (as required by the standard), the SIR_NEGO_FAIL interrupt
** will be raised eventually.
** The handler removes the HS_NEGOTIATE status, and sets the
break;
}
- np->msgin [0] = M_NOOP;
- np->msgout[0] = M_NOOP;
+ np->msgin [0] = NOP;
+ np->msgout[0] = NOP;
cp->nego_status = 0;
break;
spi_offset(starget) = ofs;
ncr_setsync(np, cp, scntl3, (fak<<5)|ofs);
- np->msgout[0] = M_EXTENDED;
- np->msgout[1] = 3;
- np->msgout[2] = M_X_SYNC_REQ;
- np->msgout[3] = per;
- np->msgout[4] = ofs;
-
+ spi_populate_sync_msg(np->msgout, per, ofs);
cp->nego_status = NS_SYNC;
if (DEBUG_FLAGS & DEBUG_NEGO) {
OUTL_DSP (NCB_SCRIPT_PHYS (np, msg_bad));
return;
}
- np->msgin [0] = M_NOOP;
+ np->msgin [0] = NOP;
break;
spi_width(starget) = wide;
ncr_setwide(np, cp, wide, 1);
+ spi_populate_width_msg(np->msgout, wide);
- np->msgout[0] = M_EXTENDED;
- np->msgout[1] = 2;
- np->msgout[2] = M_X_WIDE_REQ;
- np->msgout[3] = wide;
-
- np->msgin [0] = M_NOOP;
+ np->msgin [0] = NOP;
cp->nego_status = NS_WIDE;
case SIR_REJECT_RECEIVED:
/*-----------------------------------------------
**
- ** We received a M_REJECT message.
+ ** We received a MESSAGE_REJECT.
**
**-----------------------------------------------
*/
- PRINT_ADDR(cp->cmd, "M_REJECT received (%x:%x).\n",
+ PRINT_ADDR(cp->cmd, "MESSAGE_REJECT received (%x:%x).\n",
(unsigned)scr_to_cpu(np->lastmsg), np->msgout[0]);
break;
**-----------------------------------------------
*/
- ncr_print_msg(cp, "M_REJECT sent for", np->msgin);
+ ncr_print_msg(cp, "MESSAGE_REJECT sent for", np->msgin);
break;
/*--------------------------------------------------------------------
**-----------------------------------------------
*/
- PRINT_ADDR(cp->cmd, "M_IGN_RESIDUE received, but not yet "
+ PRINT_ADDR(cp->cmd, "IGNORE_WIDE_RESIDUE received, but not yet "
"implemented.\n");
break;
#if 0
**-----------------------------------------------
*/
- PRINT_ADDR(cp->cmd, "M_DISCONNECT received, but datapointer "
+ PRINT_ADDR(cp->cmd, "DISCONNECT received, but datapointer "
"not saved: data=%x save=%x goal=%x.\n",
(unsigned) INL (nc_temp),
(unsigned) scr_to_cpu(np->header.savep),
** sizes to the data segment array.
*/
-static int ncr_scatter_no_sglist(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd)
-{
- struct scr_tblmove *data = &cp->phys.data[MAX_SCATTER - 1];
- int segment;
-
- cp->data_len = cmd->request_bufflen;
-
- if (cmd->request_bufflen) {
- dma_addr_t baddr = map_scsi_single_data(np, cmd);
- if (baddr) {
- ncr_build_sge(np, data, baddr, cmd->request_bufflen);
- segment = 1;
- } else {
- segment = -2;
- }
- } else {
- segment = 0;
- }
-
- return segment;
-}
-
static int ncr_scatter(struct ncb *np, struct ccb *cp, struct scsi_cmnd *cmd)
{
int segment = 0;
- int use_sg = (int) cmd->use_sg;
+ int use_sg = scsi_sg_count(cmd);
cp->data_len = 0;
- if (!use_sg)
- segment = ncr_scatter_no_sglist(np, cp, cmd);
- else if ((use_sg = map_scsi_sg_data(np, cmd)) > 0) {
- struct scatterlist *scatter = (struct scatterlist *)cmd->buffer;
+ use_sg = map_scsi_sg_data(np, cmd);
+ if (use_sg > 0) {
+ struct scatterlist *sg;
struct scr_tblmove *data;
if (use_sg > MAX_SCATTER) {
data = &cp->phys.data[MAX_SCATTER - use_sg];
- for (segment = 0; segment < use_sg; segment++) {
- dma_addr_t baddr = sg_dma_address(&scatter[segment]);
- unsigned int len = sg_dma_len(&scatter[segment]);
+ scsi_for_each_sg(cmd, sg, use_sg, segment) {
+ dma_addr_t baddr = sg_dma_address(sg);
+ unsigned int len = sg_dma_len(sg);
ncr_build_sge(np, &data[segment], baddr, len);
cp->data_len += len;
}
- } else {
+ } else
segment = -2;
- }
return segment;
}
**==========================================================
**
** Note: we have to return the correct value.
-** THERE IS NO SAVE DEFAULT VALUE.
+** THERE IS NO SAFE DEFAULT VALUE.
**
** Most NCR/SYMBIOS boards are delivered with a 40 Mhz clock.
** 53C860 and 53C875 rev. 1 support fast20 transfers but
return sts;
}
-irqreturn_t ncr53c8xx_intr(int irq, void *dev_id, struct pt_regs * regs)
+irqreturn_t ncr53c8xx_intr(int irq, void *dev_id)
{
unsigned long flags;
struct Scsi_Host *shost = (struct Scsi_Host *)dev_id;
unsigned long flags;
struct scsi_cmnd *done_list;
-#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS
- printk("ncr53c8xx_abort: pid=%lu serial_number=%ld\n",
- cmd->pid, cmd->serial_number);
-#else
- printk("ncr53c8xx_abort: command pid %lu\n", cmd->pid);
-#endif
+ printk("ncr53c8xx_abort: command pid %lu\n", cmd->serial_number);
NCR_LOCK_NCB(np, flags);
cmd->next_wcmd = NULL;
if (!(wcmd = np->waiting_list)) np->waiting_list = cmd;
else {
- while ((wcmd->next_wcmd) != 0)
+ while (wcmd->next_wcmd)
wcmd = (struct scsi_cmnd *) wcmd->next_wcmd;
wcmd->next_wcmd = (char *) cmd;
}
#ifdef DEBUG_WAITING_LIST
if (waiting_list) printk("%s: waiting_list=%lx processing sts=%d\n", ncr_name(np), (u_long) waiting_list, sts);
#endif
- while ((wcmd = waiting_list) != 0) {
+ while ((wcmd = waiting_list) != NULL) {
waiting_list = (struct scsi_cmnd *) wcmd->next_wcmd;
wcmd->next_wcmd = NULL;
if (sts == DID_OK) {
#undef next_wcmd
-static ssize_t show_ncr53c8xx_revision(struct class_device *dev, char *buf)
+static ssize_t show_ncr53c8xx_revision(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct Scsi_Host *host = class_to_shost(dev);
struct host_data *host_data = (struct host_data *)host->hostdata;
return snprintf(buf, 20, "0x%x\n", host_data->ncb->revision_id);
}
-static struct class_device_attribute ncr53c8xx_revision_attr = {
+static struct device_attribute ncr53c8xx_revision_attr = {
.attr = { .name = "revision", .mode = S_IRUGO, },
.show = show_ncr53c8xx_revision,
};
-static struct class_device_attribute *ncr53c8xx_host_attrs[] = {
+static struct device_attribute *ncr53c8xx_host_attrs[] = {
&ncr53c8xx_revision_attr,
NULL
};
module_param(ncr53c8xx, charp, 0);
#endif
+#ifndef MODULE
static int __init ncr53c8xx_setup(char *str)
{
return sym53c8xx__setup(str);
}
-#ifndef MODULE
__setup("ncr53c8xx=", ncr53c8xx_setup);
#endif
/* use SIMPLE TAG messages by default */
#ifdef SCSI_NCR_ALWAYS_SIMPLE_TAG
- np->order = M_SIMPLE_TAG;
+ np->order = SIMPLE_QUEUE_TAG;
#endif
spin_unlock_irqrestore(&np->smp_lock, flags);
}
-int ncr53c8xx_release(struct Scsi_Host *host)
+void ncr53c8xx_release(struct Scsi_Host *host)
{
- struct host_data *host_data;
+ struct host_data *host_data = shost_priv(host);
#ifdef DEBUG_NCR53C8XX
printk("ncr53c8xx: release\n");
#endif
- if (!host)
- return 1;
- host_data = (struct host_data *)host->hostdata;
- if (host_data && host_data->ncb)
+ if (host_data->ncb)
ncr_detach(host_data->ncb);
- return 1;
+ scsi_host_put(host);
}
static void ncr53c8xx_set_period(struct scsi_target *starget, int period)