Commit 04073775 authored by James Bottomley's avatar James Bottomley

Make the SPI transport parameters operate at the target level

Technically, the transfer agreement governs the I_T nexus (the
target) not the I_T_L nexus (the device), so make it operate
of the scsi_target structure.
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent a70be57b
......@@ -287,8 +287,9 @@ NCR_700_get_SXFER(struct scsi_device *SDp)
struct NCR_700_Host_Parameters *hostdata =
(struct NCR_700_Host_Parameters *)SDp->host->hostdata[0];
return NCR_700_offset_period_to_sxfer(hostdata, spi_offset(SDp),
spi_period(SDp));
return NCR_700_offset_period_to_sxfer(hostdata,
spi_offset(SDp->sdev_target),
spi_period(SDp->sdev_target));
}
struct Scsi_Host *
......@@ -803,7 +804,7 @@ process_extended_message(struct Scsi_Host *host,
}
if(NCR_700_is_flag_set(SCp->device, NCR_700_DEV_PRINT_SYNC_NEGOTIATION)) {
if(spi_offset(SCp->device) != 0)
if(spi_offset(SCp->device->sdev_target) != 0)
printk(KERN_INFO "scsi%d: (%d:%d) Synchronous at offset %d, period %dns\n",
host->host_no, pun, lun,
offset, period*4);
......@@ -813,8 +814,8 @@ process_extended_message(struct Scsi_Host *host,
NCR_700_clear_flag(SCp->device, NCR_700_DEV_PRINT_SYNC_NEGOTIATION);
}
spi_offset(SCp->device) = offset;
spi_period(SCp->device) = period;
spi_offset(SCp->device->sdev_target) = offset;
spi_period(SCp->device->sdev_target) = period;
NCR_700_set_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC);
......@@ -894,7 +895,8 @@ process_message(struct Scsi_Host *host, struct NCR_700_Host_Parameters *hostdata
case A_REJECT_MSG:
if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION)) {
/* Rejected our sync negotiation attempt */
spi_period(SCp->device) = spi_offset(SCp->device) = 0;
spi_period(SCp->device->sdev_target) =
spi_offset(SCp->device->sdev_target) = 0;
NCR_700_set_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC);
NCR_700_clear_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION);
} else if(SCp != NULL && NCR_700_is_flag_set(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING)) {
......@@ -1420,8 +1422,8 @@ NCR_700_start_command(struct scsi_cmnd *SCp)
NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC)) {
memcpy(&hostdata->msgout[count], NCR_700_SDTR_msg,
sizeof(NCR_700_SDTR_msg));
hostdata->msgout[count+3] = spi_period(SCp->device);
hostdata->msgout[count+4] = spi_offset(SCp->device);
hostdata->msgout[count+3] = spi_period(SCp->device->sdev_target);
hostdata->msgout[count+4] = spi_offset(SCp->device->sdev_target);
count += sizeof(NCR_700_SDTR_msg);
NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION);
}
......@@ -1999,10 +2001,11 @@ NCR_700_host_reset(struct scsi_cmnd * SCp)
}
STATIC void
NCR_700_set_period(struct scsi_device *SDp, int period)
NCR_700_set_period(struct scsi_target *STp, int period)
{
struct Scsi_Host *SHp = dev_to_shost(STp->dev.parent);
struct NCR_700_Host_Parameters *hostdata =
(struct NCR_700_Host_Parameters *)SDp->host->hostdata[0];
(struct NCR_700_Host_Parameters *)SHp->hostdata[0];
if(!hostdata->fast)
return;
......@@ -2010,17 +2013,18 @@ NCR_700_set_period(struct scsi_device *SDp, int period)
if(period < hostdata->min_period)
period = hostdata->min_period;
spi_period(SDp) = period;
NCR_700_clear_flag(SDp, NCR_700_DEV_NEGOTIATED_SYNC);
NCR_700_clear_flag(SDp, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION);
NCR_700_set_flag(SDp, NCR_700_DEV_PRINT_SYNC_NEGOTIATION);
spi_period(STp) = period;
spi_flags(STp) &= ~(NCR_700_DEV_NEGOTIATED_SYNC |
NCR_700_DEV_BEGIN_SYNC_NEGOTIATION);
spi_flags(STp) |= NCR_700_DEV_PRINT_SYNC_NEGOTIATION;
}
STATIC void
NCR_700_set_offset(struct scsi_device *SDp, int offset)
NCR_700_set_offset(struct scsi_target *STp, int offset)
{
struct Scsi_Host *SHp = dev_to_shost(STp->dev.parent);
struct NCR_700_Host_Parameters *hostdata =
(struct NCR_700_Host_Parameters *)SDp->host->hostdata[0];
(struct NCR_700_Host_Parameters *)SHp->hostdata[0];
int max_offset = hostdata->chip710
? NCR_710_MAX_OFFSET : NCR_700_MAX_OFFSET;
......@@ -2031,14 +2035,14 @@ NCR_700_set_offset(struct scsi_device *SDp, int offset)
offset = max_offset;
/* if we're currently async, make sure the period is reasonable */
if(spi_offset(SDp) == 0 && (spi_period(SDp) < hostdata->min_period ||
spi_period(SDp) > 0xff))
spi_period(SDp) = hostdata->min_period;
spi_offset(SDp) = offset;
NCR_700_clear_flag(SDp, NCR_700_DEV_NEGOTIATED_SYNC);
NCR_700_clear_flag(SDp, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION);
NCR_700_set_flag(SDp, NCR_700_DEV_PRINT_SYNC_NEGOTIATION);
if(spi_offset(STp) == 0 && (spi_period(STp) < hostdata->min_period ||
spi_period(STp) > 0xff))
spi_period(STp) = hostdata->min_period;
spi_offset(STp) = offset;
spi_flags(STp) &= ~(NCR_700_DEV_NEGOTIATED_SYNC |
NCR_700_DEV_BEGIN_SYNC_NEGOTIATION);
spi_flags(STp) |= NCR_700_DEV_PRINT_SYNC_NEGOTIATION;
}
......@@ -2058,10 +2062,11 @@ NCR_700_slave_configure(struct scsi_device *SDp)
}
if(hostdata->fast) {
/* Find the correct offset and period via domain validation */
spi_dv_device(SDp);
if (!spi_initial_dv(SDp->sdev_target))
spi_dv_device(SDp);
} else {
spi_offset(SDp) = 0;
spi_period(SDp) = 0;
spi_offset(SDp->sdev_target) = 0;
spi_period(SDp->sdev_target) = 0;
}
return 0;
}
......
......@@ -121,22 +121,22 @@ NCR_700_get_depth(struct scsi_device *SDp)
static inline int
NCR_700_is_flag_set(struct scsi_device *SDp, __u32 flag)
{
return (((unsigned long)SDp->hostdata) & flag) == flag;
return (spi_flags(SDp->sdev_target) & flag) == flag;
}
static inline int
NCR_700_is_flag_clear(struct scsi_device *SDp, __u32 flag)
{
return (((unsigned long)SDp->hostdata) & flag) == 0;
return (spi_flags(SDp->sdev_target) & flag) == 0;
}
static inline void
NCR_700_set_flag(struct scsi_device *SDp, __u32 flag)
{
SDp->hostdata = (void *)((long)SDp->hostdata | (flag & 0xffff0000));
spi_flags(SDp->sdev_target) |= flag;
}
static inline void
NCR_700_clear_flag(struct scsi_device *SDp, __u32 flag)
{
SDp->hostdata = (void *)((long)SDp->hostdata & ~(flag & 0xffff0000));
spi_flags(SDp->sdev_target) &= ~flag;
}
struct NCR_700_command_slot {
......
......@@ -99,6 +99,9 @@
#include <linux/mca.h>
#include <asm/io.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>
#include "53c700.h"
#include "NCR_D700.h"
......
......@@ -50,6 +50,9 @@
#include <asm/delay.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>
#include "lasi700.h"
#include "53c700.h"
......
......@@ -1739,3 +1739,30 @@ scsi_device_resume(struct scsi_device *sdev)
}
EXPORT_SYMBOL(scsi_device_resume);
static int
device_quiesce_fn(struct device *dev, void *data)
{
scsi_device_quiesce(to_scsi_device(dev));
return 0;
}
void
scsi_target_quiesce(struct scsi_target *starget)
{
device_for_each_child(&starget->dev, NULL, device_quiesce_fn);
}
EXPORT_SYMBOL(scsi_target_quiesce);
static int
device_resume_fn(struct device *dev, void *data)
{
scsi_device_resume(to_scsi_device(dev));
return 0;
}
void
scsi_target_resume(struct scsi_target *starget)
{
device_for_each_child(&starget->dev, NULL, device_resume_fn);
}
EXPORT_SYMBOL(scsi_target_resume);
This diff is collapsed.
......@@ -36,6 +36,9 @@
#include <linux/eisa.h>
#include <linux/interrupt.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>
#include "53c700.h"
......
......@@ -1096,7 +1096,8 @@ static int sym53c8xx_slave_configure(struct scsi_device *device)
lp->s.scdev_depth = depth_to_use;
sym_tune_dev_queuing(np, device->id, device->lun, reqtags);
spi_dv_device(device);
if (!spi_initial_dv(device->sdev_target))
spi_dv_device(device);
return 0;
}
......@@ -2304,35 +2305,39 @@ static void __devexit sym2_remove(struct pci_dev *pdev)
attach_count--;
}
static void sym2_get_offset(struct scsi_device *sdev)
static void sym2_get_offset(struct scsi_target *starget)
{
struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
struct sym_tcb *tp = &np->target[sdev->id];
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
struct sym_tcb *tp = &np->target[starget->id];
spi_offset(sdev) = tp->tinfo.curr.offset;
spi_offset(starget) = tp->tinfo.curr.offset;
}
static void sym2_set_offset(struct scsi_device *sdev, int offset)
static void sym2_set_offset(struct scsi_target *starget, int offset)
{
struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
struct sym_tcb *tp = &np->target[sdev->id];
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
struct sym_tcb *tp = &np->target[starget->id];
tp->tinfo.goal.offset = offset;
}
static void sym2_get_period(struct scsi_device *sdev)
static void sym2_get_period(struct scsi_target *starget)
{
struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
struct sym_tcb *tp = &np->target[sdev->id];
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
struct sym_tcb *tp = &np->target[starget->id];
spi_period(sdev) = tp->tinfo.curr.period;
spi_period(starget) = tp->tinfo.curr.period;
}
static void sym2_set_period(struct scsi_device *sdev, int period)
static void sym2_set_period(struct scsi_target *starget, int period)
{
struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
struct sym_tcb *tp = &np->target[sdev->id];
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
struct sym_tcb *tp = &np->target[starget->id];
/* have to have DT for these transfers */
if (period <= np->minsync)
......@@ -2341,18 +2346,20 @@ static void sym2_set_period(struct scsi_device *sdev, int period)
tp->tinfo.goal.period = period;
}
static void sym2_get_width(struct scsi_device *sdev)
static void sym2_get_width(struct scsi_target *starget)
{
struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
struct sym_tcb *tp = &np->target[sdev->id];
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
struct sym_tcb *tp = &np->target[starget->id];
spi_width(sdev) = tp->tinfo.curr.width ? 1 : 0;
spi_width(starget) = tp->tinfo.curr.width ? 1 : 0;
}
static void sym2_set_width(struct scsi_device *sdev, int width)
static void sym2_set_width(struct scsi_target *starget, int width)
{
struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
struct sym_tcb *tp = &np->target[sdev->id];
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
struct sym_tcb *tp = &np->target[starget->id];
/* It is illegal to have DT set on narrow transfers */
if (width == 0)
......@@ -2361,18 +2368,20 @@ static void sym2_set_width(struct scsi_device *sdev, int width)
tp->tinfo.goal.width = width;
}
static void sym2_get_dt(struct scsi_device *sdev)
static void sym2_get_dt(struct scsi_target *starget)
{
struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
struct sym_tcb *tp = &np->target[sdev->id];
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
struct sym_tcb *tp = &np->target[starget->id];
spi_dt(sdev) = (tp->tinfo.curr.options & PPR_OPT_DT) ? 1 : 0;
spi_dt(starget) = (tp->tinfo.curr.options & PPR_OPT_DT) ? 1 : 0;
}
static void sym2_set_dt(struct scsi_device *sdev, int dt)
static void sym2_set_dt(struct scsi_target *starget, int dt)
{
struct sym_hcb *np = ((struct host_data *)sdev->host->hostdata)->ncb;
struct sym_tcb *tp = &np->target[sdev->id];
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
struct sym_tcb *tp = &np->target[starget->id];
if (dt)
tp->tinfo.goal.options |= PPR_OPT_DT;
......
......@@ -35,45 +35,49 @@ struct spi_transport_attrs {
unsigned int rd_strm:1; /* Read streaming enabled */
unsigned int rti:1; /* Retain Training Information */
unsigned int pcomp_en:1;/* Precompensation enabled */
unsigned int initial_dv:1; /* DV done to this target yet */
unsigned long flags; /* flags field for drivers to use */
/* Private Fields */
unsigned int dv_pending:1; /* Internal flag */
struct semaphore dv_sem; /* semaphore to serialise dv */
};
/* accessor functions */
#define spi_period(x) (((struct spi_transport_attrs *)&(x)->sdev_data)->period)
#define spi_offset(x) (((struct spi_transport_attrs *)&(x)->sdev_data)->offset)
#define spi_width(x) (((struct spi_transport_attrs *)&(x)->sdev_data)->width)
#define spi_iu(x) (((struct spi_transport_attrs *)&(x)->sdev_data)->iu)
#define spi_dt(x) (((struct spi_transport_attrs *)&(x)->sdev_data)->dt)
#define spi_qas(x) (((struct spi_transport_attrs *)&(x)->sdev_data)->qas)
#define spi_wr_flow(x) (((struct spi_transport_attrs *)&(x)->sdev_data)->wr_flow)
#define spi_rd_strm(x) (((struct spi_transport_attrs *)&(x)->sdev_data)->rd_strm)
#define spi_rti(x) (((struct spi_transport_attrs *)&(x)->sdev_data)->rti)
#define spi_pcomp_en(x) (((struct spi_transport_attrs *)&(x)->sdev_data)->pcomp_en)
#define spi_period(x) (((struct spi_transport_attrs *)&(x)->starget_data)->period)
#define spi_offset(x) (((struct spi_transport_attrs *)&(x)->starget_data)->offset)
#define spi_width(x) (((struct spi_transport_attrs *)&(x)->starget_data)->width)
#define spi_iu(x) (((struct spi_transport_attrs *)&(x)->starget_data)->iu)
#define spi_dt(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dt)
#define spi_qas(x) (((struct spi_transport_attrs *)&(x)->starget_data)->qas)
#define spi_wr_flow(x) (((struct spi_transport_attrs *)&(x)->starget_data)->wr_flow)
#define spi_rd_strm(x) (((struct spi_transport_attrs *)&(x)->starget_data)->rd_strm)
#define spi_rti(x) (((struct spi_transport_attrs *)&(x)->starget_data)->rti)
#define spi_pcomp_en(x) (((struct spi_transport_attrs *)&(x)->starget_data)->pcomp_en)
#define spi_initial_dv(x) (((struct spi_transport_attrs *)&(x)->starget_data)->initial_dv)
#define spi_flags(x) (((struct spi_transport_attrs *)&(x)->starget_data)->flags)
/* The functions by which the transport class and the driver communicate */
struct spi_function_template {
void (*get_period)(struct scsi_device *);
void (*set_period)(struct scsi_device *, int);
void (*get_offset)(struct scsi_device *);
void (*set_offset)(struct scsi_device *, int);
void (*get_width)(struct scsi_device *);
void (*set_width)(struct scsi_device *, int);
void (*get_iu)(struct scsi_device *);
void (*set_iu)(struct scsi_device *, int);
void (*get_dt)(struct scsi_device *);
void (*set_dt)(struct scsi_device *, int);
void (*get_qas)(struct scsi_device *);
void (*set_qas)(struct scsi_device *, int);
void (*get_wr_flow)(struct scsi_device *);
void (*set_wr_flow)(struct scsi_device *, int);
void (*get_rd_strm)(struct scsi_device *);
void (*set_rd_strm)(struct scsi_device *, int);
void (*get_rti)(struct scsi_device *);
void (*set_rti)(struct scsi_device *, int);
void (*get_pcomp_en)(struct scsi_device *);
void (*set_pcomp_en)(struct scsi_device *, int);
void (*get_period)(struct scsi_target *);
void (*set_period)(struct scsi_target *, int);
void (*get_offset)(struct scsi_target *);
void (*set_offset)(struct scsi_target *, int);
void (*get_width)(struct scsi_target *);
void (*set_width)(struct scsi_target *, int);
void (*get_iu)(struct scsi_target *);
void (*set_iu)(struct scsi_target *, int);
void (*get_dt)(struct scsi_target *);
void (*set_dt)(struct scsi_target *, int);
void (*get_qas)(struct scsi_target *);
void (*set_qas)(struct scsi_target *, int);
void (*get_wr_flow)(struct scsi_target *);
void (*set_wr_flow)(struct scsi_target *, int);
void (*get_rd_strm)(struct scsi_target *);
void (*set_rd_strm)(struct scsi_target *, int);
void (*get_rti)(struct scsi_target *);
void (*set_rti)(struct scsi_target *, int);
void (*get_pcomp_en)(struct scsi_target *);
void (*set_pcomp_en)(struct scsi_target *, int);
/* The driver sets these to tell the transport class it
* wants the attributes displayed in sysfs. If the show_ flag
* is not set, the attribute will be private to the transport
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment