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 */
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);
......@@ -27,13 +27,14 @@
#include <asm/scatterlist.h>
#include <asm/io.h>
#include <scsi/scsi.h>
#include "scsi_priv.h"
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_request.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_spi.h>
#define SPI_PRINTK(x, l, f, a...) printk(l "scsi(%d:%d:%d:%d): " f, (x)->host->host_no, (x)->channel, (x)->id, (x)->lun , ##a)
#define SPI_PRINTK(x, l, f, a...) dev_printk(l, &(x)->dev, f , ##a)
static void transport_class_release(struct class_device *class_dev);
......@@ -44,8 +45,8 @@ static void transport_class_release(struct class_device *class_dev);
#define SPI_MAX_ECHO_BUFFER_SIZE 4096
/* Private data accessors (keep these out of the header file) */
#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->sdev_data)->dv_pending)
#define spi_dv_sem(x) (((struct spi_transport_attrs *)&(x)->sdev_data)->dv_sem)
#define spi_dv_pending(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_pending)
#define spi_dv_sem(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_sem)
struct spi_internal {
struct scsi_transport_template t;
......@@ -95,28 +96,29 @@ static void __exit spi_transport_exit(void)
class_unregister(&spi_transport_class);
}
static int spi_setup_transport_attrs(struct scsi_device *sdev)
static int spi_setup_transport_attrs(struct scsi_target *starget)
{
spi_period(sdev) = -1; /* illegal value */
spi_offset(sdev) = 0; /* async */
spi_width(sdev) = 0; /* narrow */
spi_iu(sdev) = 0; /* no IU */
spi_dt(sdev) = 0; /* ST */
spi_qas(sdev) = 0;
spi_wr_flow(sdev) = 0;
spi_rd_strm(sdev) = 0;
spi_rti(sdev) = 0;
spi_pcomp_en(sdev) = 0;
spi_dv_pending(sdev) = 0;
init_MUTEX(&spi_dv_sem(sdev));
spi_period(starget) = -1; /* illegal value */
spi_offset(starget) = 0; /* async */
spi_width(starget) = 0; /* narrow */
spi_iu(starget) = 0; /* no IU */
spi_dt(starget) = 0; /* ST */
spi_qas(starget) = 0;
spi_wr_flow(starget) = 0;
spi_rd_strm(starget) = 0;
spi_rti(starget) = 0;
spi_pcomp_en(starget) = 0;
spi_dv_pending(starget) = 0;
spi_initial_dv(starget) = 0;
init_MUTEX(&spi_dv_sem(starget));
return 0;
}
static void transport_class_release(struct class_device *class_dev)
{
struct scsi_device *sdev = transport_class_to_sdev(class_dev);
put_device(&sdev->sdev_gendev);
struct scsi_target *starget = transport_class_to_starget(class_dev);
put_device(&starget->dev);
}
#define spi_transport_show_function(field, format_string) \
......@@ -124,12 +126,13 @@ static void transport_class_release(struct class_device *class_dev)
static ssize_t \
show_spi_transport_##field(struct class_device *cdev, char *buf) \
{ \
struct scsi_device *sdev = transport_class_to_sdev(cdev); \
struct scsi_target *starget = transport_class_to_starget(cdev); \
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \
struct spi_transport_attrs *tp; \
struct spi_internal *i = to_spi_internal(sdev->host->transportt); \
tp = (struct spi_transport_attrs *)&sdev->sdev_data; \
struct spi_internal *i = to_spi_internal(shost->transportt); \
tp = (struct spi_transport_attrs *)&starget->starget_data; \
if (i->f->get_##field) \
i->f->get_##field(sdev); \
i->f->get_##field(starget); \
return snprintf(buf, 20, format_string, tp->field); \
}
......@@ -139,11 +142,12 @@ store_spi_transport_##field(struct class_device *cdev, const char *buf, \
size_t count) \
{ \
int val; \
struct scsi_device *sdev = transport_class_to_sdev(cdev); \
struct spi_internal *i = to_spi_internal(sdev->host->transportt); \
struct scsi_target *starget = transport_class_to_starget(cdev); \
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \
struct spi_internal *i = to_spi_internal(shost->transportt); \
\
val = simple_strtoul(buf, NULL, 0); \
i->f->set_##field(sdev, val); \
i->f->set_##field(starget, val); \
return count; \
}
......@@ -168,8 +172,13 @@ spi_transport_rd_attr(pcomp_en, "%d\n");
static ssize_t
store_spi_revalidate(struct class_device *cdev, const char *buf, size_t count)
{
struct scsi_device *sdev = transport_class_to_sdev(cdev);
struct scsi_target *starget = transport_class_to_starget(cdev);
/* FIXME: we're relying on an awful lot of device internals
* here. We really need a function to get the first available
* child */
struct device *dev = container_of(starget->dev.children.next, struct device, node);
struct scsi_device *sdev = to_scsi_device(dev);
spi_dv_device(sdev);
return count;
}
......@@ -180,15 +189,16 @@ static CLASS_DEVICE_ATTR(revalidate, S_IWUSR, NULL, store_spi_revalidate);
static ssize_t show_spi_transport_period(struct class_device *cdev, char *buf)
{
struct scsi_device *sdev = transport_class_to_sdev(cdev);
struct scsi_target *starget = transport_class_to_starget(cdev);
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct spi_transport_attrs *tp;
const char *str;
struct spi_internal *i = to_spi_internal(sdev->host->transportt);
struct spi_internal *i = to_spi_internal(shost->transportt);
tp = (struct spi_transport_attrs *)&sdev->sdev_data;
tp = (struct spi_transport_attrs *)&starget->starget_data;
if (i->f->get_period)
i->f->get_period(sdev);
i->f->get_period(starget);
switch(tp->period) {
......@@ -212,8 +222,9 @@ static ssize_t
store_spi_transport_period(struct class_device *cdev, const char *buf,
size_t count)
{
struct scsi_device *sdev = transport_class_to_sdev(cdev);
struct spi_internal *i = to_spi_internal(sdev->host->transportt);
struct scsi_target *starget = transport_class_to_starget(cdev);
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
struct spi_internal *i = to_spi_internal(shost->transportt);
int j, period = -1;
for (j = 0; j < SPI_STATIC_PPR; j++) {
......@@ -246,7 +257,7 @@ store_spi_transport_period(struct class_device *cdev, const char *buf,
if (period > 0xff)
period = 0xff;
i->f->set_period(sdev, period);
i->f->set_period(starget, period);
return count;
}
......@@ -257,7 +268,7 @@ static CLASS_DEVICE_ATTR(period, S_IRUGO | S_IWUSR,
#define DV_SET(x, y) \
if(i->f->set_##x) \
i->f->set_##x(sdev, y)
i->f->set_##x(sdev->sdev_target, y)
#define DV_LOOPS 3
#define DV_TIMEOUT (10*HZ)
......@@ -325,7 +336,7 @@ spi_dv_device_echo_buffer(struct scsi_request *sreq, u8 *buffer,
DV_TIMEOUT, DV_RETRIES);
if(sreq->sr_result || !scsi_device_online(sdev)) {
scsi_device_set_state(sdev, SDEV_QUIESCE);
SPI_PRINTK(sdev, KERN_ERR, "Write Buffer failure %x\n", sreq->sr_result);
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Write Buffer failure %x\n", sreq->sr_result);
return 0;
}
......@@ -401,8 +412,8 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
/* OK, retrain, fallback */
if (i->f->get_period)
i->f->get_period(sdev);
newperiod = spi_period(sdev);
i->f->get_period(sdev->sdev_target);
newperiod = spi_period(sdev->sdev_target);
period = newperiod > period ? newperiod : period;
if (period < 0x0d)
period++;
......@@ -411,11 +422,11 @@ spi_dv_retrain(struct scsi_request *sreq, u8 *buffer, u8 *ptr,
if (unlikely(period > 0xff || period == prevperiod)) {
/* Total failure; set to async and return */
SPI_PRINTK(sdev, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n");
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Failure, dropping back to Asynchronous\n");
DV_SET(offset, 0);
return 0;
}
SPI_PRINTK(sdev, KERN_ERR, "Domain Validation detected failure, dropping back\n");
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation detected failure, dropping back\n");
DV_SET(period, period);
prevperiod = period;
}
......@@ -486,20 +497,20 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
DV_SET(width, 0);
if (!spi_dv_device_compare_inquiry(sreq, buffer, buffer, DV_LOOPS)) {
SPI_PRINTK(sdev, KERN_ERR, "Domain Validation Initial Inquiry Failed\n");
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Domain Validation Initial Inquiry Failed\n");
/* FIXME: should probably offline the device here? */
return;
}
/* test width */
if (i->f->set_width && sdev->wdtr) {
i->f->set_width(sdev, 1);
i->f->set_width(sdev->sdev_target, 1);
if (!spi_dv_device_compare_inquiry(sreq, buffer,
buffer + len,
DV_LOOPS)) {
SPI_PRINTK(sdev, KERN_ERR, "Wide Transfers Fail\n");
i->f->set_width(sdev, 0);
SPI_PRINTK(sdev->sdev_target, KERN_ERR, "Wide Transfers Fail\n");
i->f->set_width(sdev->sdev_target, 0);
}
}
......@@ -521,11 +532,11 @@ spi_dv_device_internal(struct scsi_request *sreq, u8 *buffer)
* test, now try an echo buffer test (if the device allows it) */
if ((len = spi_dv_device_get_echo_buffer(sreq, buffer)) == 0) {
SPI_PRINTK(sdev, KERN_INFO, "Domain Validation skipping write tests\n");
SPI_PRINTK(sdev->sdev_target, KERN_INFO, "Domain Validation skipping write tests\n");
return;
}
if (len > SPI_MAX_ECHO_BUFFER_SIZE) {
SPI_PRINTK(sdev, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE);
SPI_PRINTK(sdev->sdev_target, KERN_WARNING, "Echo buffer size %d is too big, trimming to %d\n", len, SPI_MAX_ECHO_BUFFER_SIZE);
len = SPI_MAX_ECHO_BUFFER_SIZE;
}
......@@ -547,6 +558,7 @@ void
spi_dv_device(struct scsi_device *sdev)
{
struct scsi_request *sreq = scsi_allocate_request(sdev, GFP_KERNEL);
struct scsi_target *starget = sdev->sdev_target;
u8 *buffer;
const int len = SPI_MAX_ECHO_BUFFER_SIZE*2;
......@@ -563,22 +575,28 @@ spi_dv_device(struct scsi_device *sdev)
memset(buffer, 0, len);
/* We need to verify that the actual device will quiesce; the
* later target quiesce is just a nice to have */
if (unlikely(scsi_device_quiesce(sdev)))
goto out_free;
spi_dv_pending(sdev) = 1;
down(&spi_dv_sem(sdev));
scsi_target_quiesce(starget);
SPI_PRINTK(sdev, KERN_INFO, "Beginning Domain Validation\n");
spi_dv_pending(starget) = 1;
down(&spi_dv_sem(starget));
SPI_PRINTK(starget, KERN_INFO, "Beginning Domain Validation\n");
spi_dv_device_internal(sreq, buffer);
SPI_PRINTK(sdev, KERN_INFO, "Ending Domain Validation\n");
SPI_PRINTK(starget, KERN_INFO, "Ending Domain Validation\n");
up(&spi_dv_sem(starget));
spi_dv_pending(starget) = 0;
up(&spi_dv_sem(sdev));
spi_dv_pending(sdev) = 0;
scsi_target_resume(starget);
scsi_device_resume(sdev);
spi_initial_dv(starget) = 1;
out_free:
kfree(buffer);
......@@ -602,7 +620,7 @@ spi_dv_device_work_wrapper(void *data)
kfree(wqw);
spi_dv_device(sdev);
spi_dv_pending(sdev) = 0;
spi_dv_pending(sdev->sdev_target) = 0;
scsi_device_put(sdev);
}
......@@ -625,15 +643,15 @@ spi_schedule_dv_device(struct scsi_device *sdev)
if (unlikely(!wqw))
return;
if (unlikely(spi_dv_pending(sdev))) {
if (unlikely(spi_dv_pending(sdev->sdev_target))) {
kfree(wqw);
return;
}
/* Set pending early (dv_device doesn't check it, only sets it) */
spi_dv_pending(sdev) = 1;
spi_dv_pending(sdev->sdev_target) = 1;
if (unlikely(scsi_device_get(sdev))) {
kfree(wqw);
spi_dv_pending(sdev) = 0;
spi_dv_pending(sdev->sdev_target) = 0;
return;
}
......@@ -666,10 +684,10 @@ spi_attach_transport(struct spi_function_template *ft)
memset(i, 0, sizeof(struct spi_internal));
i->t.device_attrs = &i->attrs[0];
i->t.device_class = &spi_transport_class;
i->t.device_setup = &spi_setup_transport_attrs;
i->t.device_size = sizeof(struct spi_transport_attrs);
i->t.target_attrs = &i->attrs[0];
i->t.target_class = &spi_transport_class;
i->t.target_setup = &spi_setup_transport_attrs;
i->t.target_size = sizeof(struct spi_transport_attrs);
i->f = ft;
SETUP_ATTRIBUTE(period);
......
......@@ -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,6 +1096,7 @@ 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);
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