From 09345f65058bb927f3b3f4c33421f83ba8eeb5f8 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 27 Jun 2007 16:32:39 +0900 Subject: [SCSI] add srp transport class This adds srp transport class that works with ib_srp and ibmvscsi. It creates only /sys/class/{srp_host,srp_remote_ports} and srp_remote_ports has only "port_id" attribute. viola:/sys/class/srp_remote_ports/port-0:1# ls device port_id subsystem uevent viola:/sys/class/srp_remote_ports/port-0:1# cat port_id 4c:49:4e:55:58:20:56:49:4f:00:00:00:00:00:00:00 Signed-off-by: FUJITA Tomonori Signed-off-by: James Bottomley --- include/scsi/scsi_transport_srp.h | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 include/scsi/scsi_transport_srp.h (limited to 'include') diff --git a/include/scsi/scsi_transport_srp.h b/include/scsi/scsi_transport_srp.h new file mode 100644 index 000000000000..adbfca402a69 --- /dev/null +++ b/include/scsi/scsi_transport_srp.h @@ -0,0 +1,32 @@ +#ifndef SCSI_TRANSPORT_SRP_H +#define SCSI_TRANSPORT_SRP_H + +#include +#include +#include + +struct srp_rport_identifiers { + u8 port_id[16]; +}; + +struct srp_rport { + struct device dev; + + u8 port_id[16]; +}; + +struct srp_function_template { + /* later */ +}; + +extern struct scsi_transport_template * +srp_attach_transport(struct srp_function_template *); +extern void srp_release_transport(struct scsi_transport_template *); + +extern struct srp_rport *srp_rport_add(struct Scsi_Host *, + struct srp_rport_identifiers *); +extern void srp_rport_del(struct srp_rport *); + +extern void srp_remove_host(struct Scsi_Host *); + +#endif -- cgit v1.2.3 From aebd5e476ecc8ceb53577b20f2a352ff4ceffd8d Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 11 Jul 2007 15:08:15 +0900 Subject: [SCSI] transport_srp: add rport roles attribute This adds a 'roles' attribute to rport like transport_fc. The role can be initiator or target. That is, the initiator driver creates target remote ports and the target driver creates initiator remote ports. Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/infiniband/ulp/srp/ib_srp.c | 1 + drivers/scsi/ibmvscsi/ibmvscsi.c | 1 + drivers/scsi/scsi_transport_srp.c | 29 ++++++++++++++++++++++++++++- include/scsi/scsi_transport_srp.h | 5 +++++ 4 files changed, 35 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index d8d056e004bb..e616c4fc6ff0 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -1545,6 +1545,7 @@ static int srp_add_target(struct srp_host *host, struct srp_target_port *target) memcpy(ids.port_id, &target->id_ext, 8); memcpy(ids.port_id + 8, &target->ioc_guid, 8); + ids.roles = SRP_RPORT_ROLE_TARGET; rport = srp_rport_add(target->scsi_host, &ids); if (IS_ERR(rport)) { scsi_remove_host(target->scsi_host); diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index e6f937eeb78f..93bd01b1e4b5 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -1599,6 +1599,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) /* we don't have a proper target_port_id so let's use the fake one */ memcpy(ids.port_id, hostdata->madapter_info.partition_name, sizeof(ids.port_id)); + ids.roles = SRP_RPORT_ROLE_TARGET; rport = srp_rport_add(host, &ids); if (IS_ERR(rport)) goto add_srp_port_failed; diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c index dcb3d2aa780c..608abd8aef20 100644 --- a/drivers/scsi/scsi_transport_srp.c +++ b/drivers/scsi/scsi_transport_srp.c @@ -37,7 +37,7 @@ struct srp_host_attrs { #define to_srp_host_attrs(host) ((struct srp_host_attrs *)(host)->shost_data) #define SRP_HOST_ATTRS 0 -#define SRP_RPORT_ATTRS 3 +#define SRP_RPORT_ATTRS 2 struct srp_internal { struct scsi_transport_template t; @@ -107,6 +107,31 @@ show_srp_rport_id(struct class_device *cdev, char *buf) static CLASS_DEVICE_ATTR(port_id, S_IRUGO, show_srp_rport_id, NULL); +static const struct { + u32 value; + char *name; +} srp_rport_role_names[] = { + {SRP_RPORT_ROLE_INITIATOR, "SRP Initiator"}, + {SRP_RPORT_ROLE_TARGET, "SRP Target"}, +}; + +static ssize_t +show_srp_rport_roles(struct class_device *cdev, char *buf) +{ + struct srp_rport *rport = transport_class_to_srp_rport(cdev); + int i; + char *name = NULL; + + for (i = 0; i < ARRAY_SIZE(srp_rport_role_names); i++) + if (srp_rport_role_names[i].value == rport->roles) { + name = srp_rport_role_names[i].name; + break; + } + return sprintf(buf, "%s\n", name ? : "unknown"); +} + +static CLASS_DEVICE_ATTR(roles, S_IRUGO, show_srp_rport_roles, NULL); + static void srp_rport_release(struct device *dev) { struct srp_rport *rport = dev_to_rport(dev); @@ -182,6 +207,7 @@ struct srp_rport *srp_rport_add(struct Scsi_Host *shost, rport->dev.release = srp_rport_release; memcpy(rport->port_id, ids->port_id, sizeof(rport->port_id)); + rport->roles = ids->roles; id = atomic_inc_return(&to_srp_host_attrs(shost)->next_port_id); sprintf(rport->dev.bus_id, "port-%d:%d", shost->host_no, id); @@ -266,6 +292,7 @@ srp_attach_transport(struct srp_function_template *ft) count = 0; SETUP_RPORT_ATTRIBUTE_RD(port_id); + SETUP_RPORT_ATTRIBUTE_RD(roles); i->rport_attrs[count] = NULL; i->f = ft; diff --git a/include/scsi/scsi_transport_srp.h b/include/scsi/scsi_transport_srp.h index adbfca402a69..08b4a28a77b8 100644 --- a/include/scsi/scsi_transport_srp.h +++ b/include/scsi/scsi_transport_srp.h @@ -5,14 +5,19 @@ #include #include +#define SRP_RPORT_ROLE_INITIATOR 0 +#define SRP_RPORT_ROLE_TARGET 1 + struct srp_rport_identifiers { u8 port_id[16]; + u8 roles; }; struct srp_rport { struct device dev; u8 port_id[16]; + u8 roles; }; struct srp_function_template { -- cgit v1.2.3 From 2c47f9efbedbe5749b6bb16e59bc11d6e460855f Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 11 Jul 2007 15:08:17 +0900 Subject: [SCSI] tgt: add I_T nexus support tgt uses scsi_host as I_T nexus. This works for ibmvstgt because it creates one scsi_host for one initiator. However, other target drivers don't work like that. This adds I_T nexus support, which enable one scsi_host to handle multiple initiators. New scsi_tgt_it_nexus_create/destroy functions are expected be called transport classes. For example, ibmvstgt creates an initiator remote port, then the srp transport calls tgt_it_nexus_create. tgt doesn't manages I_T nexus, instead it tells tgtd, user-space daemon, to create a new I_T nexus. On the receiving the response from tgtd, tgt calls shost->transportt->it_nexus_response. transports should notify a lld. The srp transport uses it_nexus_response callback in srp_function_template to do that. Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_tgt_if.c | 42 +++++++++++++++++++--- drivers/scsi/scsi_tgt_lib.c | 83 ++++++++++++++++++++++++++++++++++++------- drivers/scsi/scsi_tgt_priv.h | 22 +++++++----- include/scsi/scsi_host.h | 2 +- include/scsi/scsi_tgt.h | 8 +++-- include/scsi/scsi_tgt_if.h | 35 +++++++++++++----- include/scsi/scsi_transport.h | 6 ++++ 7 files changed, 161 insertions(+), 37 deletions(-) (limited to 'include') diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c index ca22ddf81746..9815a1a2db24 100644 --- a/drivers/scsi/scsi_tgt_if.c +++ b/drivers/scsi/scsi_tgt_if.c @@ -102,7 +102,8 @@ static int tgt_uspace_send_event(u32 type, struct tgt_event *p) return 0; } -int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 tag) +int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 itn_id, + struct scsi_lun *lun, u64 tag) { struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); struct tgt_event ev; @@ -110,6 +111,7 @@ int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 ta memset(&ev, 0, sizeof(ev)); ev.p.cmd_req.host_no = shost->host_no; + ev.p.cmd_req.itn_id = itn_id; ev.p.cmd_req.data_len = cmd->request_bufflen; memcpy(ev.p.cmd_req.scb, cmd->cmnd, sizeof(ev.p.cmd_req.scb)); memcpy(ev.p.cmd_req.lun, lun, sizeof(ev.p.cmd_req.lun)); @@ -127,7 +129,7 @@ int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 ta return err; } -int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag) +int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 itn_id, u64 tag) { struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); struct tgt_event ev; @@ -135,6 +137,7 @@ int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag) memset(&ev, 0, sizeof(ev)); ev.p.cmd_done.host_no = shost->host_no; + ev.p.cmd_done.itn_id = itn_id; ev.p.cmd_done.tag = tag; ev.p.cmd_done.result = cmd->result; @@ -149,14 +152,15 @@ int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag) return err; } -int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, - struct scsi_lun *scsilun, void *data) +int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 itn_id, int function, + u64 tag, struct scsi_lun *scsilun, void *data) { struct tgt_event ev; int err; memset(&ev, 0, sizeof(ev)); ev.p.tsk_mgmt_req.host_no = host_no; + ev.p.tsk_mgmt_req.itn_id = itn_id; ev.p.tsk_mgmt_req.function = function; ev.p.tsk_mgmt_req.tag = tag; memcpy(ev.p.tsk_mgmt_req.lun, scsilun, sizeof(ev.p.tsk_mgmt_req.lun)); @@ -172,6 +176,29 @@ int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, return err; } +int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 itn_id, + int function, char *initiator_id) +{ + struct tgt_event ev; + int err; + + memset(&ev, 0, sizeof(ev)); + ev.p.it_nexus_req.host_no = host_no; + ev.p.it_nexus_req.function = function; + ev.p.it_nexus_req.itn_id = itn_id; + if (initiator_id) + strncpy(ev.p.it_nexus_req.initiator_id, initiator_id, + sizeof(ev.p.it_nexus_req.initiator_id)); + + dprintk("%d %x %llx\n", host_no, function, (unsigned long long)itn_id); + + err = tgt_uspace_send_event(TGT_KEVENT_IT_NEXUS_REQ, &ev); + if (err) + eprintk("tx buf is full, could not send\n"); + + return err; +} + static int event_recv_msg(struct tgt_event *ev) { int err = 0; @@ -179,6 +206,7 @@ static int event_recv_msg(struct tgt_event *ev) switch (ev->hdr.type) { case TGT_UEVENT_CMD_RSP: err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no, + ev->p.cmd_rsp.itn_id, ev->p.cmd_rsp.result, ev->p.cmd_rsp.tag, ev->p.cmd_rsp.uaddr, @@ -189,9 +217,15 @@ static int event_recv_msg(struct tgt_event *ev) break; case TGT_UEVENT_TSK_MGMT_RSP: err = scsi_tgt_kspace_tsk_mgmt(ev->p.tsk_mgmt_rsp.host_no, + ev->p.tsk_mgmt_rsp.itn_id, ev->p.tsk_mgmt_rsp.mid, ev->p.tsk_mgmt_rsp.result); break; + case TGT_UEVENT_IT_NEXUS_RSP: + err = scsi_tgt_kspace_it_nexus_rsp(ev->p.it_nexus_rsp.host_no, + ev->p.it_nexus_rsp.itn_id, + ev->p.it_nexus_rsp.result); + break; default: eprintk("unknown type %d\n", ev->hdr.type); err = -EINVAL; diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 371b69c110bc..fa79e54722db 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "scsi_tgt_priv.h" @@ -46,6 +47,7 @@ struct scsi_tgt_cmd { struct list_head hash_list; struct request *rq; + u64 itn_id; u64 tag; }; @@ -185,12 +187,13 @@ static void scsi_tgt_cmd_destroy(struct work_struct *work) } static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd, - u64 tag) + u64 itn_id, u64 tag) { struct scsi_tgt_queuedata *qdata = rq->q->queuedata; unsigned long flags; struct list_head *head; + tcmd->itn_id = itn_id; tcmd->tag = tag; tcmd->bio = NULL; INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy); @@ -301,14 +304,14 @@ EXPORT_SYMBOL_GPL(scsi_tgt_cmd_to_host); * @scsilun: scsi lun * @tag: unique value to identify this command for tmf */ -int scsi_tgt_queue_command(struct scsi_cmnd *cmd, struct scsi_lun *scsilun, - u64 tag) +int scsi_tgt_queue_command(struct scsi_cmnd *cmd, u64 itn_id, + struct scsi_lun *scsilun, u64 tag) { struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; int err; - init_scsi_tgt_cmd(cmd->request, tcmd, tag); - err = scsi_tgt_uspace_send_cmd(cmd, scsilun, tag); + init_scsi_tgt_cmd(cmd->request, tcmd, itn_id, tag); + err = scsi_tgt_uspace_send_cmd(cmd, itn_id, scsilun, tag); if (err) cmd_hashlist_del(cmd); @@ -326,7 +329,7 @@ static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd) dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request)); - scsi_tgt_uspace_send_status(cmd, tcmd->tag); + scsi_tgt_uspace_send_status(cmd, tcmd->itn_id, tcmd->tag); if (cmd->request_buffer) scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); @@ -459,7 +462,7 @@ static struct request *tgt_cmd_hash_lookup(struct request_queue *q, u64 tag) return rq; } -int scsi_tgt_kspace_exec(int host_no, int result, u64 tag, +int scsi_tgt_kspace_exec(int host_no, u64 itn_id, int result, u64 tag, unsigned long uaddr, u32 len, unsigned long sense_uaddr, u32 sense_len, u8 rw) { @@ -541,21 +544,22 @@ done: return err; } -int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, int function, u64 tag, - struct scsi_lun *scsilun, void *data) +int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, u64 itn_id, + int function, u64 tag, struct scsi_lun *scsilun, + void *data) { int err; /* TODO: need to retry if this fails. */ - err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, function, - tag, scsilun, data); + err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, itn_id, + function, tag, scsilun, data); if (err < 0) eprintk("The task management request lost!\n"); return err; } EXPORT_SYMBOL_GPL(scsi_tgt_tsk_mgmt_request); -int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result) +int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 itn_id, u64 mid, int result) { struct Scsi_Host *shost; int err = -EINVAL; @@ -573,7 +577,60 @@ int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result) goto done; } - err = shost->hostt->tsk_mgmt_response(mid, result); + err = shost->hostt->tsk_mgmt_response(shost, itn_id, mid, result); +done: + scsi_host_put(shost); + return err; +} + +int scsi_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, + char *initiator) +{ + int err; + + /* TODO: need to retry if this fails. */ + err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no, itn_id, 0, + initiator); + if (err < 0) + eprintk("The i_t_neuxs request lost, %d %llx!\n", + shost->host_no, (unsigned long long)itn_id); + return err; +} +EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_create); + +int scsi_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) +{ + int err; + + /* TODO: need to retry if this fails. */ + err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no, + itn_id, 1, NULL); + if (err < 0) + eprintk("The i_t_neuxs request lost, %d %llx!\n", + shost->host_no, (unsigned long long)itn_id); + return err; +} +EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_destroy); + +int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 itn_id, int result) +{ + struct Scsi_Host *shost; + int err = -EINVAL; + + dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid); + + shost = scsi_host_lookup(host_no); + if (IS_ERR(shost)) { + printk(KERN_ERR "Could not find host no %d\n", host_no); + return err; + } + + if (!shost->uspace_req_q) { + printk(KERN_ERR "Not target scsi host %d\n", host_no); + goto done; + } + + err = shost->transportt->it_nexus_response(shost, itn_id, result); done: scsi_host_put(shost); return err; diff --git a/drivers/scsi/scsi_tgt_priv.h b/drivers/scsi/scsi_tgt_priv.h index e9e6db1c417f..cb92888948f9 100644 --- a/drivers/scsi/scsi_tgt_priv.h +++ b/drivers/scsi/scsi_tgt_priv.h @@ -15,12 +15,18 @@ do { \ extern void scsi_tgt_if_exit(void); extern int scsi_tgt_if_init(void); -extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, - u64 tag); -extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag); -extern int scsi_tgt_kspace_exec(int host_no, int result, u64 tag, - unsigned long uaddr, u32 len, unsigned long sense_uaddr, - u32 sense_len, u8 rw); -extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, +extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 it_nexus_id, + struct scsi_lun *lun, u64 tag); +extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 it_nexus_id, + u64 tag); +extern int scsi_tgt_kspace_exec(int host_no, u64 it_nexus_id, int result, u64 tag, + unsigned long uaddr, u32 len, + unsigned long sense_uaddr, u32 sense_len, u8 rw); +extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 it_nexus_id, + int function, u64 tag, struct scsi_lun *scsilun, void *data); -extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result); +extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 it_nexus_id, + u64 mid, int result); +extern int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 it_nexus_id, + int function, char *initiator); +extern int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 it_nexus_id, int result); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 3b8a6a85c2f8..89c40c4bd5c4 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -146,7 +146,7 @@ struct scsi_host_template { void (*done)(struct scsi_cmnd *)); /* Used as callback for the completion of task management request. */ - int (* tsk_mgmt_response)(u64 mid, int result); + int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64 mid, int result); /* * This is an error handling strategy routine. You don't need to diff --git a/include/scsi/scsi_tgt.h b/include/scsi/scsi_tgt.h index 4f4427937af2..d0fefb96158f 100644 --- a/include/scsi/scsi_tgt.h +++ b/include/scsi/scsi_tgt.h @@ -11,9 +11,11 @@ struct scsi_lun; extern struct Scsi_Host *scsi_tgt_cmd_to_host(struct scsi_cmnd *); extern int scsi_tgt_alloc_queue(struct Scsi_Host *); extern void scsi_tgt_free_queue(struct Scsi_Host *); -extern int scsi_tgt_queue_command(struct scsi_cmnd *, struct scsi_lun *, u64); -extern int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *, int, u64, struct scsi_lun *, - void *); +extern int scsi_tgt_queue_command(struct scsi_cmnd *, u64, struct scsi_lun *, u64); +extern int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *, u64, int, u64, + struct scsi_lun *, void *); extern struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *, enum dma_data_direction, gfp_t); extern void scsi_host_put_command(struct Scsi_Host *, struct scsi_cmnd *); +extern int scsi_tgt_it_nexus_create(struct Scsi_Host *, u64, char *); +extern int scsi_tgt_it_nexus_destroy(struct Scsi_Host *, u64); diff --git a/include/scsi/scsi_tgt_if.h b/include/scsi/scsi_tgt_if.h index 4cf9dff29a2f..f2ee7c238a45 100644 --- a/include/scsi/scsi_tgt_if.h +++ b/include/scsi/scsi_tgt_if.h @@ -23,13 +23,15 @@ #define __SCSI_TARGET_IF_H /* user -> kernel */ -#define TGT_UEVENT_CMD_RSP 0x0001 -#define TGT_UEVENT_TSK_MGMT_RSP 0x0002 +#define TGT_UEVENT_CMD_RSP 0x0001 +#define TGT_UEVENT_IT_NEXUS_RSP 0x0002 +#define TGT_UEVENT_TSK_MGMT_RSP 0x0003 /* kernel -> user */ -#define TGT_KEVENT_CMD_REQ 0x1001 -#define TGT_KEVENT_CMD_DONE 0x1002 -#define TGT_KEVENT_TSK_MGMT_REQ 0x1003 +#define TGT_KEVENT_CMD_REQ 0x1001 +#define TGT_KEVENT_CMD_DONE 0x1002 +#define TGT_KEVENT_IT_NEXUS_REQ 0x1003 +#define TGT_KEVENT_TSK_MGMT_REQ 0x1004 struct tgt_event_hdr { uint16_t version; @@ -46,6 +48,7 @@ struct tgt_event { struct { int host_no; int result; + aligned_u64 itn_id; aligned_u64 tag; aligned_u64 uaddr; aligned_u64 sense_uaddr; @@ -55,15 +58,22 @@ struct tgt_event { } cmd_rsp; struct { int host_no; - aligned_u64 mid; int result; + aligned_u64 itn_id; + aligned_u64 mid; } tsk_mgmt_rsp; - + struct { + __s32 host_no; + __s32 result; + aligned_u64 itn_id; + __u32 function; + } it_nexus_rsp; /* kernel -> user */ struct { int host_no; uint32_t data_len; + aligned_u64 itn_id; uint8_t scb[16]; uint8_t lun[8]; int attribute; @@ -71,16 +81,25 @@ struct tgt_event { } cmd_req; struct { int host_no; - aligned_u64 tag; int result; + aligned_u64 itn_id; + aligned_u64 tag; } cmd_done; struct { int host_no; int function; + aligned_u64 itn_id; aligned_u64 tag; uint8_t lun[8]; aligned_u64 mid; } tsk_mgmt_req; + struct { + __s32 host_no; + __u32 function; + aligned_u64 itn_id; + __u32 max_cmds; + __u8 initiator_id[16]; + } it_nexus_req; } p; } __attribute__ ((aligned (sizeof(uint64_t)))); diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h index 3c18baa65a72..af5b3e15e64e 100644 --- a/include/scsi/scsi_transport.h +++ b/include/scsi/scsi_transport.h @@ -65,6 +65,12 @@ struct scsi_transport_template { * EH_NOT_HANDLED Begin normal error recovery */ enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); + + /* + * Used as callback for the completion of i_t_nexus request + * for target drivers. + */ + int (* it_nexus_response)(struct Scsi_Host *, u64, int); }; #define transport_class_to_shost(tc) \ -- cgit v1.2.3 From 62fe88261b9d865264d857777cf58a0335513151 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 11 Jul 2007 15:08:19 +0900 Subject: [SCSI] srp_transport: add target driver support This adds minimum target driver support: - srp_rport_{add,del} calls scsi_tgt_it_nexus_{create,destroy} for target drivers. - add a callback to notify target drivers of the nexus operation results to srp_function_template. Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/Kconfig | 2 +- drivers/scsi/scsi_transport_srp.c | 24 ++++++++++++++++++++++++ include/scsi/scsi_transport_srp.h | 3 ++- 3 files changed, 27 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 778dc0fb1e4f..8d4057ea27b1 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -291,7 +291,7 @@ source "drivers/scsi/libsas/Kconfig" config SCSI_SRP_ATTRS tristate "SRP Transport Attributes" - depends on SCSI + depends on SCSI && SCSI_TGT help If you wish to export transport-specific information about each attached SRP device to sysfs, say Y. diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c index 608abd8aef20..8e5b41ca181d 100644 --- a/drivers/scsi/scsi_transport_srp.c +++ b/drivers/scsi/scsi_transport_srp.c @@ -30,6 +30,7 @@ #include #include #include +#include struct srp_host_attrs { atomic_t next_port_id; @@ -221,6 +222,17 @@ struct srp_rport *srp_rport_add(struct Scsi_Host *shost, return ERR_PTR(ret); } + if (ids->roles == SRP_RPORT_ROLE_INITIATOR) { + ret = scsi_tgt_it_nexus_create(shost, (unsigned long)rport, + rport->port_id); + if (ret) { + device_del(&rport->dev); + transport_destroy_device(&rport->dev); + put_device(&rport->dev); + return ERR_PTR(ret); + } + } + transport_add_device(&rport->dev); transport_configure_device(&rport->dev); @@ -238,6 +250,10 @@ void srp_rport_del(struct srp_rport *rport) { struct device *dev = &rport->dev; + if (rport->roles == SRP_RPORT_ROLE_INITIATOR) + scsi_tgt_it_nexus_destroy(dev_to_shost(dev->parent), + (unsigned long)rport); + transport_remove_device(dev); device_del(dev); transport_destroy_device(dev); @@ -264,6 +280,12 @@ void srp_remove_host(struct Scsi_Host *shost) } EXPORT_SYMBOL_GPL(srp_remove_host); +static int srp_it_nexus_response(struct Scsi_Host *shost, u64 id, int result) +{ + struct srp_internal *i = to_srp_internal(shost->transportt); + return i->f->it_nexus_response(shost, id, result); +} + /** * srp_attach_transport -- instantiate SRP transport template * @ft: SRP transport class function template @@ -278,6 +300,8 @@ srp_attach_transport(struct srp_function_template *ft) if (!i) return NULL; + i->t.it_nexus_response = srp_it_nexus_response; + i->t.host_size = sizeof(struct srp_host_attrs); i->t.host_attrs.ac.attrs = &i->host_attrs[0]; i->t.host_attrs.ac.class = &srp_host_class.class; diff --git a/include/scsi/scsi_transport_srp.h b/include/scsi/scsi_transport_srp.h index 08b4a28a77b8..a705dbc016b3 100644 --- a/include/scsi/scsi_transport_srp.h +++ b/include/scsi/scsi_transport_srp.h @@ -21,7 +21,8 @@ struct srp_rport { }; struct srp_function_template { - /* later */ + /* for target drivers */ + int (* it_nexus_response)(struct Scsi_Host *, u64, int); }; extern struct scsi_transport_template * -- cgit v1.2.3 From 17b0bcfad795913b1f2a3926cd238fa2ad5522a2 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 11 Jul 2007 15:08:21 +0900 Subject: [SCSI] tgt: convert libsrp and ibmvstgt to use srp_transport This converts libsrp and ibmvstgt to use srp transport. Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/Kconfig | 2 +- drivers/scsi/ibmvscsi/ibmvstgt.c | 58 +++++++++++++++++++++++++++++++++++----- drivers/scsi/libsrp.c | 5 ++-- include/scsi/libsrp.h | 2 +- 4 files changed, 57 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 8d4057ea27b1..4562273dfad3 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -848,7 +848,7 @@ config SCSI_IBMVSCSI config SCSI_IBMVSCSIS tristate "IBM Virtual SCSI Server support" - depends on PPC_PSERIES && SCSI_TGT && SCSI_SRP + depends on PPC_PSERIES && SCSI_TGT && SCSI_SRP && SCSI_SRP_ATTRS help This is the SRP target driver for IBM pSeries virtual environments. diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c index 8ba7dd09d01d..4ee6e417d0bf 100644 --- a/drivers/scsi/ibmvscsi/ibmvstgt.c +++ b/drivers/scsi/ibmvscsi/ibmvstgt.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -68,9 +69,12 @@ struct vio_port { unsigned long liobn; unsigned long riobn; struct srp_target *target; + + struct srp_rport *rport; }; static struct workqueue_struct *vtgtd; +static struct scsi_transport_template *ibmvstgt_transport_template; /* * These are fixed for the system and come from the Open Firmware device tree. @@ -188,6 +192,7 @@ static int send_rsp(struct iu_entry *iue, struct scsi_cmnd *sc, static void handle_cmd_queue(struct srp_target *target) { struct Scsi_Host *shost = target->shost; + struct srp_rport *rport = target_to_port(target)->rport; struct iu_entry *iue; struct srp_cmd *cmd; unsigned long flags; @@ -200,7 +205,8 @@ retry: if (!test_and_set_bit(V_FLYING, &iue->flags)) { spin_unlock_irqrestore(&target->lock, flags); cmd = iue->sbuf->buf; - err = srp_cmd_queue(shost, cmd, iue, 0); + err = srp_cmd_queue(shost, cmd, iue, + (unsigned long)rport, 0); if (err) { eprintk("cannot queue cmd %p %d\n", cmd, err); srp_iu_put(iue); @@ -359,6 +365,16 @@ static void process_login(struct iu_entry *iue) union viosrp_iu *iu = vio_iu(iue); struct srp_login_rsp *rsp = &iu->srp.login_rsp; uint64_t tag = iu->srp.rsp.tag; + struct Scsi_Host *shost = iue->target->shost; + struct srp_target *target = host_to_srp_target(shost); + struct vio_port *vport = target_to_port(target); + struct srp_rport_identifiers ids; + + memset(&ids, 0, sizeof(ids)); + sprintf(ids.port_id, "%x", vport->dma_dev->unit_address); + ids.roles = SRP_RPORT_ROLE_INITIATOR; + if (!vport->rport) + vport->rport = srp_rport_add(shost, &ids); /* TODO handle case that requested size is wrong and * buffer format is wrong @@ -412,7 +428,9 @@ static int process_tsk_mgmt(struct iu_entry *iue) fn = 0; } if (fn) - scsi_tgt_tsk_mgmt_request(iue->target->shost, fn, + scsi_tgt_tsk_mgmt_request(iue->target->shost, + (unsigned long)iue->target->shost, + fn, iu->srp.tsk_mgmt.task_tag, (struct scsi_lun *) &iu->srp.tsk_mgmt.lun, iue); @@ -721,7 +739,8 @@ static int ibmvstgt_eh_abort_handler(struct scsi_cmnd *sc) return 0; } -static int ibmvstgt_tsk_mgmt_response(u64 mid, int result) +static int ibmvstgt_tsk_mgmt_response(struct Scsi_Host *shost, + u64 itn_id, u64 mid, int result) { struct iu_entry *iue = (struct iu_entry *) ((void *) mid); union viosrp_iu *iu = vio_iu(iue); @@ -747,6 +766,20 @@ static int ibmvstgt_tsk_mgmt_response(u64 mid, int result) return 0; } +static int ibmvstgt_it_nexus_response(struct Scsi_Host *shost, u64 itn_id, + int result) +{ + struct srp_target *target = host_to_srp_target(shost); + struct vio_port *vport = target_to_port(target); + + if (result) { + eprintk("%p %d\n", shost, result); + srp_rport_del(vport->rport); + vport->rport = NULL; + } + return 0; +} + static ssize_t system_id_show(struct class_device *cdev, char *buf) { return snprintf(buf, PAGE_SIZE, "%s\n", system_id); @@ -804,6 +837,7 @@ static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id) shost = scsi_host_alloc(&ibmvstgt_sht, sizeof(struct srp_target)); if (!shost) goto free_vport; + shost->transportt = ibmvstgt_transport_template; err = scsi_tgt_alloc_queue(shost); if (err) goto put_host; @@ -837,8 +871,8 @@ static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id) err = scsi_add_host(shost, target->dev); if (err) goto destroy_queue; - return 0; + return 0; destroy_queue: crq_queue_destroy(target); free_srp_target: @@ -857,6 +891,7 @@ static int ibmvstgt_remove(struct vio_dev *dev) struct vio_port *vport = target->ldata; crq_queue_destroy(target); + srp_remove_host(shost); scsi_remove_host(shost); scsi_tgt_free_queue(shost); srp_target_free(target); @@ -909,15 +944,24 @@ static int get_system_info(void) return 0; } +static struct srp_function_template ibmvstgt_transport_functions = { + .it_nexus_response = ibmvstgt_it_nexus_response, +}; + static int ibmvstgt_init(void) { int err = -ENOMEM; printk("IBM eServer i/pSeries Virtual SCSI Target Driver\n"); + ibmvstgt_transport_template = + srp_attach_transport(&ibmvstgt_transport_functions); + if (!ibmvstgt_transport_template) + return err; + vtgtd = create_workqueue("ibmvtgtd"); if (!vtgtd) - return err; + goto release_transport; err = get_system_info(); if (err) @@ -928,9 +972,10 @@ static int ibmvstgt_init(void) goto destroy_wq; return 0; - destroy_wq: destroy_workqueue(vtgtd); +release_transport: + srp_release_transport(ibmvstgt_transport_template); return err; } @@ -940,6 +985,7 @@ static void ibmvstgt_exit(void) destroy_workqueue(vtgtd); vio_unregister_driver(&ibmvstgt_driver); + srp_release_transport(ibmvstgt_transport_template); } MODULE_DESCRIPTION("IBM Virtual SCSI Target"); diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c index 732446e63963..2ad0a27dbaab 100644 --- a/drivers/scsi/libsrp.c +++ b/drivers/scsi/libsrp.c @@ -392,7 +392,7 @@ static int vscsis_data_length(struct srp_cmd *cmd, enum dma_data_direction dir) } int srp_cmd_queue(struct Scsi_Host *shost, struct srp_cmd *cmd, void *info, - u64 addr) + u64 itn_id, u64 addr) { enum dma_data_direction dir; struct scsi_cmnd *sc; @@ -428,7 +428,8 @@ int srp_cmd_queue(struct Scsi_Host *shost, struct srp_cmd *cmd, void *info, sc->request_bufflen = len; sc->request_buffer = (void *) (unsigned long) addr; sc->tag = tag; - err = scsi_tgt_queue_command(sc, (struct scsi_lun *) &cmd->lun, cmd->tag); + err = scsi_tgt_queue_command(sc, itn_id, (struct scsi_lun *)&cmd->lun, + cmd->tag); if (err) scsi_host_put_command(shost, sc); diff --git a/include/scsi/libsrp.h b/include/scsi/libsrp.h index d143171896ae..ba615e4c1d7c 100644 --- a/include/scsi/libsrp.h +++ b/include/scsi/libsrp.h @@ -59,7 +59,7 @@ extern void srp_target_free(struct srp_target *); extern struct iu_entry *srp_iu_get(struct srp_target *); extern void srp_iu_put(struct iu_entry *); -extern int srp_cmd_queue(struct Scsi_Host *, struct srp_cmd *, void *, u64); +extern int srp_cmd_queue(struct Scsi_Host *, struct srp_cmd *, void *, u64, u64); extern int srp_transfer_data(struct scsi_cmnd *, struct srp_cmd *, srp_rdma_t, int, int); -- cgit v1.2.3 From bfb743740e1598d3030c4972a8808f2bb5b95b6b Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 11 Jul 2007 15:08:22 +0900 Subject: [SCSI] tgt: move tsk_mgmt_response callback to transport class This moves tsk_mgmt_response callback in struct scsi_host_template to struct scsi_transport_template since struct scsi_transport_template is more suitable for the task management stuff. Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_tgt_lib.c | 2 +- drivers/scsi/scsi_transport_srp.c | 12 ++++++++++-- include/scsi/scsi_host.h | 3 --- include/scsi/scsi_transport.h | 6 ++++++ include/scsi/scsi_transport_srp.h | 1 + 5 files changed, 18 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index fa79e54722db..5851c8e53e40 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -577,7 +577,7 @@ int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 itn_id, u64 mid, int result) goto done; } - err = shost->hostt->tsk_mgmt_response(shost, itn_id, mid, result); + err = shost->transportt->tsk_mgmt_response(shost, itn_id, mid, result); done: scsi_host_put(shost); return err; diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c index 8e5b41ca181d..cdd001a6639c 100644 --- a/drivers/scsi/scsi_transport_srp.c +++ b/drivers/scsi/scsi_transport_srp.c @@ -280,10 +280,17 @@ void srp_remove_host(struct Scsi_Host *shost) } EXPORT_SYMBOL_GPL(srp_remove_host); -static int srp_it_nexus_response(struct Scsi_Host *shost, u64 id, int result) +static int srp_tsk_mgmt_response(struct Scsi_Host *shost, u64 nexus, u64 tm_id, + int result) { struct srp_internal *i = to_srp_internal(shost->transportt); - return i->f->it_nexus_response(shost, id, result); + return i->f->tsk_mgmt_response(shost, nexus, tm_id, result); +} + +static int srp_it_nexus_response(struct Scsi_Host *shost, u64 nexus, int result) +{ + struct srp_internal *i = to_srp_internal(shost->transportt); + return i->f->it_nexus_response(shost, nexus, result); } /** @@ -300,6 +307,7 @@ srp_attach_transport(struct srp_function_template *ft) if (!i) return NULL; + i->t.tsk_mgmt_response = srp_tsk_mgmt_response; i->t.it_nexus_response = srp_it_nexus_response; i->t.host_size = sizeof(struct srp_host_attrs); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 89c40c4bd5c4..88f6871badd8 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -145,9 +145,6 @@ struct scsi_host_template { int (* transfer_response)(struct scsi_cmnd *, void (*done)(struct scsi_cmnd *)); - /* Used as callback for the completion of task management request. */ - int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64 mid, int result); - /* * This is an error handling strategy routine. You don't need to * define one of these if you don't want to - there is a default diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h index af5b3e15e64e..0dfef752f0e2 100644 --- a/include/scsi/scsi_transport.h +++ b/include/scsi/scsi_transport.h @@ -71,6 +71,12 @@ struct scsi_transport_template { * for target drivers. */ int (* it_nexus_response)(struct Scsi_Host *, u64, int); + + /* + * Used as callback for the completion of task management + * request for target drivers. + */ + int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int); }; #define transport_class_to_shost(tc) \ diff --git a/include/scsi/scsi_transport_srp.h b/include/scsi/scsi_transport_srp.h index a705dbc016b3..9c60ca1c08c5 100644 --- a/include/scsi/scsi_transport_srp.h +++ b/include/scsi/scsi_transport_srp.h @@ -22,6 +22,7 @@ struct srp_rport { struct srp_function_template { /* for target drivers */ + int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int); int (* it_nexus_response)(struct Scsi_Host *, u64, int); }; -- cgit v1.2.3 From 6778a35bd02939767a17463d74da113541c9371f Mon Sep 17 00:00:00 2001 From: Eric Moore Date: Tue, 14 Aug 2007 16:18:02 -0600 Subject: [SCSI] Addition to pci_ids.h for ATTO Technology, Inc. A new PCI_VENDOR_ID for pci_ids.h. signed-off-by: Eric Moore Signed-off-by: James Bottomley --- include/linux/pci_ids.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 07fc57429b58..715a23e4a1e9 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1460,6 +1460,8 @@ #define PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC 0x0108 #define PCI_DEVICE_ID_TOSHIBA_SPIDER_NET 0x01b3 +#define PCI_VENDOR_ID_ATTO 0x117c + #define PCI_VENDOR_ID_RICOH 0x1180 #define PCI_DEVICE_ID_RICOH_RL5C465 0x0465 #define PCI_DEVICE_ID_RICOH_RL5C466 0x0466 -- cgit v1.2.3 From 03f002f778e58e9056e8e9a22952c5c6f4d76269 Mon Sep 17 00:00:00 2001 From: Christof Schmitt Date: Tue, 28 Aug 2007 09:31:21 +0200 Subject: [SCSI] scsi_transport_fc: Introduce disable_target_scan flag This change has already been discussed on linux-scsi: http://marc.info/?t=118771096400003 http://marc.info/?t=118760913100005 Signed-off-by: Christof Schmitt Signed-off-by: Swen Schillig Acked-by: James Smart Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_fc.c | 4 +++- include/scsi/scsi_transport_fc.h | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 47057254850d..dd97f2652508 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -2988,10 +2988,12 @@ fc_scsi_scan_rport(struct work_struct *work) struct fc_rport *rport = container_of(work, struct fc_rport, scan_work); struct Scsi_Host *shost = rport_to_shost(rport); + struct fc_internal *i = to_fc_internal(shost->transportt); unsigned long flags; if ((rport->port_state == FC_PORTSTATE_ONLINE) && - (rport->roles & FC_PORT_ROLE_FCP_TARGET)) { + (rport->roles & FC_PORT_ROLE_FCP_TARGET) && + !(i->f->disable_target_scan)) { scsi_scan_target(&rport->dev, rport->channel, rport->scsi_target_id, SCAN_WILD_CARD, 1); } diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index a0d80bcaa93d..616a96a3ab81 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -632,6 +632,8 @@ struct fc_function_template { unsigned long show_host_fabric_name:1; unsigned long show_host_symbolic_name:1; unsigned long show_host_system_hostname:1; + + unsigned long disable_target_scan:1; }; -- cgit v1.2.3 From 5dc2b89e124251662f580f4ba3c9f6195d1eaff6 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sat, 1 Sep 2007 02:02:20 +0900 Subject: [SCSI] add supported_mode and active_mode attributes to the host This adds supported_mode and active_mode attributes to /sys/class/sys_host/hostX/ for specifying the mode that a lld supports and the currently activated mode. The output format is similar to fc rport roles: luce:/sys/class/scsi_host/host0$ cat supported_mode Initiator luce:/sys/class/scsi_host/host0$ cat active_mode Initiator The mode values uses bitmap since we would support dual-mode llds in the future like this: luce:/sys/class/scsi_host/host0$ cat supported_mode Initiator, Target The supported_mode attribute looks at a scsi_host_template and the active_mode attribute looks at a scsi_host. We would add a hook to a scsi_host_template to change the active_mode attribute dynamically. But now there is no hook since no lld supports that feature. Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/hosts.c | 1 + drivers/scsi/scsi_sysfs.c | 42 ++++++++++++++++++++++++++++++++++++++++++ include/scsi/scsi_host.h | 9 +++++++++ 3 files changed, 52 insertions(+) (limited to 'include') diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 96bc31266c98..adc9559cb6f4 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -342,6 +342,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) shost->unchecked_isa_dma = sht->unchecked_isa_dma; shost->use_clustering = sht->use_clustering; shost->ordered_tag = sht->ordered_tag; + shost->active_mode = sht->supported_mode; if (sht->max_host_blocked) shost->max_host_blocked = sht->max_host_blocked; diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 34cdce6738a6..a3d227f3f520 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -190,6 +190,46 @@ show_shost_state(struct class_device *class_dev, char *buf) static CLASS_DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state); +static ssize_t +show_shost_mode(unsigned int mode, char *buf) +{ + ssize_t len = 0; + + if (mode & MODE_INITIATOR) + len = sprintf(buf, "%s", "Initiator"); + + if (mode & MODE_TARGET) + len += sprintf(buf + len, "%s%s", len ? ", " : "", "Target"); + + len += sprintf(buf + len, "\n"); + + return len; +} + +static ssize_t show_shost_supported_mode(struct class_device *class_dev, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(class_dev); + + if (shost->hostt->supported_mode == MODE_UNKNOWN) + return snprintf(buf, 20, "unknown\n"); + else + return show_shost_mode(shost->hostt->supported_mode, buf); +} + +static CLASS_DEVICE_ATTR(supported_mode, S_IRUGO | S_IWUSR, show_shost_supported_mode, NULL); + +static ssize_t show_shost_active_mode(struct class_device *class_dev, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(class_dev); + + if (shost->active_mode == MODE_UNKNOWN) + return snprintf(buf, 20, "unknown\n"); + else + return show_shost_mode(shost->active_mode, buf); +} + +static CLASS_DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL); + shost_rd_attr(unique_id, "%u\n"); shost_rd_attr(host_busy, "%hu\n"); shost_rd_attr(cmd_per_lun, "%hd\n"); @@ -208,6 +248,8 @@ static struct class_device_attribute *scsi_sysfs_shost_attrs[] = { &class_device_attr_proc_name, &class_device_attr_scan, &class_device_attr_state, + &class_device_attr_supported_mode, + &class_device_attr_active_mode, NULL }; diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 88f6871badd8..5b79697a3a80 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -32,6 +32,9 @@ struct blk_queue_tags; #define SG_NONE 0 #define SG_ALL 0xff +#define MODE_UNKNOWN 0x00 +#define MODE_INITIATOR 0x01 +#define MODE_TARGET 0x02 #define DISABLE_CLUSTERING 0 #define ENABLE_CLUSTERING 1 @@ -404,6 +407,11 @@ struct scsi_host_template { */ unsigned char present; + /* + * This specifies the mode that a LLD supports. + */ + unsigned supported_mode:2; + /* * true if this host adapter uses unchecked DMA onto an ISA bus. */ @@ -574,6 +582,7 @@ struct Scsi_Host { */ unsigned long cmd_serial_number, cmd_pid; + unsigned active_mode:2; unsigned unchecked_isa_dma:1; unsigned use_clustering:1; unsigned use_blk_tcq:1; -- cgit v1.2.3 From 7525236d0bc7ad17eb5e0733417896cab745d6c8 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sat, 1 Sep 2007 02:02:27 +0900 Subject: [SCSI] fc_transport: add target driver support This adds minimum target driver support like the srp transport does: - fc_remote_port_{rolechg,delete} calls scsi_tgt_it_nexus_{create,destroy} for target drivers. - add callbacks to notify target drivers of the nexus and tmf operation results to fc_function_template. Signed-off-by: FUJITA Tomonori Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/Kconfig | 7 +++++++ drivers/scsi/scsi_transport_fc.c | 29 +++++++++++++++++++++++++++++ drivers/scsi/scsi_transport_fc_internal.h | 26 ++++++++++++++++++++++++++ include/scsi/scsi_transport_fc.h | 4 ++++ 4 files changed, 66 insertions(+) create mode 100644 drivers/scsi/scsi_transport_fc_internal.h (limited to 'include') diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 7877dfdd2322..e1efa0eac4ff 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -272,6 +272,13 @@ config SCSI_FC_ATTRS each attached FiberChannel device to sysfs, say Y. Otherwise, say N. +config SCSI_FC_TGT_ATTRS + bool "SCSI target support for FiberChannel Transport Attributes" + depends on SCSI_FC_ATTRS + depends on SCSI_TGT = y || SCSI_TGT = SCSI_FC_ATTRS + help + If you want to use SCSI target mode drivers enable this option. + config SCSI_ISCSI_ATTRS tristate "iSCSI Transport Attributes" depends on SCSI && NET diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index dd97f2652508..8df0f080997f 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -36,6 +36,7 @@ #include #include #include "scsi_priv.h" +#include "scsi_transport_fc_internal.h" static int fc_queue_work(struct Scsi_Host *, struct work_struct *); static void fc_vport_sched_delete(struct work_struct *work); @@ -1956,6 +1957,19 @@ static int fc_user_scan(struct Scsi_Host *shost, uint channel, return 0; } +static int fc_tsk_mgmt_response(struct Scsi_Host *shost, u64 nexus, u64 tm_id, + int result) +{ + struct fc_internal *i = to_fc_internal(shost->transportt); + return i->f->tsk_mgmt_response(shost, nexus, tm_id, result); +} + +static int fc_it_nexus_response(struct Scsi_Host *shost, u64 nexus, int result) +{ + struct fc_internal *i = to_fc_internal(shost->transportt); + return i->f->it_nexus_response(shost, nexus, result); +} + struct scsi_transport_template * fc_attach_transport(struct fc_function_template *ft) { @@ -1999,6 +2013,10 @@ fc_attach_transport(struct fc_function_template *ft) i->t.user_scan = fc_user_scan; + /* target-mode drivers' functions */ + i->t.tsk_mgmt_response = fc_tsk_mgmt_response; + i->t.it_nexus_response = fc_it_nexus_response; + /* * Setup SCSI Target Attributes. */ @@ -2756,6 +2774,10 @@ fc_remote_port_delete(struct fc_rport *rport) spin_unlock_irqrestore(shost->host_lock, flags); + if (rport->roles & FC_PORT_ROLE_FCP_INITIATOR && + shost->active_mode & MODE_TARGET) + fc_tgt_it_nexus_destroy(shost, (unsigned long)rport); + scsi_target_block(&rport->dev); /* see if we need to kill io faster than waiting for device loss */ @@ -2796,6 +2818,7 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles) struct fc_host_attrs *fc_host = shost_to_fc_host(shost); unsigned long flags; int create = 0; + int ret; spin_lock_irqsave(shost->host_lock, flags); if (roles & FC_PORT_ROLE_FCP_TARGET) { @@ -2804,6 +2827,12 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles) create = 1; } else if (!(rport->roles & FC_PORT_ROLE_FCP_TARGET)) create = 1; + } else if (shost->active_mode & MODE_TARGET) { + ret = fc_tgt_it_nexus_create(shost, (unsigned long)rport, + (char *)&rport->node_name); + if (ret) + printk(KERN_ERR "FC Remore Port tgt nexus failed %d\n", + ret); } rport->roles = roles; diff --git a/drivers/scsi/scsi_transport_fc_internal.h b/drivers/scsi/scsi_transport_fc_internal.h new file mode 100644 index 000000000000..e7bfbe751c1f --- /dev/null +++ b/drivers/scsi/scsi_transport_fc_internal.h @@ -0,0 +1,26 @@ +#include + +#ifdef CONFIG_SCSI_FC_TGT_ATTRS +static inline int fc_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, + char *initiator) +{ + return scsi_tgt_it_nexus_create(shost, itn_id, initiator); +} + +static inline int fc_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) +{ + return scsi_tgt_it_nexus_destroy(shost, itn_id); +} +#else +static inline int fc_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, + char *initiator) +{ + return 0; +} + +static inline int fc_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) +{ + return 0; +} + +#endif diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index 616a96a3ab81..e466d886e192 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -589,6 +589,10 @@ struct fc_function_template { int (*vport_disable)(struct fc_vport *, bool); int (*vport_delete)(struct fc_vport *); + /* target-mode drivers' functions */ + int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int); + int (* it_nexus_response)(struct Scsi_Host *, u64, int); + /* allocation lengths for host-specific data */ u32 dd_fcrport_size; u32 dd_fcvport_size; -- cgit v1.2.3 From 1a4f550a09f89e3a15eff1971bc9db977571b9f6 Mon Sep 17 00:00:00 2001 From: Nick Cheng Date: Thu, 13 Sep 2007 17:26:40 +0800 Subject: [SCSI] arcmsr: 1.20.00.15: add SATA RAID plus other fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Description: ** support ARC1200/1201/1202 SATA RAID adapter, which is named ACB_ADAPTER_TYPE_B ** modify the arcmsr_pci_slot_reset function ** modify the arcmsr_pci_ers_disconnect_forepart function ** modify the arcmsr_pci_ers_need_reset_forepart function  Signed-off-by: Nick Cheng Signed-off-by: James Bottomley --- Documentation/scsi/ChangeLog.arcmsr | 17 +- drivers/scsi/Kconfig | 23 +- drivers/scsi/arcmsr/arcmsr.h | 192 ++- drivers/scsi/arcmsr/arcmsr_attr.c | 64 +- drivers/scsi/arcmsr/arcmsr_hba.c | 2263 +++++++++++++++++++++-------------- include/linux/pci_ids.h | 3 + 6 files changed, 1571 insertions(+), 991 deletions(-) (limited to 'include') diff --git a/Documentation/scsi/ChangeLog.arcmsr b/Documentation/scsi/ChangeLog.arcmsr index 162c47fdf45f..cd8403a33ee6 100644 --- a/Documentation/scsi/ChangeLog.arcmsr +++ b/Documentation/scsi/ChangeLog.arcmsr @@ -53,4 +53,19 @@ ** for linux standard list ** enable usage of pci message signal interrupt ** follow Randy.Danlup kindness suggestion cleanup this code -************************************************************************** \ No newline at end of file +** 1.20.00.14 05/02/2007 Erich Chen & Nick Cheng +** 1.implement PCI-Express error recovery function and AER capability +** 2.implement the selection of ARCMSR_MAX_XFER_SECTORS_B=4096 +** if firmware version is newer than 1.42 +** 3.modify arcmsr_iop_reset to improve the ability +** 4.modify the ISR, arcmsr_interrupt routine,to prevent the +** inconsistency with sg_mod driver if application directly calls +** the arcmsr driver w/o passing through scsi mid layer +** specially thanks to Yanmin Zhang's openhanded help about AER +** 1.20.00.15 08/30/2007 Erich Chen & Nick Cheng +** 1. support ARC1200/1201/1202 SATA RAID adapter, which is named +** ACB_ADAPTER_TYPE_B +** 2. modify the arcmsr_pci_slot_reset function +** 3. modify the arcmsr_pci_ers_disconnect_forepart function +** 4. modify the arcmsr_pci_ers_need_reset_forepart function +************************************************************************** diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index e1efa0eac4ff..69b2fac6f098 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -543,19 +543,32 @@ config SCSI_IN2000 module will be called in2000. config SCSI_ARCMSR - tristate "ARECA ARC11X0[PCI-X]/ARC12X0[PCI-EXPRESS] SATA-RAID support" + tristate "ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID Host Adapter" depends on PCI && SCSI help - This driver supports all of ARECA's SATA RAID controller cards. + This driver supports all of ARECA's SATA/SAS RAID controller cards. This is an ARECA-maintained driver by Erich Chen. - If you have any problems, please mail to: < erich@areca.com.tw > + If you have any problems, please mail to: . Areca supports Linux RAID config tools. - - < http://www.areca.com.tw > + Please link To compile this driver as a module, choose M here: the module will be called arcmsr (modprobe arcmsr). +config SCSI_ARCMSR_AER + bool "Enable PCI Error Recovery Capability in Areca Driver(ARCMSR)" + depends on SCSI_ARCMSR && PCIEAER + default n + help + The advanced error reporting(AER) capability is "NOT" provided by + ARC1200/1201/1202 SATA RAID controllers cards. + If your card is one of ARC1200/1201/1202, please use the default setting, n. + If your card is other models, you could pick it + on condition that the kernel version is greater than 2.6.19. + This function is maintained driver by Nick Cheng. If you have any + problems or suggestion, you are welcome to contact with . + To enable this function, choose Y here. + source "drivers/scsi/megaraid/Kconfig.megaraid" config SCSI_HPTIOP diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index f0b8bf4534f0..ace7a15b413e 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h @@ -9,7 +9,7 @@ ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved. ** ** Web site: www.areca.com.tw -** E-mail: erich@areca.com.tw +** E-mail: support@areca.com.tw ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License version 2 as @@ -45,19 +45,26 @@ #include struct class_device_attribute; - -#define ARCMSR_MAX_OUTSTANDING_CMD 256 -#define ARCMSR_MAX_FREECCB_NUM 288 -#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.14" +/*The limit of outstanding scsi command that firmware can handle*/ +#define ARCMSR_MAX_OUTSTANDING_CMD 256 +#define ARCMSR_MAX_FREECCB_NUM 320 +#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2007/08/30" #define ARCMSR_SCSI_INITIATOR_ID 255 #define ARCMSR_MAX_XFER_SECTORS 512 -#define ARCMSR_MAX_XFER_SECTORS_B 4096 -#define ARCMSR_MAX_TARGETID 17 -#define ARCMSR_MAX_TARGETLUN 8 -#define ARCMSR_MAX_CMD_PERLUN ARCMSR_MAX_OUTSTANDING_CMD -#define ARCMSR_MAX_QBUFFER 4096 -#define ARCMSR_MAX_SG_ENTRIES 38 - +#define ARCMSR_MAX_XFER_SECTORS_B 4096 +#define ARCMSR_MAX_TARGETID 17 +#define ARCMSR_MAX_TARGETLUN 8 +#define ARCMSR_MAX_CMD_PERLUN ARCMSR_MAX_OUTSTANDING_CMD +#define ARCMSR_MAX_QBUFFER 4096 +#define ARCMSR_MAX_SG_ENTRIES 38 +#define ARCMSR_MAX_HBB_POSTQUEUE 264 +/* +********************************************************************************** +** +********************************************************************************** +*/ +#define ARC_SUCCESS 0 +#define ARC_FAILURE 1 /* ******************************************************************************* ** split 64bits dma addressing @@ -90,7 +97,7 @@ struct CMD_MESSAGE_FIELD uint8_t messagedatabuffer[1032]; }; /* IOP message transfer */ -#define ARCMSR_MESSAGE_FAIL 0x0001 +#define ARCMSR_MESSAGE_FAIL 0x0001 /* DeviceType */ #define ARECA_SATA_RAID 0x90000000 /* FunctionCode */ @@ -163,27 +170,27 @@ struct QBUFFER }; /* ******************************************************************************* -** FIRMWARE INFO +** FIRMWARE INFO for Intel IOP R 80331 processor (Type A) ******************************************************************************* */ struct FIRMWARE_INFO { - uint32_t signature; /*0, 00-03*/ - uint32_t request_len; /*1, 04-07*/ - uint32_t numbers_queue; /*2, 08-11*/ + uint32_t signature; /*0, 00-03*/ + uint32_t request_len; /*1, 04-07*/ + uint32_t numbers_queue; /*2, 08-11*/ uint32_t sdram_size; /*3, 12-15*/ - uint32_t ide_channels; /*4, 16-19*/ - char vendor[40]; /*5, 20-59*/ - char model[8]; /*15, 60-67*/ - char firmware_ver[16]; /*17, 68-83*/ - char device_map[16]; /*21, 84-99*/ + uint32_t ide_channels; /*4, 16-19*/ + char vendor[40]; /*5, 20-59*/ + char model[8]; /*15, 60-67*/ + char firmware_ver[16]; /*17, 68-83*/ + char device_map[16]; /*21, 84-99*/ }; /* signature of set and get firmware config */ -#define ARCMSR_SIGNATURE_GET_CONFIG 0x87974060 -#define ARCMSR_SIGNATURE_SET_CONFIG 0x87974063 +#define ARCMSR_SIGNATURE_GET_CONFIG 0x87974060 +#define ARCMSR_SIGNATURE_SET_CONFIG 0x87974063 /* message code of inbound message register */ -#define ARCMSR_INBOUND_MESG0_NOP 0x00000000 -#define ARCMSR_INBOUND_MESG0_GET_CONFIG 0x00000001 +#define ARCMSR_INBOUND_MESG0_NOP 0x00000000 +#define ARCMSR_INBOUND_MESG0_GET_CONFIG 0x00000001 #define ARCMSR_INBOUND_MESG0_SET_CONFIG 0x00000002 #define ARCMSR_INBOUND_MESG0_ABORT_CMD 0x00000003 #define ARCMSR_INBOUND_MESG0_STOP_BGRB 0x00000004 @@ -203,6 +210,60 @@ struct FIRMWARE_INFO #define ARCMSR_CCBREPLY_FLAG_ERROR 0x10000000 /* outbound firmware ok */ #define ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK 0x80000000 + +/* +************************************************************************ +** SPEC. for Areca Type B adapter +************************************************************************ +*/ +/* ARECA HBB COMMAND for its FIRMWARE */ +/* window of "instruction flags" from driver to iop */ +#define ARCMSR_DRV2IOP_DOORBELL 0x00020400 +#define ARCMSR_DRV2IOP_DOORBELL_MASK 0x00020404 +/* window of "instruction flags" from iop to driver */ +#define ARCMSR_IOP2DRV_DOORBELL 0x00020408 +#define ARCMSR_IOP2DRV_DOORBELL_MASK 0x0002040C +/* ARECA FLAG LANGUAGE */ +/* ioctl transfer */ +#define ARCMSR_IOP2DRV_DATA_WRITE_OK 0x00000001 +/* ioctl transfer */ +#define ARCMSR_IOP2DRV_DATA_READ_OK 0x00000002 +#define ARCMSR_IOP2DRV_CDB_DONE 0x00000004 +#define ARCMSR_IOP2DRV_MESSAGE_CMD_DONE 0x00000008 + +#define ARCMSR_DOORBELL_HANDLE_INT 0x0000000F +#define ARCMSR_DOORBELL_INT_CLEAR_PATTERN 0xFF00FFF0 +#define ARCMSR_MESSAGE_INT_CLEAR_PATTERN 0xFF00FFF7 +/* (ARCMSR_INBOUND_MESG0_GET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_GET_CONFIG 0x00010008 +/* (ARCMSR_INBOUND_MESG0_SET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_SET_CONFIG 0x00020008 +/* (ARCMSR_INBOUND_MESG0_ABORT_CMD<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_ABORT_CMD 0x00030008 +/* (ARCMSR_INBOUND_MESG0_STOP_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_STOP_BGRB 0x00040008 +/* (ARCMSR_INBOUND_MESG0_FLUSH_CACHE<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_FLUSH_CACHE 0x00050008 +/* (ARCMSR_INBOUND_MESG0_START_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_START_BGRB 0x00060008 +#define ARCMSR_MESSAGE_START_DRIVER_MODE 0x000E0008 +#define ARCMSR_MESSAGE_SET_POST_WINDOW 0x000F0008 +/* ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK */ +#define ARCMSR_MESSAGE_FIRMWARE_OK 0x80000000 +/* ioctl transfer */ +#define ARCMSR_DRV2IOP_DATA_WRITE_OK 0x00000001 +/* ioctl transfer */ +#define ARCMSR_DRV2IOP_DATA_READ_OK 0x00000002 +#define ARCMSR_DRV2IOP_CDB_POSTED 0x00000004 +#define ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED 0x00000008 + +/* data tunnel buffer between user space program and its firmware */ +/* user space data to iop 128bytes */ +#define ARCMSR_IOCTL_WBUFFER 0x0000fe00 +/* iop data to user space 128bytes */ +#define ARCMSR_IOCTL_RBUFFER 0x0000ff00 +/* iop message_rwbuffer for message command */ +#define ARCMSR_MSGCODE_RWBUFFER 0x0000fa00 /* ******************************************************************************* ** ARECA SCSI COMMAND DESCRIPTOR BLOCK size 0x1F8 (504) @@ -214,7 +275,6 @@ struct ARCMSR_CDB uint8_t TargetID; uint8_t LUN; uint8_t Function; - uint8_t CdbLength; uint8_t sgcount; uint8_t Flags; @@ -224,20 +284,18 @@ struct ARCMSR_CDB #define ARCMSR_CDB_FLAG_SIMPLEQ 0x00 #define ARCMSR_CDB_FLAG_HEADQ 0x08 #define ARCMSR_CDB_FLAG_ORDEREDQ 0x10 - uint8_t Reserved1; + uint8_t Reserved1; uint32_t Context; uint32_t DataLength; - uint8_t Cdb[16]; - uint8_t DeviceStatus; -#define ARCMSR_DEV_CHECK_CONDITION 0x02 -#define ARCMSR_DEV_SELECT_TIMEOUT 0xF0 -#define ARCMSR_DEV_ABORTED 0xF1 -#define ARCMSR_DEV_INIT_FAIL 0xF2 - uint8_t SenseData[15]; +#define ARCMSR_DEV_CHECK_CONDITION 0x02 +#define ARCMSR_DEV_SELECT_TIMEOUT 0xF0 +#define ARCMSR_DEV_ABORTED 0xF1 +#define ARCMSR_DEV_INIT_FAIL 0xF2 + uint8_t SenseData[15]; union { struct SG32ENTRY sg32entry[ARCMSR_MAX_SG_ENTRIES]; @@ -246,10 +304,10 @@ struct ARCMSR_CDB }; /* ******************************************************************************* -** Messaging Unit (MU) of the Intel R 80331 I/O processor (80331) +** Messaging Unit (MU) of the Intel R 80331 I/O processor(Type A) and Type B processor ******************************************************************************* */ -struct MessageUnit +struct MessageUnit_A { uint32_t resrved0[4]; /*0000 000F*/ uint32_t inbound_msgaddr0; /*0010 0013*/ @@ -274,6 +332,30 @@ struct MessageUnit uint32_t message_rbuffer[32]; /*0F00 0F7F 32*/ uint32_t reserved6[32]; /*0F80 0FFF 32*/ }; + +struct MessageUnit_B +{ + uint32_t post_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; + uint32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; + uint32_t postq_index; + uint32_t doneq_index; + uint32_t *drv2iop_doorbell_reg; + uint32_t *drv2iop_doorbell_mask_reg; + uint32_t *iop2drv_doorbell_reg; + uint32_t *iop2drv_doorbell_mask_reg; + uint32_t *msgcode_rwbuffer_reg; + uint32_t *ioctl_wbuffer_reg; + uint32_t *ioctl_rbuffer_reg; +}; + +struct MessageUnit +{ + union + { + struct MessageUnit_A pmu_A; + struct MessageUnit_B pmu_B; + } u; +}; /* ******************************************************************************* ** Adapter Control Block @@ -281,37 +363,45 @@ struct MessageUnit */ struct AdapterControlBlock { + uint32_t adapter_type; /* adapter A,B..... */ + #define ACB_ADAPTER_TYPE_A 0x00000001 /* hba I IOP */ + #define ACB_ADAPTER_TYPE_B 0x00000002 /* hbb M IOP */ + #define ACB_ADAPTER_TYPE_C 0x00000004 /* hbc P IOP */ + #define ACB_ADAPTER_TYPE_D 0x00000008 /* hbd A IOP */ struct pci_dev * pdev; struct Scsi_Host * host; unsigned long vir2phy_offset; /* Offset is used in making arc cdb physical to virtual calculations */ uint32_t outbound_int_enable; - struct MessageUnit __iomem * pmu; + struct MessageUnit * pmu; /* message unit ATU inbound base address0 */ uint32_t acb_flags; -#define ACB_F_SCSISTOPADAPTER 0x0001 -#define ACB_F_MSG_STOP_BGRB 0x0002 + #define ACB_F_SCSISTOPADAPTER 0x0001 + #define ACB_F_MSG_STOP_BGRB 0x0002 /* stop RAID background rebuild */ -#define ACB_F_MSG_START_BGRB 0x0004 + #define ACB_F_MSG_START_BGRB 0x0004 /* stop RAID background rebuild */ -#define ACB_F_IOPDATA_OVERFLOW 0x0008 + #define ACB_F_IOPDATA_OVERFLOW 0x0008 /* iop message data rqbuffer overflow */ -#define ACB_F_MESSAGE_WQBUFFER_CLEARED 0x0010 + #define ACB_F_MESSAGE_WQBUFFER_CLEARED 0x0010 /* message clear wqbuffer */ -#define ACB_F_MESSAGE_RQBUFFER_CLEARED 0x0020 + #define ACB_F_MESSAGE_RQBUFFER_CLEARED 0x0020 /* message clear rqbuffer */ -#define ACB_F_MESSAGE_WQBUFFER_READED 0x0040 -#define ACB_F_BUS_RESET 0x0080 -#define ACB_F_IOP_INITED 0x0100 + #define ACB_F_MESSAGE_WQBUFFER_READED 0x0040 + #define ACB_F_BUS_RESET 0x0080 + #define ACB_F_IOP_INITED 0x0100 /* iop init */ struct CommandControlBlock * pccb_pool[ARCMSR_MAX_FREECCB_NUM]; /* used for memory free */ struct list_head ccb_free_list; /* head of free ccb list */ + atomic_t ccboutstandingcount; + /*The present outstanding command number that in the IOP that + waiting for being handled by FW*/ void * dma_coherent; /* dma_coherent used for memory free */ @@ -353,7 +443,7 @@ struct CommandControlBlock { struct ARCMSR_CDB arcmsr_cdb; /* - ** 0-503 (size of CDB=504): + ** 0-503 (size of CDB = 504): ** arcmsr messenger scsi command descriptor size 504 bytes */ uint32_t cdb_shifted_phyaddr; @@ -466,7 +556,9 @@ struct SENSE_DATA #define ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE 0x01 #define ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE 0x1F -extern void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb); +extern void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *); +extern void arcmsr_iop_message_read(struct AdapterControlBlock *); +extern struct QBUFFER *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *); extern struct class_device_attribute *arcmsr_host_attrs[]; -extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb); +extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *); void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb); diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index 06c0dce3b839..0f0a1ae99434 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c @@ -8,7 +8,7 @@ ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved ** ** Web site: www.areca.com.tw -** E-mail: erich@areca.com.tw +** E-mail: support@areca.com.tw ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License version 2 as @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -58,15 +59,11 @@ struct class_device_attribute *arcmsr_host_attrs[]; -static ssize_t -arcmsr_sysfs_iop_message_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) +static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj, char *buf, loff_t off, size_t count) { struct class_device *cdev = container_of(kobj,struct class_device,kobj); struct Scsi_Host *host = class_to_shost(cdev); struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; - struct MessageUnit __iomem *reg = acb->pmu; uint8_t *pQbuffer,*ptmpQbuffer; int32_t allxfer_len = 0; @@ -85,12 +82,13 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj, allxfer_len++; } if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - struct QBUFFER __iomem * prbuffer = (struct QBUFFER __iomem *) - ®->message_rbuffer; - uint8_t __iomem * iop_data = (uint8_t __iomem *)prbuffer->data; + struct QBUFFER *prbuffer; + uint8_t *iop_data; int32_t iop_len; acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; + prbuffer = arcmsr_get_iop_rqbuffer(acb); + iop_data = (uint8_t *)prbuffer->data; iop_len = readl(&prbuffer->data_len); while (iop_len > 0) { acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); @@ -99,16 +97,12 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj, iop_data++; iop_len--; } - writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, - ®->inbound_doorbell); + arcmsr_iop_message_read(acb); } return (allxfer_len); } -static ssize_t -arcmsr_sysfs_iop_message_write(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) +static ssize_t arcmsr_sysfs_iop_message_write(struct kobject *kobj, char *buf, loff_t off, size_t count) { struct class_device *cdev = container_of(kobj,struct class_device,kobj); struct Scsi_Host *host = class_to_shost(cdev); @@ -126,7 +120,7 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj, wqbuf_lastindex = acb->wqbuf_lastindex; wqbuf_firstindex = acb->wqbuf_firstindex; if (wqbuf_lastindex != wqbuf_firstindex) { - arcmsr_post_Qbuffer(acb); + arcmsr_post_ioctldata2iop(acb); return 0; /*need retry*/ } else { my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) @@ -144,7 +138,7 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj, if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { acb->acb_flags &= ~ACB_F_MESSAGE_WQBUFFER_CLEARED; - arcmsr_post_Qbuffer(acb); + arcmsr_post_ioctldata2iop(acb); } return count; } else { @@ -153,15 +147,11 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj, } } -static ssize_t -arcmsr_sysfs_iop_message_clear(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) +static ssize_t arcmsr_sysfs_iop_message_clear(struct kobject *kobj, char *buf, loff_t off, size_t count) { struct class_device *cdev = container_of(kobj,struct class_device,kobj); struct Scsi_Host *host = class_to_shost(cdev); struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; - struct MessageUnit __iomem *reg = acb->pmu; uint8_t *pQbuffer; if (!capable(CAP_SYS_ADMIN)) @@ -169,8 +159,7 @@ arcmsr_sysfs_iop_message_clear(struct kobject *kobj, if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK - , ®->inbound_doorbell); + arcmsr_iop_message_read(acb); } acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED @@ -191,6 +180,7 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = { .attr = { .name = "mu_read", .mode = S_IRUSR , + .owner = THIS_MODULE, }, .size = 1032, .read = arcmsr_sysfs_iop_message_read, @@ -200,6 +190,7 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = { .attr = { .name = "mu_write", .mode = S_IWUSR, + .owner = THIS_MODULE, }, .size = 1032, .write = arcmsr_sysfs_iop_message_write, @@ -209,6 +200,7 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = { .attr = { .name = "mu_clear", .mode = S_IWUSR, + .owner = THIS_MODULE, }, .size = 1, .write = arcmsr_sysfs_iop_message_clear, @@ -219,31 +211,26 @@ int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb) struct Scsi_Host *host = acb->host; int error; - error = sysfs_create_bin_file(&host->shost_classdev.kobj, - &arcmsr_sysfs_message_read_attr); + error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr); if (error) { printk(KERN_ERR "arcmsr: alloc sysfs mu_read failed\n"); goto error_bin_file_message_read; } - error = sysfs_create_bin_file(&host->shost_classdev.kobj, - &arcmsr_sysfs_message_write_attr); + error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr); if (error) { printk(KERN_ERR "arcmsr: alloc sysfs mu_write failed\n"); goto error_bin_file_message_write; } - error = sysfs_create_bin_file(&host->shost_classdev.kobj, - &arcmsr_sysfs_message_clear_attr); + error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_clear_attr); if (error) { printk(KERN_ERR "arcmsr: alloc sysfs mu_clear failed\n"); goto error_bin_file_message_clear; } return 0; error_bin_file_message_clear: - sysfs_remove_bin_file(&host->shost_classdev.kobj, - &arcmsr_sysfs_message_write_attr); + sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr); error_bin_file_message_write: - sysfs_remove_bin_file(&host->shost_classdev.kobj, - &arcmsr_sysfs_message_read_attr); + sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr); error_bin_file_message_read: return error; } @@ -252,12 +239,9 @@ void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb) { struct Scsi_Host *host = acb->host; - sysfs_remove_bin_file(&host->shost_classdev.kobj, - &arcmsr_sysfs_message_clear_attr); - sysfs_remove_bin_file(&host->shost_classdev.kobj, - &arcmsr_sysfs_message_write_attr); - sysfs_remove_bin_file(&host->shost_classdev.kobj, - &arcmsr_sysfs_message_read_attr); + sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_clear_attr); + sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr); + sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr); } diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 0ddfc21e9f7d..d70398ac64db 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -9,7 +9,7 @@ ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved ** ** Web site: www.areca.com.tw -** E-mail: erich@areca.com.tw +** E-mail: support@areca.com.tw ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License version 2 as @@ -71,33 +71,37 @@ #include #include "arcmsr.h" -MODULE_AUTHOR("Erich Chen "); +MODULE_AUTHOR("Erich Chen "); MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID HOST Adapter"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_VERSION(ARCMSR_DRIVER_VERSION); -static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_cmnd *cmd); +static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, + struct scsi_cmnd *cmd); +static int arcmsr_iop_confirm(struct AdapterControlBlock *acb); static int arcmsr_abort(struct scsi_cmnd *); static int arcmsr_bus_reset(struct scsi_cmnd *); static int arcmsr_bios_param(struct scsi_device *sdev, - struct block_device *bdev, sector_t capacity, int *info); -static int arcmsr_queue_command(struct scsi_cmnd * cmd, - void (*done) (struct scsi_cmnd *)); + struct block_device *bdev, sector_t capacity, int *info); +static int arcmsr_queue_command(struct scsi_cmnd *cmd, + void (*done) (struct scsi_cmnd *)); static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id); static void arcmsr_remove(struct pci_dev *pdev); static void arcmsr_shutdown(struct pci_dev *pdev); static void arcmsr_iop_init(struct AdapterControlBlock *acb); static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb); +static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb); static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); -static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); -static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb); +static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb); +static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb); static const char *arcmsr_info(struct Scsi_Host *); static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state); static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev); -static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, int queue_depth) +static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, + int queue_depth) { if (queue_depth > ARCMSR_MAX_CMD_PERLUN) queue_depth = ARCMSR_MAX_CMD_PERLUN; @@ -123,17 +127,21 @@ static struct scsi_host_template arcmsr_scsi_host_template = { .use_clustering = ENABLE_CLUSTERING, .shost_attrs = arcmsr_host_attrs, }; +#ifdef CONFIG_SCSI_ARCMSR_AER static struct pci_error_handlers arcmsr_pci_error_handlers = { .error_detected = arcmsr_pci_error_detected, .slot_reset = arcmsr_pci_slot_reset, }; - +#endif static struct pci_device_id arcmsr_device_id_table[] = { {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)}, {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1120)}, {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1130)}, {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1160)}, {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1170)}, + {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1200)}, + {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1201)}, + {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1202)}, {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1210)}, {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1220)}, {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1230)}, @@ -153,20 +161,20 @@ static struct pci_driver arcmsr_pci_driver = { .probe = arcmsr_probe, .remove = arcmsr_remove, .shutdown = arcmsr_shutdown, + #ifdef CONFIG_SCSI_ARCMSR_AER .err_handler = &arcmsr_pci_error_handlers, + #endif }; static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id) { irqreturn_t handle_state; - struct AdapterControlBlock *acb; - unsigned long flags; - - acb = (struct AdapterControlBlock *)dev_id; + struct AdapterControlBlock *acb = dev_id; - spin_lock_irqsave(acb->host->host_lock, flags); + spin_lock(acb->host->host_lock); handle_state = arcmsr_interrupt(acb); - spin_unlock_irqrestore(acb->host->host_lock, flags); + spin_unlock(acb->host->host_lock); + return handle_state; } @@ -198,68 +206,159 @@ static int arcmsr_bios_param(struct scsi_device *sdev, return 0; } -static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) +static void arcmsr_define_adapter_type(struct AdapterControlBlock *acb) { struct pci_dev *pdev = acb->pdev; - struct MessageUnit __iomem *reg = acb->pmu; - u32 ccb_phyaddr_hi32; - void *dma_coherent; - dma_addr_t dma_coherent_handle, dma_addr; - struct CommandControlBlock *ccb_tmp; - int i, j; + u16 dev_id; + pci_read_config_word(pdev, PCI_DEVICE_ID, &dev_id); + switch (dev_id) { + case 0x1201 : { + acb->adapter_type = ACB_ADAPTER_TYPE_B; + } + break; + + default : acb->adapter_type = ACB_ADAPTER_TYPE_A; + } +} + +static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) +{ + + switch (acb->adapter_type) { - dma_coherent = dma_alloc_coherent(&pdev->dev, + case ACB_ADAPTER_TYPE_A: { + struct pci_dev *pdev = acb->pdev; + void *dma_coherent; + dma_addr_t dma_coherent_handle, dma_addr; + struct CommandControlBlock *ccb_tmp; + uint32_t intmask_org; + int i, j; + + acb->pmu = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + if (!acb->pmu) { + printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", + acb->host->host_no); + } + + dma_coherent = dma_alloc_coherent(&pdev->dev, ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20, &dma_coherent_handle, GFP_KERNEL); - if (!dma_coherent) - return -ENOMEM; + if (!dma_coherent) + return -ENOMEM; - acb->dma_coherent = dma_coherent; - acb->dma_coherent_handle = dma_coherent_handle; + acb->dma_coherent = dma_coherent; + acb->dma_coherent_handle = dma_coherent_handle; - if (((unsigned long)dma_coherent & 0x1F)) { - dma_coherent = dma_coherent + - (0x20 - ((unsigned long)dma_coherent & 0x1F)); - dma_coherent_handle = dma_coherent_handle + - (0x20 - ((unsigned long)dma_coherent_handle & 0x1F)); - } + if (((unsigned long)dma_coherent & 0x1F)) { + dma_coherent = dma_coherent + + (0x20 - ((unsigned long)dma_coherent & 0x1F)); + dma_coherent_handle = dma_coherent_handle + + (0x20 - ((unsigned long)dma_coherent_handle & 0x1F)); + } - dma_addr = dma_coherent_handle; - ccb_tmp = (struct CommandControlBlock *)dma_coherent; - for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { - ccb_tmp->cdb_shifted_phyaddr = dma_addr >> 5; - ccb_tmp->acb = acb; - acb->pccb_pool[i] = ccb_tmp; - list_add_tail(&ccb_tmp->list, &acb->ccb_free_list); - dma_addr = dma_addr + sizeof (struct CommandControlBlock); - ccb_tmp++; - } + dma_addr = dma_coherent_handle; + ccb_tmp = (struct CommandControlBlock *)dma_coherent; + for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { + ccb_tmp->cdb_shifted_phyaddr = dma_addr >> 5; + ccb_tmp->acb = acb; + acb->pccb_pool[i] = ccb_tmp; + list_add_tail(&ccb_tmp->list, &acb->ccb_free_list); + dma_addr = dma_addr + sizeof(struct CommandControlBlock); + ccb_tmp++; + } - acb->vir2phy_offset = (unsigned long)ccb_tmp - - (unsigned long)dma_addr; - for (i = 0; i < ARCMSR_MAX_TARGETID; i++) - for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) - acb->devstate[i][j] = ARECA_RAID_GOOD; + acb->vir2phy_offset = (unsigned long)ccb_tmp -(unsigned long)dma_addr; + for (i = 0; i < ARCMSR_MAX_TARGETID; i++) + for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) + acb->devstate[i][j] = ARECA_RAID_GONE; - /* - ** here we need to tell iop 331 our ccb_tmp.HighPart - ** if ccb_tmp.HighPart is not zero - */ - ccb_phyaddr_hi32 = (uint32_t) ((dma_coherent_handle >> 16) >> 16); - if (ccb_phyaddr_hi32 != 0) { - writel(ARCMSR_SIGNATURE_SET_CONFIG, ®->message_rwbuffer[0]); - writel(ccb_phyaddr_hi32, ®->message_rwbuffer[1]); - writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, ®->inbound_msgaddr0); - if (arcmsr_wait_msgint_ready(acb)) - printk(KERN_NOTICE "arcmsr%d: " - "'set ccb high part physical address' timeout\n", - acb->host->host_no); - } + /* + ** here we need to tell iop 331 our ccb_tmp.HighPart + ** if ccb_tmp.HighPart is not zero + */ + intmask_org = arcmsr_disable_outbound_ints(acb); + } + break; + + case ACB_ADAPTER_TYPE_B: { + + struct pci_dev *pdev = acb->pdev; + struct MessageUnit_B *reg; + void *mem_base0, *mem_base1; + void *dma_coherent; + dma_addr_t dma_coherent_handle, dma_addr; + uint32_t intmask_org; + struct CommandControlBlock *ccb_tmp; + int i, j; + + dma_coherent = dma_alloc_coherent(&pdev->dev, + ((ARCMSR_MAX_FREECCB_NUM * + sizeof(struct CommandControlBlock) + 0x20) + + sizeof(struct MessageUnit_B)), + &dma_coherent_handle, GFP_KERNEL); + if (!dma_coherent) + return -ENOMEM; + + acb->dma_coherent = dma_coherent; + acb->dma_coherent_handle = dma_coherent_handle; + + if (((unsigned long)dma_coherent & 0x1F)) { + dma_coherent = dma_coherent + + (0x20 - ((unsigned long)dma_coherent & 0x1F)); + dma_coherent_handle = dma_coherent_handle + + (0x20 - ((unsigned long)dma_coherent_handle & 0x1F)); + } + + reg = (struct MessageUnit_B *)(dma_coherent + + ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock)); + + dma_addr = dma_coherent_handle; + ccb_tmp = (struct CommandControlBlock *)dma_coherent; + for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { + ccb_tmp->cdb_shifted_phyaddr = dma_addr >> 5; + ccb_tmp->acb = acb; + acb->pccb_pool[i] = ccb_tmp; + list_add_tail(&ccb_tmp->list, &acb->ccb_free_list); + dma_addr = dma_addr + sizeof(struct CommandControlBlock); + ccb_tmp++; + } + + reg = (struct MessageUnit_B *)(dma_coherent + + ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock)); + acb->pmu = (struct MessageUnit_B *)reg; + mem_base0 = ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + mem_base1 = ioremap(pci_resource_start(pdev, 2), + pci_resource_len(pdev, 2)); + reg->drv2iop_doorbell_reg = (uint32_t *)((char *)mem_base0 + + ARCMSR_DRV2IOP_DOORBELL); + reg->drv2iop_doorbell_mask_reg = (uint32_t *)((char *)mem_base0 + + ARCMSR_DRV2IOP_DOORBELL_MASK); + reg->iop2drv_doorbell_reg = (uint32_t *)((char *)mem_base0 + + ARCMSR_IOP2DRV_DOORBELL); + reg->iop2drv_doorbell_mask_reg = (uint32_t *)((char *)mem_base0 + + ARCMSR_IOP2DRV_DOORBELL_MASK); + reg->ioctl_wbuffer_reg = (uint32_t *)((char *)mem_base1 + + ARCMSR_IOCTL_WBUFFER); + reg->ioctl_rbuffer_reg = (uint32_t *)((char *)mem_base1 + + ARCMSR_IOCTL_RBUFFER); + reg->msgcode_rwbuffer_reg = (uint32_t *)((char *)mem_base1 + + ARCMSR_MSGCODE_RWBUFFER); + + acb->vir2phy_offset = (unsigned long)ccb_tmp -(unsigned long)dma_addr; + for (i = 0; i < ARCMSR_MAX_TARGETID; i++) + for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) + acb->devstate[i][j] = ARECA_RAID_GOOD; - writel(readl(®->outbound_intmask) | - ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, - ®->outbound_intmask); + /* + ** here we need to tell iop 331 our ccb_tmp.HighPart + ** if ccb_tmp.HighPart is not zero + */ + intmask_org = arcmsr_disable_outbound_ints(acb); + } + break; + } return 0; } @@ -310,16 +409,11 @@ static int arcmsr_probe(struct pci_dev *pdev, host->unique_id = (bus << 8) | dev_fun; host->irq = pdev->irq; error = pci_request_regions(pdev, "arcmsr"); - if (error) + if (error) { goto out_host_put; - - acb->pmu = ioremap(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - if (!acb->pmu) { - printk(KERN_NOTICE "arcmsr%d: memory" - " mapping region fail \n", acb->host->host_no); - goto out_release_regions; } + arcmsr_define_adapter_type(acb); + acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | ACB_F_MESSAGE_RQBUFFER_CLEARED | ACB_F_MESSAGE_WQBUFFER_READED); @@ -328,10 +422,10 @@ static int arcmsr_probe(struct pci_dev *pdev, error = arcmsr_alloc_ccb_pool(acb); if (error) - goto out_iounmap; + goto out_release_regions; error = request_irq(pdev->irq, arcmsr_do_interrupt, - IRQF_DISABLED | IRQF_SHARED, "arcmsr", acb); + IRQF_SHARED, "arcmsr", acb); if (error) goto out_free_ccb_pool; @@ -349,14 +443,15 @@ static int arcmsr_probe(struct pci_dev *pdev, goto out_free_sysfs; scsi_scan_host(host); + #ifdef CONFIG_SCSI_ARCMSR_AER pci_enable_pcie_error_reporting(pdev); + #endif return 0; out_free_sysfs: out_free_irq: free_irq(pdev->irq, acb); out_free_ccb_pool: arcmsr_free_ccb_pool(acb); - out_iounmap: iounmap(acb->pmu); out_release_regions: pci_release_regions(pdev); @@ -368,17 +463,84 @@ static int arcmsr_probe(struct pci_dev *pdev, return error; } -static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) +static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) +{ + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + uint32_t Index; + uint8_t Retries = 0x00; + + do { + for (Index = 0; Index < 100; Index++) { + if (readl(®->outbound_intstatus) & + ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { + writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT, + ®->outbound_intstatus); + return 0x00; + } + msleep(10); + }/*max 1 seconds*/ + + } while (Retries++ < 20);/*max 20 sec*/ + return 0xff; +} + +static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) +{ + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + uint32_t Index; + uint8_t Retries = 0x00; + + do { + for (Index = 0; Index < 100; Index++) { + if (readl(reg->iop2drv_doorbell_reg) + & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { + writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN + , reg->iop2drv_doorbell_reg); + return 0x00; + } + msleep(10); + }/*max 1 seconds*/ + + } while (Retries++ < 20);/*max 20 sec*/ + return 0xff; +} + +static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) { - struct MessageUnit __iomem *reg = acb->pmu; + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0); - if (arcmsr_wait_msgint_ready(acb)) + if (arcmsr_hba_wait_msgint_ready(acb)) + printk(KERN_NOTICE + "arcmsr%d: wait 'abort all outstanding command' timeout \n" + , acb->host->host_no); +} + +static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) +{ + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + + writel(ARCMSR_MESSAGE_ABORT_CMD, reg->drv2iop_doorbell_reg); + if (arcmsr_hbb_wait_msgint_ready(acb)) printk(KERN_NOTICE "arcmsr%d: wait 'abort all outstanding command' timeout \n" , acb->host->host_no); } +static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + arcmsr_abort_hba_allcmd(acb); + } + break; + + case ACB_ADAPTER_TYPE_B: { + arcmsr_abort_hbb_allcmd(acb); + } + } +} + static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb) { struct scsi_cmnd *pcmd = ccb->pcmd; @@ -400,28 +562,239 @@ static void arcmsr_ccb_complete(struct CommandControlBlock *ccb, int stand_flag) pcmd->scsi_done(pcmd); } +static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) +{ + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + int retry_count = 30; + + writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); + do { + if (!arcmsr_hba_wait_msgint_ready(acb)) + break; + else { + retry_count--; + printk(KERN_NOTICE "arcmsr%d: wait 'flush adapter cache' \ + timeout, retry count down = %d \n", acb->host->host_no, retry_count); + } + } while (retry_count != 0); +} + +static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) +{ + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + int retry_count = 30; + + writel(ARCMSR_MESSAGE_FLUSH_CACHE, reg->drv2iop_doorbell_reg); + do { + if (!arcmsr_hbb_wait_msgint_ready(acb)) + break; + else { + retry_count--; + printk(KERN_NOTICE "arcmsr%d: wait 'flush adapter cache' \ + timeout,retry count down = %d \n", acb->host->host_no, retry_count); + } + } while (retry_count != 0); +} + +static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A: { + arcmsr_flush_hba_cache(acb); + } + break; + + case ACB_ADAPTER_TYPE_B: { + arcmsr_flush_hbb_cache(acb); + } + } +} + +static void arcmsr_report_sense_info(struct CommandControlBlock *ccb) +{ + + struct scsi_cmnd *pcmd = ccb->pcmd; + struct SENSE_DATA *sensebuffer = (struct SENSE_DATA *)pcmd->sense_buffer; + + pcmd->result = DID_OK << 16; + if (sensebuffer) { + int sense_data_length = + sizeof(struct SENSE_DATA) < sizeof(pcmd->sense_buffer) + ? sizeof(struct SENSE_DATA) : sizeof(pcmd->sense_buffer); + memset(sensebuffer, 0, sizeof(pcmd->sense_buffer)); + memcpy(sensebuffer, ccb->arcmsr_cdb.SenseData, sense_data_length); + sensebuffer->ErrorCode = SCSI_SENSE_CURRENT_ERRORS; + sensebuffer->Valid = 1; + } +} + +static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) +{ + u32 orig_mask = 0; + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A : { + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + orig_mask = readl(®->outbound_intmask)|\ + ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; + writel(orig_mask|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, \ + ®->outbound_intmask); + } + break; + + case ACB_ADAPTER_TYPE_B : { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + orig_mask = readl(reg->iop2drv_doorbell_mask_reg) & \ + (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); + writel(0, reg->iop2drv_doorbell_mask_reg); + } + break; + } + return orig_mask; +} + +static void arcmsr_report_ccb_state(struct AdapterControlBlock *acb, \ + struct CommandControlBlock *ccb, uint32_t flag_ccb) +{ + + uint8_t id, lun; + id = ccb->pcmd->device->id; + lun = ccb->pcmd->device->lun; + if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { + if (acb->devstate[id][lun] == ARECA_RAID_GONE) + acb->devstate[id][lun] = ARECA_RAID_GOOD; + ccb->pcmd->result = DID_OK << 16; + arcmsr_ccb_complete(ccb, 1); + } else { + switch (ccb->arcmsr_cdb.DeviceStatus) { + case ARCMSR_DEV_SELECT_TIMEOUT: { + acb->devstate[id][lun] = ARECA_RAID_GONE; + ccb->pcmd->result = DID_NO_CONNECT << 16; + arcmsr_ccb_complete(ccb, 1); + } + break; + + case ARCMSR_DEV_ABORTED: + + case ARCMSR_DEV_INIT_FAIL: { + acb->devstate[id][lun] = ARECA_RAID_GONE; + ccb->pcmd->result = DID_BAD_TARGET << 16; + arcmsr_ccb_complete(ccb, 1); + } + break; + + case ARCMSR_DEV_CHECK_CONDITION: { + acb->devstate[id][lun] = ARECA_RAID_GOOD; + arcmsr_report_sense_info(ccb); + arcmsr_ccb_complete(ccb, 1); + } + break; + + default: + printk(KERN_NOTICE + "arcmsr%d: scsi id = %d lun = %d" + " isr get command error done, " + "but got unknown DeviceStatus = 0x%x \n" + , acb->host->host_no + , id + , lun + , ccb->arcmsr_cdb.DeviceStatus); + acb->devstate[id][lun] = ARECA_RAID_GONE; + ccb->pcmd->result = DID_NO_CONNECT << 16; + arcmsr_ccb_complete(ccb, 1); + break; + } + } +} + +static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, uint32_t flag_ccb) + +{ + struct CommandControlBlock *ccb; + + ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + (flag_ccb << 5)); + if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { + if (ccb->startdone == ARCMSR_CCB_ABORTED) { + struct scsi_cmnd *abortcmd = ccb->pcmd; + if (abortcmd) { + abortcmd->result |= DID_ABORT << 16; + arcmsr_ccb_complete(ccb, 1); + printk(KERN_NOTICE "arcmsr%d: ccb ='0x%p' \ + isr got aborted command \n", acb->host->host_no, ccb); + } + } + printk(KERN_NOTICE "arcmsr%d: isr get an illegal ccb command \ + done acb = '0x%p'" + "ccb = '0x%p' ccbacb = '0x%p' startdone = 0x%x" + " ccboutstandingcount = %d \n" + , acb->host->host_no + , acb + , ccb + , ccb->acb + , ccb->startdone + , atomic_read(&acb->ccboutstandingcount)); + } + arcmsr_report_ccb_state(acb, ccb, flag_ccb); +} + +static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) +{ + int i = 0; + uint32_t flag_ccb; + + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A: { + struct MessageUnit_A __iomem *reg = \ + (struct MessageUnit_A *)acb->pmu; + uint32_t outbound_intstatus; + outbound_intstatus = readl(®->outbound_intstatus) & \ + acb->outbound_int_enable; + /*clear and abort all outbound posted Q*/ + writel(outbound_intstatus, ®->outbound_intstatus);/*clear interrupt*/ + while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) \ + && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { + arcmsr_drain_donequeue(acb, flag_ccb); + } + } + break; + + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + /*clear all outbound posted Q*/ + for (i = 0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { + if ((flag_ccb = readl(®->done_qbuffer[i])) != 0) { + writel(0, ®->done_qbuffer[i]); + arcmsr_drain_donequeue(acb, flag_ccb); + } + writel(0, ®->post_qbuffer[i]); + } + reg->doneq_index = 0; + reg->postq_index = 0; + } + break; + } +} static void arcmsr_remove(struct pci_dev *pdev) { struct Scsi_Host *host = pci_get_drvdata(pdev); struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; - struct MessageUnit __iomem *reg = acb->pmu; int poll_count = 0; arcmsr_free_sysfs_attr(acb); scsi_remove_host(host); arcmsr_stop_adapter_bgrb(acb); arcmsr_flush_adapter_cache(acb); - writel(readl(®->outbound_intmask) | - ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, - ®->outbound_intmask); + arcmsr_disable_outbound_ints(acb); acb->acb_flags |= ACB_F_SCSISTOPADAPTER; acb->acb_flags &= ~ACB_F_IOP_INITED; - for (poll_count = 0; poll_count < 256; poll_count++) { + for (poll_count = 0; poll_count < ARCMSR_MAX_OUTSTANDING_CMD; poll_count++) { if (!atomic_read(&acb->ccboutstandingcount)) break; - arcmsr_interrupt(acb); + arcmsr_interrupt(acb);/* FIXME: need spinlock */ msleep(25); } @@ -429,8 +802,7 @@ static void arcmsr_remove(struct pci_dev *pdev) int i; arcmsr_abort_allcmd(acb); - for (i = 0; i < ARCMSR_MAX_OUTSTANDING_CMD; i++) - readl(®->outbound_queueport); + arcmsr_done4abort_postqueue(acb); for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { struct CommandControlBlock *ccb = acb->pccb_pool[i]; if (ccb->startdone == ARCMSR_CCB_START) { @@ -477,86 +849,43 @@ static void arcmsr_module_exit(void) module_init(arcmsr_module_init); module_exit(arcmsr_module_exit); -static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) -{ - struct MessageUnit __iomem *reg = acb->pmu; - u32 orig_mask = readl(®->outbound_intmask); - - writel(orig_mask | ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, - ®->outbound_intmask); - return orig_mask; -} - -static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, - u32 orig_mask) +static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \ + u32 intmask_org) { - struct MessageUnit __iomem *reg = acb->pmu; u32 mask; - mask = orig_mask & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | - ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); - writel(mask, ®->outbound_intmask); -} - -static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) -{ - struct MessageUnit __iomem *reg = acb->pmu; - - writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); - if (arcmsr_wait_msgint_ready(acb)) - printk(KERN_NOTICE - "arcmsr%d: wait 'flush adapter cache' timeout \n" - , acb->host->host_no); -} + switch (acb->adapter_type) { -static void arcmsr_report_sense_info(struct CommandControlBlock *ccb) -{ - struct scsi_cmnd *pcmd = ccb->pcmd; - struct SENSE_DATA *sensebuffer = (struct SENSE_DATA *)pcmd->sense_buffer; + case ACB_ADAPTER_TYPE_A : { + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + mask = intmask_org & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | + ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); + writel(mask, ®->outbound_intmask); + acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; + } + break; - pcmd->result = DID_OK << 16; - if (sensebuffer) { - int sense_data_length = - sizeof (struct SENSE_DATA) < sizeof (pcmd->sense_buffer) - ? sizeof (struct SENSE_DATA) : sizeof (pcmd->sense_buffer); - memset(sensebuffer, 0, sizeof (pcmd->sense_buffer)); - memcpy(sensebuffer, ccb->arcmsr_cdb.SenseData, sense_data_length); - sensebuffer->ErrorCode = SCSI_SENSE_CURRENT_ERRORS; - sensebuffer->Valid = 1; + case ACB_ADAPTER_TYPE_B : { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + mask = intmask_org | (ARCMSR_IOP2DRV_DATA_WRITE_OK | \ + ARCMSR_IOP2DRV_DATA_READ_OK | ARCMSR_IOP2DRV_CDB_DONE); + writel(mask, reg->iop2drv_doorbell_mask_reg); + acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; + } } } -static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb) +static void arcmsr_build_ccb(struct AdapterControlBlock *acb, + struct CommandControlBlock *ccb, struct scsi_cmnd *pcmd) { - struct MessageUnit __iomem *reg = acb->pmu; - uint32_t Index; - uint8_t Retries = 0x00; - - do { - for (Index = 0; Index < 100; Index++) { - if (readl(®->outbound_intstatus) - & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { - writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT - , ®->outbound_intstatus); - return 0x00; - } - msleep_interruptible(10); - }/*max 1 seconds*/ - } while (Retries++ < 20);/*max 20 sec*/ - return 0xff; -} - -static void arcmsr_build_ccb(struct AdapterControlBlock *acb, - struct CommandControlBlock *ccb, struct scsi_cmnd *pcmd) -{ - struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb; - int8_t *psge = (int8_t *)&arcmsr_cdb->u; - uint32_t address_lo, address_hi; - int arccdbsize = 0x30; - int nseg; + struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb; + int8_t *psge = (int8_t *)&arcmsr_cdb->u; + uint32_t address_lo, address_hi; + int arccdbsize = 0x30; + int nseg; ccb->pcmd = pcmd; - memset(arcmsr_cdb, 0, sizeof (struct ARCMSR_CDB)); + memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); arcmsr_cdb->Bus = 0; arcmsr_cdb->TargetID = pcmd->device->id; arcmsr_cdb->LUN = pcmd->device->lun; @@ -609,52 +938,85 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb) { - struct MessageUnit __iomem *reg = acb->pmu; uint32_t cdb_shifted_phyaddr = ccb->cdb_shifted_phyaddr; struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb; - atomic_inc(&acb->ccboutstandingcount); ccb->startdone = ARCMSR_CCB_START; - if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) - writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, + + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + struct MessageUnit_A *reg = (struct MessageUnit_A *)acb->pmu; + + if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) + writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, ®->inbound_queueport); - else - writel(cdb_shifted_phyaddr, ®->inbound_queueport); -} + else { + writel(cdb_shifted_phyaddr, ®->inbound_queueport); + } + } + break; -void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb) -{ - struct MessageUnit __iomem *reg = acb->pmu; - struct QBUFFER __iomem *pwbuffer = (struct QBUFFER __iomem *) ®->message_wbuffer; - uint8_t __iomem *iop_data = (uint8_t __iomem *) pwbuffer->data; - int32_t allxfer_len = 0; + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + uint32_t ending_index, index = reg->postq_index; - if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) { - acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); - while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) - && (allxfer_len < 124)) { - writeb(acb->wqbuffer[acb->wqbuf_firstindex], iop_data); - acb->wqbuf_firstindex++; - acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; - iop_data++; - allxfer_len++; + ending_index = ((index + 1) % ARCMSR_MAX_HBB_POSTQUEUE); + writel(0, ®->post_qbuffer[ending_index]); + if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { + writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE,\ + ®->post_qbuffer[index]); + } + else { + writel(cdb_shifted_phyaddr, ®->post_qbuffer[index]); + } + index++; + index %= ARCMSR_MAX_HBB_POSTQUEUE;/*if last index number set it to 0 */ + reg->postq_index = index; + writel(ARCMSR_DRV2IOP_CDB_POSTED, reg->drv2iop_doorbell_reg); } - writel(allxfer_len, &pwbuffer->data_len); - writel(ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK - , ®->inbound_doorbell); + break; } } -static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) +static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) { - struct MessageUnit __iomem *reg = acb->pmu; - + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; acb->acb_flags &= ~ACB_F_MSG_START_BGRB; writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, ®->inbound_msgaddr0); - if (arcmsr_wait_msgint_ready(acb)) + + if (arcmsr_hba_wait_msgint_ready(acb)) { + printk(KERN_NOTICE + "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" + , acb->host->host_no); + } +} + +static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) +{ + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + acb->acb_flags &= ~ACB_F_MSG_START_BGRB; + writel(ARCMSR_MESSAGE_STOP_BGRB, reg->drv2iop_doorbell_reg); + + if (arcmsr_hbb_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" , acb->host->host_no); + } +} + +static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + arcmsr_stop_hba_bgrb(acb); + } + break; + + case ACB_ADAPTER_TYPE_B: { + arcmsr_stop_hbb_bgrb(acb); + } + break; + } } static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb) @@ -665,151 +1027,260 @@ static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb) acb->dma_coherent_handle); } -static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) +void arcmsr_iop_message_read(struct AdapterControlBlock *acb) { - struct MessageUnit __iomem *reg = acb->pmu; - struct CommandControlBlock *ccb; - uint32_t flag_ccb, outbound_intstatus, outbound_doorbell; + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell); + } + break; - outbound_intstatus = readl(®->outbound_intstatus) - & acb->outbound_int_enable; - writel(outbound_intstatus, ®->outbound_intstatus); - if (outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { - outbound_doorbell = readl(®->outbound_doorbell); - writel(outbound_doorbell, ®->outbound_doorbell); - if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { - struct QBUFFER __iomem * prbuffer = - (struct QBUFFER __iomem *) ®->message_rbuffer; - uint8_t __iomem * iop_data = (uint8_t __iomem *)prbuffer->data; - int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; - - rqbuf_lastindex = acb->rqbuf_lastindex; - rqbuf_firstindex = acb->rqbuf_firstindex; - iop_len = readl(&prbuffer->data_len); - my_empty_len = (rqbuf_firstindex - rqbuf_lastindex - 1) - &(ARCMSR_MAX_QBUFFER - 1); - if (my_empty_len >= iop_len) { - while (iop_len > 0) { - acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); - acb->rqbuf_lastindex++; - acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; - iop_data++; - iop_len--; - } - writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, - ®->inbound_doorbell); - } else - acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; - } - if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { - acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; - if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) { - struct QBUFFER __iomem * pwbuffer = - (struct QBUFFER __iomem *) ®->message_wbuffer; - uint8_t __iomem * iop_data = (uint8_t __iomem *) pwbuffer->data; - int32_t allxfer_len = 0; - - acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); - while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) - && (allxfer_len < 124)) { - writeb(acb->wqbuffer[acb->wqbuf_firstindex], iop_data); - acb->wqbuf_firstindex++; - acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; - iop_data++; - allxfer_len++; - } - writel(allxfer_len, &pwbuffer->data_len); - writel(ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK, - ®->inbound_doorbell); - } - if (acb->wqbuf_firstindex == acb->wqbuf_lastindex) - acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg); } + break; } - if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { - int id, lun; +} + +static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; /* - **************************************************************** - ** areca cdb command done - **************************************************************** + ** push inbound doorbell tell iop, driver data write ok + ** and wait reply on next hwinterrupt for next Qbuffer post */ - while (1) { - if ((flag_ccb = readl(®->outbound_queueport)) == 0xFFFFFFFF) - break;/*chip FIFO no ccb for completion already*/ - /* check if command done with no error*/ - ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + - (flag_ccb << 5)); - if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { - if (ccb->startdone == ARCMSR_CCB_ABORTED) { - struct scsi_cmnd *abortcmd = ccb->pcmd; - if (abortcmd) { - abortcmd->result |= DID_ABORT >> 16; - arcmsr_ccb_complete(ccb, 1); - printk(KERN_NOTICE - "arcmsr%d: ccb ='0x%p' isr got aborted command \n" - , acb->host->host_no, ccb); - } - continue; - } - printk(KERN_NOTICE - "arcmsr%d: isr get an illegal ccb command done acb = '0x%p'" - "ccb = '0x%p' ccbacb = '0x%p' startdone = 0x%x" - " ccboutstandingcount = %d \n" - , acb->host->host_no - , acb - , ccb - , ccb->acb - , ccb->startdone - , atomic_read(&acb->ccboutstandingcount)); - continue; - } - id = ccb->pcmd->device->id; - lun = ccb->pcmd->device->lun; - if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { - if (acb->devstate[id][lun] == ARECA_RAID_GONE) - acb->devstate[id][lun] = ARECA_RAID_GOOD; - ccb->pcmd->result = DID_OK << 16; - arcmsr_ccb_complete(ccb, 1); - } else { - switch(ccb->arcmsr_cdb.DeviceStatus) { - case ARCMSR_DEV_SELECT_TIMEOUT: { - acb->devstate[id][lun] = ARECA_RAID_GONE; - ccb->pcmd->result = DID_NO_CONNECT << 16; - arcmsr_ccb_complete(ccb, 1); - } - break; - case ARCMSR_DEV_ABORTED: - case ARCMSR_DEV_INIT_FAIL: { - acb->devstate[id][lun] = ARECA_RAID_GONE; - ccb->pcmd->result = DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); - } - break; - case ARCMSR_DEV_CHECK_CONDITION: { - acb->devstate[id][lun] = ARECA_RAID_GOOD; - arcmsr_report_sense_info(ccb); - arcmsr_ccb_complete(ccb, 1); - } - break; - default: - printk(KERN_NOTICE - "arcmsr%d: scsi id = %d lun = %d" - " isr get command error done, " - "but got unknown DeviceStatus = 0x%x \n" - , acb->host->host_no - , id - , lun - , ccb->arcmsr_cdb.DeviceStatus); - acb->devstate[id][lun] = ARECA_RAID_GONE; - ccb->pcmd->result = DID_NO_CONNECT << 16; - arcmsr_ccb_complete(ccb, 1); - break; - } - } - }/*drain reply FIFO*/ + writel(ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK, ®->inbound_doorbell); + } + break; + + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + /* + ** push inbound doorbell tell iop, driver data write ok + ** and wait reply on next hwinterrupt for next Qbuffer post + */ + writel(ARCMSR_DRV2IOP_DATA_WRITE_OK, reg->drv2iop_doorbell_reg); + } + break; + } +} + +struct QBUFFER *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb) +{ + static struct QBUFFER *qbuffer; + + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A: { + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + qbuffer = (struct QBUFFER __iomem *) ®->message_rbuffer; + } + break; + + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + qbuffer = (struct QBUFFER __iomem *) reg->ioctl_rbuffer_reg; + } + break; + } + return qbuffer; +} + +static struct QBUFFER *arcmsr_get_iop_wqbuffer(struct AdapterControlBlock *acb) +{ + static struct QBUFFER *pqbuffer; + + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A: { + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + pqbuffer = (struct QBUFFER *) ®->message_wbuffer; + } + break; + + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + pqbuffer = (struct QBUFFER __iomem *)reg->ioctl_wbuffer_reg; + } + break; + } + return pqbuffer; +} + +static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) +{ + struct QBUFFER *prbuffer; + struct QBUFFER *pQbuffer; + uint8_t *iop_data; + int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; + + rqbuf_lastindex = acb->rqbuf_lastindex; + rqbuf_firstindex = acb->rqbuf_firstindex; + prbuffer = arcmsr_get_iop_rqbuffer(acb); + iop_data = (uint8_t *)prbuffer->data; + iop_len = prbuffer->data_len; + my_empty_len = (rqbuf_firstindex - rqbuf_lastindex -1)&(ARCMSR_MAX_QBUFFER -1); + + if (my_empty_len >= iop_len) + { + while (iop_len > 0) { + pQbuffer = (struct QBUFFER *)&acb->rqbuffer[rqbuf_lastindex]; + memcpy(pQbuffer, iop_data,1); + rqbuf_lastindex++; + rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; + iop_data++; + iop_len--; + } + acb->rqbuf_lastindex = rqbuf_lastindex; + arcmsr_iop_message_read(acb); + } + + else { + acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; + } +} + +static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) +{ + acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; + if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) { + uint8_t *pQbuffer; + struct QBUFFER *pwbuffer; + uint8_t *iop_data; + int32_t allxfer_len = 0; + + acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); + pwbuffer = arcmsr_get_iop_wqbuffer(acb); + iop_data = (uint8_t __iomem *)pwbuffer->data; + + while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) && \ + (allxfer_len < 124)) { + pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; + memcpy(iop_data, pQbuffer, 1); + acb->wqbuf_firstindex++; + acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; + iop_data++; + allxfer_len++; + } + pwbuffer->data_len = allxfer_len; + + arcmsr_iop_message_wrote(acb); + } + + if (acb->wqbuf_firstindex == acb->wqbuf_lastindex) { + acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; + } +} + +static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) +{ + uint32_t outbound_doorbell; + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + + outbound_doorbell = readl(®->outbound_doorbell); + writel(outbound_doorbell, ®->outbound_doorbell); + if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { + arcmsr_iop2drv_data_wrote_handle(acb); + } + + if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { + arcmsr_iop2drv_data_read_handle(acb); + } +} + +static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) +{ + uint32_t flag_ccb; + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + + while ((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) { + arcmsr_drain_donequeue(acb, flag_ccb); + } +} + +static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) +{ + uint32_t index; + uint32_t flag_ccb; + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + + index = reg->doneq_index; + + while ((flag_ccb = readl(®->done_qbuffer[index])) != 0) { + writel(0, ®->done_qbuffer[index]); + arcmsr_drain_donequeue(acb, flag_ccb); + index++; + index %= ARCMSR_MAX_HBB_POSTQUEUE; + reg->doneq_index = index; + } +} + +static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) +{ + uint32_t outbound_intstatus; + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + + outbound_intstatus = readl(®->outbound_intstatus) & \ + acb->outbound_int_enable; + if (!(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT)) { + return 1; + } + writel(outbound_intstatus, ®->outbound_intstatus); + if (outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { + arcmsr_hba_doorbell_isr(acb); + } + if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { + arcmsr_hba_postqueue_isr(acb); + } + return 0; +} + +static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) +{ + uint32_t outbound_doorbell; + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + + outbound_doorbell = readl(reg->iop2drv_doorbell_reg) & \ + acb->outbound_int_enable; + if (!outbound_doorbell) + return 1; + + writel(~outbound_doorbell, reg->iop2drv_doorbell_reg); + + if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { + arcmsr_iop2drv_data_wrote_handle(acb); + } + if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) { + arcmsr_iop2drv_data_read_handle(acb); + } + if (outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { + arcmsr_hbb_postqueue_isr(acb); + } + + return 0; +} + +static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + if (arcmsr_handle_hba_isr(acb)) { + return IRQ_NONE; + } + } + break; + + case ACB_ADAPTER_TYPE_B: { + if (arcmsr_handle_hbb_isr(acb)) { + return IRQ_NONE; + } + } + break; } - if (!(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT)) - return IRQ_NONE; return IRQ_HANDLED; } @@ -818,16 +1289,47 @@ static void arcmsr_iop_parking(struct AdapterControlBlock *acb) if (acb) { /* stop adapter background rebuild */ if (acb->acb_flags & ACB_F_MSG_START_BGRB) { + uint32_t intmask_org; acb->acb_flags &= ~ACB_F_MSG_START_BGRB; + intmask_org = arcmsr_disable_outbound_ints(acb); arcmsr_stop_adapter_bgrb(acb); arcmsr_flush_adapter_cache(acb); + arcmsr_enable_outbound_ints(acb, intmask_org); + } + } +} + +void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb) +{ + int32_t wqbuf_firstindex, wqbuf_lastindex; + uint8_t *pQbuffer; + struct QBUFFER *pwbuffer; + uint8_t *iop_data; + int32_t allxfer_len = 0; + + pwbuffer = arcmsr_get_iop_wqbuffer(acb); + iop_data = (uint8_t __iomem *)pwbuffer->data; + if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) { + acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); + wqbuf_firstindex = acb->wqbuf_firstindex; + wqbuf_lastindex = acb->wqbuf_lastindex; + while ((wqbuf_firstindex != wqbuf_lastindex) && (allxfer_len < 124)) { + pQbuffer = &acb->wqbuffer[wqbuf_firstindex]; + memcpy(iop_data, pQbuffer, 1); + wqbuf_firstindex++; + wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; + iop_data++; + allxfer_len++; } + acb->wqbuf_firstindex = wqbuf_firstindex; + pwbuffer->data_len = allxfer_len; + arcmsr_iop_message_wrote(acb); } } -static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_cmnd *cmd) +static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ + struct scsi_cmnd *cmd) { - struct MessageUnit __iomem *reg = acb->pmu; struct CMD_MESSAGE_FIELD *pcmdmessagefld; int retvalue = 0, transfer_len = 0; char *buffer; @@ -836,7 +1338,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_ (uint32_t ) cmd->cmnd[6] << 16 | (uint32_t ) cmd->cmnd[7] << 8 | (uint32_t ) cmd->cmnd[8]; - /* 4 bytes: Areca io control code */ + /* 4 bytes: Areca io control code */ sg = scsi_sglist(cmd); buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; @@ -852,194 +1354,199 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_ } pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; switch(controlcode) { + case ARCMSR_MESSAGE_READ_RQBUFFER: { - unsigned long *ver_addr; - dma_addr_t buf_handle; - uint8_t *pQbuffer, *ptmpQbuffer; - int32_t allxfer_len = 0; + unsigned long *ver_addr; + dma_addr_t buf_handle; + uint8_t *pQbuffer, *ptmpQbuffer; + int32_t allxfer_len = 0; + + ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); + if (!ver_addr) { + retvalue = ARCMSR_MESSAGE_FAIL; + goto message_out; + } + ptmpQbuffer = (uint8_t *) ver_addr; + while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) + && (allxfer_len < 1031)) { + pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; + memcpy(ptmpQbuffer, pQbuffer, 1); + acb->rqbuf_firstindex++; + acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; + ptmpQbuffer++; + allxfer_len++; + } + if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); - if (!ver_addr) { - retvalue = ARCMSR_MESSAGE_FAIL; - goto message_out; - } - ptmpQbuffer = (uint8_t *) ver_addr; - while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) - && (allxfer_len < 1031)) { - pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; - memcpy(ptmpQbuffer, pQbuffer, 1); - acb->rqbuf_firstindex++; - acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; - ptmpQbuffer++; - allxfer_len++; - } - if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - struct QBUFFER __iomem * prbuffer = (struct QBUFFER __iomem *) - ®->message_rbuffer; - uint8_t __iomem * iop_data = (uint8_t __iomem *)prbuffer->data; - int32_t iop_len; - - acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - iop_len = readl(&prbuffer->data_len); - while (iop_len > 0) { - acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); - acb->rqbuf_lastindex++; - acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; - iop_data++; - iop_len--; - } - writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, - ®->inbound_doorbell); + struct QBUFFER *prbuffer; + uint8_t *iop_data; + int32_t iop_len; + + acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; + prbuffer = arcmsr_get_iop_rqbuffer(acb); + iop_data = (uint8_t *)prbuffer->data; + iop_len = readl(&prbuffer->data_len); + while (iop_len > 0) { + acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); + acb->rqbuf_lastindex++; + acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; + iop_data++; + iop_len--; } - memcpy(pcmdmessagefld->messagedatabuffer, - (uint8_t *)ver_addr, allxfer_len); - pcmdmessagefld->cmdmessage.Length = allxfer_len; - pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; - pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle); + arcmsr_iop_message_read(acb); + } + memcpy(pcmdmessagefld->messagedatabuffer, (uint8_t *)ver_addr, allxfer_len); + pcmdmessagefld->cmdmessage.Length = allxfer_len; + pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; + pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle); } break; - case ARCMSR_MESSAGE_WRITE_WQBUFFER: { - unsigned long *ver_addr; - dma_addr_t buf_handle; - int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; - uint8_t *pQbuffer, *ptmpuserbuffer; - ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); - if (!ver_addr) { - retvalue = ARCMSR_MESSAGE_FAIL; - goto message_out; - } - ptmpuserbuffer = (uint8_t *)ver_addr; - user_len = pcmdmessagefld->cmdmessage.Length; - memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len); - wqbuf_lastindex = acb->wqbuf_lastindex; - wqbuf_firstindex = acb->wqbuf_firstindex; - if (wqbuf_lastindex != wqbuf_firstindex) { + case ARCMSR_MESSAGE_WRITE_WQBUFFER: { + unsigned long *ver_addr; + dma_addr_t buf_handle; + int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; + uint8_t *pQbuffer, *ptmpuserbuffer; + + ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); + if (!ver_addr) { + retvalue = ARCMSR_MESSAGE_FAIL; + goto message_out; + } + ptmpuserbuffer = (uint8_t *)ver_addr; + user_len = pcmdmessagefld->cmdmessage.Length; + memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len); + wqbuf_lastindex = acb->wqbuf_lastindex; + wqbuf_firstindex = acb->wqbuf_firstindex; + if (wqbuf_lastindex != wqbuf_firstindex) { + struct SENSE_DATA *sensebuffer = + (struct SENSE_DATA *)cmd->sense_buffer; + arcmsr_post_ioctldata2iop(acb); + /* has error report sensedata */ + sensebuffer->ErrorCode = 0x70; + sensebuffer->SenseKey = ILLEGAL_REQUEST; + sensebuffer->AdditionalSenseLength = 0x0A; + sensebuffer->AdditionalSenseCode = 0x20; + sensebuffer->Valid = 1; + retvalue = ARCMSR_MESSAGE_FAIL; + } else { + my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) + &(ARCMSR_MAX_QBUFFER - 1); + if (my_empty_len >= user_len) { + while (user_len > 0) { + pQbuffer = + &acb->wqbuffer[acb->wqbuf_lastindex]; + memcpy(pQbuffer, ptmpuserbuffer, 1); + acb->wqbuf_lastindex++; + acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; + ptmpuserbuffer++; + user_len--; + } + if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { + acb->acb_flags &= + ~ACB_F_MESSAGE_WQBUFFER_CLEARED; + arcmsr_post_ioctldata2iop(acb); + } + } else { + /* has error report sensedata */ struct SENSE_DATA *sensebuffer = (struct SENSE_DATA *)cmd->sense_buffer; - arcmsr_post_Qbuffer(acb); - /* has error report sensedata */ sensebuffer->ErrorCode = 0x70; sensebuffer->SenseKey = ILLEGAL_REQUEST; sensebuffer->AdditionalSenseLength = 0x0A; sensebuffer->AdditionalSenseCode = 0x20; sensebuffer->Valid = 1; retvalue = ARCMSR_MESSAGE_FAIL; - } else { - my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) - &(ARCMSR_MAX_QBUFFER - 1); - if (my_empty_len >= user_len) { - while (user_len > 0) { - pQbuffer = - &acb->wqbuffer[acb->wqbuf_lastindex]; - memcpy(pQbuffer, ptmpuserbuffer, 1); - acb->wqbuf_lastindex++; - acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; - ptmpuserbuffer++; - user_len--; - } - if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { - acb->acb_flags &= - ~ACB_F_MESSAGE_WQBUFFER_CLEARED; - arcmsr_post_Qbuffer(acb); - } - } else { - /* has error report sensedata */ - struct SENSE_DATA *sensebuffer = - (struct SENSE_DATA *)cmd->sense_buffer; - sensebuffer->ErrorCode = 0x70; - sensebuffer->SenseKey = ILLEGAL_REQUEST; - sensebuffer->AdditionalSenseLength = 0x0A; - sensebuffer->AdditionalSenseCode = 0x20; - sensebuffer->Valid = 1; - retvalue = ARCMSR_MESSAGE_FAIL; - } + } } pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle); } break; + case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { - uint8_t *pQbuffer = acb->rqbuffer; + uint8_t *pQbuffer = acb->rqbuffer; - if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, - ®->inbound_doorbell); - } - acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; - acb->rqbuf_firstindex = 0; - acb->rqbuf_lastindex = 0; - memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); - pcmdmessagefld->cmdmessage.ReturnCode = - ARCMSR_MESSAGE_RETURNCODE_OK; + if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { + acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; + arcmsr_iop_message_read(acb); + } + acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; + acb->rqbuf_firstindex = 0; + acb->rqbuf_lastindex = 0; + memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); + pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; } break; + case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { - uint8_t *pQbuffer = acb->wqbuffer; + uint8_t *pQbuffer = acb->wqbuffer; - if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK - , ®->inbound_doorbell); - } - acb->acb_flags |= - (ACB_F_MESSAGE_WQBUFFER_CLEARED | - ACB_F_MESSAGE_WQBUFFER_READED); - acb->wqbuf_firstindex = 0; - acb->wqbuf_lastindex = 0; - memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); - pcmdmessagefld->cmdmessage.ReturnCode = - ARCMSR_MESSAGE_RETURNCODE_OK; + if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { + acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; + arcmsr_iop_message_read(acb); + } + acb->acb_flags |= + (ACB_F_MESSAGE_WQBUFFER_CLEARED | + ACB_F_MESSAGE_WQBUFFER_READED); + acb->wqbuf_firstindex = 0; + acb->wqbuf_lastindex = 0; + memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_OK; } break; + case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { - uint8_t *pQbuffer; + uint8_t *pQbuffer; - if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK - , ®->inbound_doorbell); - } - acb->acb_flags |= - (ACB_F_MESSAGE_WQBUFFER_CLEARED - | ACB_F_MESSAGE_RQBUFFER_CLEARED - | ACB_F_MESSAGE_WQBUFFER_READED); - acb->rqbuf_firstindex = 0; - acb->rqbuf_lastindex = 0; - acb->wqbuf_firstindex = 0; - acb->wqbuf_lastindex = 0; - pQbuffer = acb->rqbuffer; - memset(pQbuffer, 0, sizeof (struct QBUFFER)); - pQbuffer = acb->wqbuffer; - memset(pQbuffer, 0, sizeof (struct QBUFFER)); - pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; + if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { + acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; + arcmsr_iop_message_read(acb); + } + acb->acb_flags |= + (ACB_F_MESSAGE_WQBUFFER_CLEARED + | ACB_F_MESSAGE_RQBUFFER_CLEARED + | ACB_F_MESSAGE_WQBUFFER_READED); + acb->rqbuf_firstindex = 0; + acb->rqbuf_lastindex = 0; + acb->wqbuf_firstindex = 0; + acb->wqbuf_lastindex = 0; + pQbuffer = acb->rqbuffer; + memset(pQbuffer, 0, sizeof(struct QBUFFER)); + pQbuffer = acb->wqbuffer; + memset(pQbuffer, 0, sizeof(struct QBUFFER)); + pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; } break; + case ARCMSR_MESSAGE_RETURN_CODE_3F: { - pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; + pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; } break; + case ARCMSR_MESSAGE_SAY_HELLO: { - int8_t * hello_string = "Hello! I am ARCMSR"; + int8_t *hello_string = "Hello! I am ARCMSR"; - memcpy(pcmdmessagefld->messagedatabuffer, hello_string - , (int16_t)strlen(hello_string)); - pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; + memcpy(pcmdmessagefld->messagedatabuffer, hello_string + , (int16_t)strlen(hello_string)); + pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; } break; + case ARCMSR_MESSAGE_SAY_GOODBYE: arcmsr_iop_parking(acb); break; + case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: arcmsr_flush_adapter_cache(acb); break; + default: retvalue = ARCMSR_MESSAGE_FAIL; } - message_out: + message_out: sg = scsi_sglist(cmd); kunmap_atomic(buffer - sg->offset, KM_IRQ0); - return retvalue; } @@ -1109,8 +1616,7 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) { struct Scsi_Host *host = cmd->device->host; - struct AdapterControlBlock *acb = - (struct AdapterControlBlock *) host->hostdata; + struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; struct CommandControlBlock *ccb; int target = cmd->device->id; int lun = cmd->device->lun; @@ -1153,26 +1659,27 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd, ccb = arcmsr_get_freeccb(acb); if (!ccb) return SCSI_MLQUEUE_HOST_BUSY; + arcmsr_build_ccb(acb, ccb, cmd); arcmsr_post_ccb(acb, ccb); return 0; } -static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) +static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) { - struct MessageUnit __iomem *reg = acb->pmu; + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; char *acb_firm_model = acb->firm_model; char *acb_firm_version = acb->firm_version; - char __iomem *iop_firm_model = (char __iomem *) ®->message_rwbuffer[15]; - char __iomem *iop_firm_version = (char __iomem *) ®->message_rwbuffer[17]; + char *iop_firm_model = (char *) (®->message_rwbuffer[15]); + char *iop_firm_version = (char *) (®->message_rwbuffer[17]); int count; writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); - if (arcmsr_wait_msgint_ready(acb)) - printk(KERN_NOTICE - "arcmsr%d: wait " - "'get adapter firmware miscellaneous data' timeout \n" - , acb->host->host_no); + if (arcmsr_hba_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ + miscellaneous data' timeout \n", acb->host->host_no); + } + count = 8; while (count) { *acb_firm_model = readb(iop_firm_model); @@ -1180,6 +1687,7 @@ static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) iop_firm_model++; count--; } + count = 16; while (count) { *acb_firm_version = readb(iop_firm_version); @@ -1187,28 +1695,93 @@ static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) iop_firm_version++; count--; } - printk(KERN_INFO - "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n" + + printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n" , acb->host->host_no , acb->firm_version); + acb->firm_request_len = readl(®->message_rwbuffer[1]); acb->firm_numbers_queue = readl(®->message_rwbuffer[2]); acb->firm_sdram_size = readl(®->message_rwbuffer[3]); acb->firm_hd_channels = readl(®->message_rwbuffer[4]); } -static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, +static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) +{ + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + uint32_t *lrwbuffer = reg->msgcode_rwbuffer_reg; + char *acb_firm_model = acb->firm_model; + char *acb_firm_version = acb->firm_version; + char *iop_firm_model = (char *) (&lrwbuffer[15]); + /*firm_model,15,60-67*/ + char *iop_firm_version = (char *) (&lrwbuffer[17]); + /*firm_version,17,68-83*/ + int count; + + writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell_reg); + if (arcmsr_hbb_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ + miscellaneous data' timeout \n", acb->host->host_no); + } + + count = 8; + while (count) + { + *acb_firm_model = readb(iop_firm_model); + acb_firm_model++; + iop_firm_model++; + count--; + } + + count = 16; + while (count) + { + *acb_firm_version = readb(iop_firm_version); + acb_firm_version++; + iop_firm_version++; + count--; + } + + printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", + acb->host->host_no, + acb->firm_version); + + lrwbuffer++; + acb->firm_request_len = readl(lrwbuffer++); + /*firm_request_len,1,04-07*/ + acb->firm_numbers_queue = readl(lrwbuffer++); + /*firm_numbers_queue,2,08-11*/ + acb->firm_sdram_size = readl(lrwbuffer++); + /*firm_sdram_size,3,12-15*/ + acb->firm_hd_channels = readl(lrwbuffer); + /*firm_ide_channels,4,16-19*/ +} + +static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + arcmsr_get_hba_config(acb); + } + break; + + case ACB_ADAPTER_TYPE_B: { + arcmsr_get_hbb_config(acb); + } + break; + } +} + +static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_ccb) { - struct MessageUnit __iomem *reg = acb->pmu; + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; struct CommandControlBlock *ccb; uint32_t flag_ccb, outbound_intstatus, poll_ccb_done = 0, poll_count = 0; - int id, lun; - polling_ccb_retry: + polling_hba_ccb_retry: poll_count++; - outbound_intstatus = readl(®->outbound_intstatus) - & acb->outbound_int_enable; + outbound_intstatus = readl(®->outbound_intstatus) & acb->outbound_int_enable; writel(outbound_intstatus, ®->outbound_intstatus);/*clear interrupt*/ while (1) { if ((flag_ccb = readl(®->outbound_queueport)) == 0xFFFFFFFF) { @@ -1218,17 +1791,14 @@ static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, msleep(25); if (poll_count > 100) break; - goto polling_ccb_retry; + goto polling_hba_ccb_retry; } } - ccb = (struct CommandControlBlock *) - (acb->vir2phy_offset + (flag_ccb << 5)); - if ((ccb->acb != acb) || - (ccb->startdone != ARCMSR_CCB_START)) { - if ((ccb->startdone == ARCMSR_CCB_ABORTED) || - (ccb == poll_ccb)) { - printk(KERN_NOTICE - "arcmsr%d: scsi id = %d lun = %d ccb = '0x%p'" + ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + (flag_ccb << 5)); + poll_ccb_done = (ccb == poll_ccb) ? 1:0; + if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { + if ((ccb->startdone == ARCMSR_CCB_ABORTED) || (ccb == poll_ccb)) { + printk(KERN_NOTICE "arcmsr%d: scsi id = %d lun = %d ccb = '0x%p'" " poll command abort successfully \n" , acb->host->host_no , ccb->pcmd->device->id @@ -1239,176 +1809,280 @@ static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, poll_ccb_done = 1; continue; } - printk(KERN_NOTICE - "arcmsr%d: polling get an illegal ccb" - " command done ccb ='0x%p'" + printk(KERN_NOTICE "arcmsr%d: polling get an illegal ccb" + " command done ccb = '0x%p'" "ccboutstandingcount = %d \n" , acb->host->host_no , ccb , atomic_read(&acb->ccboutstandingcount)); continue; } - id = ccb->pcmd->device->id; - lun = ccb->pcmd->device->lun; - if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { - if (acb->devstate[id][lun] == ARECA_RAID_GONE) - acb->devstate[id][lun] = ARECA_RAID_GOOD; - ccb->pcmd->result = DID_OK << 16; - arcmsr_ccb_complete(ccb, 1); - } else { - switch(ccb->arcmsr_cdb.DeviceStatus) { - case ARCMSR_DEV_SELECT_TIMEOUT: { - acb->devstate[id][lun] = ARECA_RAID_GONE; - ccb->pcmd->result = DID_NO_CONNECT << 16; - arcmsr_ccb_complete(ccb, 1); - } - break; - case ARCMSR_DEV_ABORTED: - case ARCMSR_DEV_INIT_FAIL: { - acb->devstate[id][lun] = ARECA_RAID_GONE; - ccb->pcmd->result = DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); + arcmsr_report_ccb_state(acb, ccb, flag_ccb); + } +} + +static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \ + struct CommandControlBlock *poll_ccb) +{ + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct CommandControlBlock *ccb; + uint32_t flag_ccb, poll_ccb_done = 0, poll_count = 0; + int index; + + polling_hbb_ccb_retry: + poll_count++; + /* clear doorbell interrupt */ + writel(ARCMSR_DOORBELL_INT_CLEAR_PATTERN, reg->iop2drv_doorbell_reg); + while (1) { + index = reg->doneq_index; + if ((flag_ccb = readl(®->done_qbuffer[index])) == 0) { + if (poll_ccb_done) + break; + else { + msleep(25); + if (poll_count > 100) + break; + goto polling_hbb_ccb_retry; } - break; - case ARCMSR_DEV_CHECK_CONDITION: { - acb->devstate[id][lun] = ARECA_RAID_GOOD; - arcmsr_report_sense_info(ccb); + } + writel(0, ®->done_qbuffer[index]); + index++; + /*if last index number set it to 0 */ + index %= ARCMSR_MAX_HBB_POSTQUEUE; + reg->doneq_index = index; + /* check ifcommand done with no error*/ + ccb = (struct CommandControlBlock *)\ + (acb->vir2phy_offset + (flag_ccb << 5));/*frame must be 32 bytes aligned*/ + poll_ccb_done = (ccb == poll_ccb) ? 1:0; + if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { + if (ccb->startdone == ARCMSR_CCB_ABORTED) { + printk(KERN_NOTICE "arcmsr%d: \ + scsi id = %d lun = %d ccb = '0x%p' poll command abort successfully \n" + ,acb->host->host_no + ,ccb->pcmd->device->id + ,ccb->pcmd->device->lun + ,ccb); + ccb->pcmd->result = DID_ABORT << 16; arcmsr_ccb_complete(ccb, 1); + continue; } - break; - default: - printk(KERN_NOTICE - "arcmsr%d: scsi id = %d lun = %d" - " polling and getting command error done" - "but got unknown DeviceStatus = 0x%x \n" + printk(KERN_NOTICE "arcmsr%d: polling get an illegal ccb" + " command done ccb = '0x%p'" + "ccboutstandingcount = %d \n" , acb->host->host_no - , id - , lun - , ccb->arcmsr_cdb.DeviceStatus); - acb->devstate[id][lun] = ARECA_RAID_GONE; - ccb->pcmd->result = DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); - break; + , ccb + , atomic_read(&acb->ccboutstandingcount)); + continue; } + arcmsr_report_ccb_state(acb, ccb, flag_ccb); + } /*drain reply FIFO*/ +} + +static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, \ + struct CommandControlBlock *poll_ccb) +{ + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A: { + arcmsr_polling_hba_ccbdone(acb,poll_ccb); + } + break; + + case ACB_ADAPTER_TYPE_B: { + arcmsr_polling_hbb_ccbdone(acb,poll_ccb); } } } -static void arcmsr_done4_abort_postqueue(struct AdapterControlBlock *acb) + +static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) { - int i = 0, found = 0; - int id, lun; - uint32_t flag_ccb, outbound_intstatus; - struct MessageUnit __iomem *reg = acb->pmu; - struct CommandControlBlock *ccb; - /*clear and abort all outbound posted Q*/ - - while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) && -(i++ < 256)){ - ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + -(flag_ccb << 5)); - if (ccb){ - if ((ccb->acb != acb)||(ccb->startdone != \ -ARCMSR_CCB_START)){ - printk(KERN_NOTICE "arcmsr%d: polling get \ -an illegal ccb" "command done ccb = '0x%p'""ccboutstandingcount = %d \n", - acb->host->host_no, ccb, - atomic_read(&acb->ccboutstandingcount)); - continue; + uint32_t cdb_phyaddr, ccb_phyaddr_hi32; + dma_addr_t dma_coherent_handle; + /* + ******************************************************************** + ** here we need to tell iop 331 our freeccb.HighPart + ** if freeccb.HighPart is not zero + ******************************************************************** + */ + dma_coherent_handle = acb->dma_coherent_handle; + cdb_phyaddr = (uint32_t)(dma_coherent_handle); + ccb_phyaddr_hi32 = (uint32_t)((cdb_phyaddr >> 16) >> 16); + /* + *********************************************************************** + ** if adapter type B, set window of "post command Q" + *********************************************************************** + */ + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A: { + if (ccb_phyaddr_hi32 != 0) { + struct MessageUnit_A __iomem *reg = \ + (struct MessageUnit_A *)acb->pmu; + uint32_t intmask_org; + intmask_org = arcmsr_disable_outbound_ints(acb); + writel(ARCMSR_SIGNATURE_SET_CONFIG, \ + ®->message_rwbuffer[0]); + writel(ccb_phyaddr_hi32, ®->message_rwbuffer[1]); + writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, \ + ®->inbound_msgaddr0); + if (arcmsr_hba_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: ""set ccb high \ + part physical address timeout\n", + acb->host->host_no); + return 1; } + arcmsr_enable_outbound_ints(acb, intmask_org); + } + } + break; - id = ccb->pcmd->device->id; - lun = ccb->pcmd->device->lun; - if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)){ - if (acb->devstate[id][lun] == ARECA_RAID_GONE) - acb->devstate[id][lun] = ARECA_RAID_GOOD; - ccb->pcmd->result = DID_OK << 16; - arcmsr_ccb_complete(ccb, 1); - } - else { - switch(ccb->arcmsr_cdb.DeviceStatus) { - case ARCMSR_DEV_SELECT_TIMEOUT: { - acb->devstate[id][lun] = ARECA_RAID_GONE; - ccb->pcmd->result = DID_NO_CONNECT << 16; - arcmsr_ccb_complete(ccb, 1); - } - break; + case ACB_ADAPTER_TYPE_B: { + unsigned long post_queue_phyaddr; + uint32_t *rwbuffer; - case ARCMSR_DEV_ABORTED: + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + uint32_t intmask_org; + intmask_org = arcmsr_disable_outbound_ints(acb); + reg->postq_index = 0; + reg->doneq_index = 0; + writel(ARCMSR_MESSAGE_SET_POST_WINDOW, reg->drv2iop_doorbell_reg); + if (arcmsr_hbb_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d:can not set diver mode\n", \ + acb->host->host_no); + return 1; + } + post_queue_phyaddr = cdb_phyaddr + ARCMSR_MAX_FREECCB_NUM * \ + sizeof(struct CommandControlBlock) + offsetof(struct MessageUnit_B, post_qbuffer) ; + rwbuffer = reg->msgcode_rwbuffer_reg; + /* driver "set config" signature */ + writel(ARCMSR_SIGNATURE_SET_CONFIG, rwbuffer++); + /* normal should be zero */ + writel(ccb_phyaddr_hi32, rwbuffer++); + /* postQ size (256 + 8)*4 */ + writel(post_queue_phyaddr, rwbuffer++); + /* doneQ size (256 + 8)*4 */ + writel(post_queue_phyaddr + 1056, rwbuffer++); + /* ccb maxQ size must be --> [(256 + 8)*4]*/ + writel(1056, rwbuffer); + + writel(ARCMSR_MESSAGE_SET_CONFIG, reg->drv2iop_doorbell_reg); + if (arcmsr_hbb_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: 'set command Q window' \ + timeout \n",acb->host->host_no); + return 1; + } - case ARCMSR_DEV_INIT_FAIL: { - acb->devstate[id][lun] = - ARECA_RAID_GONE; - ccb->pcmd->result = - DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); - } - break; + writel(ARCMSR_MESSAGE_START_DRIVER_MODE, reg->drv2iop_doorbell_reg); + if (arcmsr_hbb_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: 'can not set diver mode \n"\ + ,acb->host->host_no); + return 1; + } + arcmsr_enable_outbound_ints(acb, intmask_org); + } + break; + } + return 0; +} - case ARCMSR_DEV_CHECK_CONDITION: { - acb->devstate[id][lun] = - ARECA_RAID_GOOD; - arcmsr_report_sense_info(ccb); - arcmsr_ccb_complete(ccb, 1); - } - break; +static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) +{ + uint32_t firmware_state = 0; - default: - printk(KERN_NOTICE - "arcmsr%d: scsi id = %d \ - lun = %d""polling and \ - getting command error \ - done""but got unknown \ - DeviceStatus = 0x%x \n", - acb->host->host_no, id, - lun, ccb->arcmsr_cdb.DeviceStatus); - acb->devstate[id][lun] = - ARECA_RAID_GONE; - ccb->pcmd->result = - DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); - break; - } - } - found = 1; - } + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A: { + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + do { + firmware_state = readl(®->outbound_msgaddr1); + } while ((firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0); + } + break; + + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + do { + firmware_state = readl(reg->iop2drv_doorbell_reg); + } while ((firmware_state & ARCMSR_MESSAGE_FIRMWARE_OK) == 0); + } + break; } - if (found){ - outbound_intstatus = readl(®->outbound_intstatus) & \ - acb->outbound_int_enable; - writel(outbound_intstatus, ®->outbound_intstatus); - /*clear interrupt*/ +} + +static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) +{ + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + acb->acb_flags |= ACB_F_MSG_START_BGRB; + writel(ARCMSR_INBOUND_MESG0_START_BGRB, ®->inbound_msgaddr0); + if (arcmsr_hba_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: wait 'start adapter background \ + rebulid' timeout \n", acb->host->host_no); } - return; } +static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) +{ + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + acb->acb_flags |= ACB_F_MSG_START_BGRB; + writel(ARCMSR_MESSAGE_START_BGRB, reg->drv2iop_doorbell_reg); + if (arcmsr_hbb_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: wait 'start adapter background \ + rebulid' timeout \n",acb->host->host_no); + } +} -static void arcmsr_iop_init(struct AdapterControlBlock *acb) +static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) { - struct MessageUnit __iomem *reg = acb->pmu; - uint32_t intmask_org, mask, outbound_doorbell, firmware_state = 0; + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: + arcmsr_start_hba_bgrb(acb); + break; + case ACB_ADAPTER_TYPE_B: + arcmsr_start_hbb_bgrb(acb); + break; + } +} - do { - firmware_state = readl(®->outbound_msgaddr1); - } while (!(firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK)); - intmask_org = readl(®->outbound_intmask) - | ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; - arcmsr_get_firmware_spec(acb); +static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + struct MessageUnit_A *reg = (struct MessageUnit_A *)acb->pmu; + uint32_t outbound_doorbell; + /* empty doorbell Qbuffer if door bell ringed */ + outbound_doorbell = readl(®->outbound_doorbell); + /*clear doorbell interrupt */ + writel(outbound_doorbell, ®->outbound_doorbell); + writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell); + } + break; - acb->acb_flags |= ACB_F_MSG_START_BGRB; - writel(ARCMSR_INBOUND_MESG0_START_BGRB, ®->inbound_msgaddr0); - if (arcmsr_wait_msgint_ready(acb)) { - printk(KERN_NOTICE "arcmsr%d: " - "wait 'start adapter background rebulid' timeout\n", - acb->host->host_no); + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + /*clear interrupt and message state*/ + writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN, reg->iop2drv_doorbell_reg); + writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg); + /* let IOP know data has been read */ + } + break; } +} - outbound_doorbell = readl(®->outbound_doorbell); - writel(outbound_doorbell, ®->outbound_doorbell); - writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell); - mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE - | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); - writel(intmask_org & mask, ®->outbound_intmask); - acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; +static void arcmsr_iop_init(struct AdapterControlBlock *acb) +{ + uint32_t intmask_org; + + arcmsr_wait_firmware_ready(acb); + arcmsr_iop_confirm(acb); + /* disable all outbound interrupt */ + intmask_org = arcmsr_disable_outbound_ints(acb); + arcmsr_get_firmware_spec(acb); + /*start background rebuild*/ + arcmsr_start_adapter_bgrb(acb); + /* empty doorbell Qbuffer if door bell ringed */ + arcmsr_clear_doorbell_queue_buffer(acb); + /* enable outbound Post Queue,outbound doorbell Interrupt */ + arcmsr_enable_outbound_ints(acb, intmask_org); acb->acb_flags |= ACB_F_IOP_INITED; } @@ -1422,21 +2096,21 @@ static void arcmsr_iop_reset(struct AdapterControlBlock *acb) /* talk to iop 331 outstanding command aborted */ arcmsr_abort_allcmd(acb); /* wait for 3 sec for all command aborted*/ - msleep_interruptible(3000); + ssleep(3); /* disable all outbound interrupt */ intmask_org = arcmsr_disable_outbound_ints(acb); /* clear all outbound posted Q */ - arcmsr_done4_abort_postqueue(acb); + arcmsr_done4abort_postqueue(acb); for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { ccb = acb->pccb_pool[i]; if (ccb->startdone == ARCMSR_CCB_START) { ccb->startdone = ARCMSR_CCB_ABORTED; + arcmsr_ccb_complete(ccb, 1); } } /* enable all outbound interrupt */ arcmsr_enable_outbound_ints(acb, intmask_org); } - } static int arcmsr_bus_reset(struct scsi_cmnd *cmd) @@ -1450,7 +2124,7 @@ static int arcmsr_bus_reset(struct scsi_cmnd *cmd) for (i = 0; i < 400; i++) { if (!atomic_read(&acb->ccboutstandingcount)) break; - arcmsr_interrupt(acb); + arcmsr_interrupt(acb);/* FIXME: need spinlock */ msleep(25); } arcmsr_iop_reset(acb); @@ -1468,7 +2142,7 @@ static void arcmsr_abort_one_cmd(struct AdapterControlBlock *acb, /* ** Wait for 3 sec for all command done. */ - msleep_interruptible(3000); + ssleep(3); intmask = arcmsr_disable_outbound_ints(acb); arcmsr_polling_ccbdone(acb, ccb); @@ -1515,6 +2189,8 @@ static const char *arcmsr_info(struct Scsi_Host *host) switch (acb->pdev->device) { case PCI_DEVICE_ID_ARECA_1110: + case PCI_DEVICE_ID_ARECA_1200: + case PCI_DEVICE_ID_ARECA_1202: case PCI_DEVICE_ID_ARECA_1210: raid6 = 0; /*FALLTHRU*/ @@ -1522,6 +2198,7 @@ static const char *arcmsr_info(struct Scsi_Host *host) case PCI_DEVICE_ID_ARECA_1130: case PCI_DEVICE_ID_ARECA_1160: case PCI_DEVICE_ID_ARECA_1170: + case PCI_DEVICE_ID_ARECA_1201: case PCI_DEVICE_ID_ARECA_1220: case PCI_DEVICE_ID_ARECA_1230: case PCI_DEVICE_ID_ARECA_1260: @@ -1544,287 +2221,82 @@ static const char *arcmsr_info(struct Scsi_Host *host) ARCMSR_DRIVER_VERSION); return buf; } - +#ifdef CONFIG_SCSI_ARCMSR_AER static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev) { - struct Scsi_Host *host; - struct AdapterControlBlock *acb; - uint8_t bus, dev_fun; - int error; - - error = pci_enable_device(pdev); - if (error) - return PCI_ERS_RESULT_DISCONNECT; - pci_set_master(pdev); - - host = scsi_host_alloc(&arcmsr_scsi_host_template, sizeof \ -(struct AdapterControlBlock)); - if (!host) - return PCI_ERS_RESULT_DISCONNECT; - acb = (struct AdapterControlBlock *)host->hostdata; - memset(acb, 0, sizeof (struct AdapterControlBlock)); - - error = pci_set_dma_mask(pdev, DMA_64BIT_MASK); - if (error) { - error = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (error) { - printk(KERN_WARNING - "scsi%d: No suitable DMA mask available\n", - host->host_no); - return PCI_ERS_RESULT_DISCONNECT; - } - } - bus = pdev->bus->number; - dev_fun = pdev->devfn; - acb = (struct AdapterControlBlock *) host->hostdata; - memset(acb, 0, sizeof(struct AdapterControlBlock)); - acb->pdev = pdev; - acb->host = host; - host->max_sectors = ARCMSR_MAX_XFER_SECTORS; - host->max_lun = ARCMSR_MAX_TARGETLUN; - host->max_id = ARCMSR_MAX_TARGETID;/*16:8*/ - host->max_cmd_len = 16; /*this is issue of 64bit LBA, over 2T byte*/ - host->sg_tablesize = ARCMSR_MAX_SG_ENTRIES; - host->can_queue = ARCMSR_MAX_FREECCB_NUM; /* max simultaneous cmds */ - host->cmd_per_lun = ARCMSR_MAX_CMD_PERLUN; - host->this_id = ARCMSR_SCSI_INITIATOR_ID; - host->unique_id = (bus << 8) | dev_fun; - host->irq = pdev->irq; - error = pci_request_regions(pdev, "arcmsr"); - if (error) - return PCI_ERS_RESULT_DISCONNECT; + struct Scsi_Host *host = pci_get_drvdata(pdev); + struct AdapterControlBlock *acb = + (struct AdapterControlBlock *) host->hostdata; + uint32_t intmask_org; + int i, j; - acb->pmu = ioremap(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - if (!acb->pmu) { - printk(KERN_NOTICE "arcmsr%d: memory" - " mapping region fail \n", acb->host->host_no); + if (pci_enable_device(pdev)) { return PCI_ERS_RESULT_DISCONNECT; } + pci_set_master(pdev); + intmask_org = arcmsr_disable_outbound_ints(acb); acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | ACB_F_MESSAGE_RQBUFFER_CLEARED | ACB_F_MESSAGE_WQBUFFER_READED); acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; - INIT_LIST_HEAD(&acb->ccb_free_list); - - error = arcmsr_alloc_ccb_pool(acb); - if (error) - return PCI_ERS_RESULT_DISCONNECT; - - error = request_irq(pdev->irq, arcmsr_do_interrupt, - IRQF_DISABLED | IRQF_SHARED, "arcmsr", acb); - if (error) - return PCI_ERS_RESULT_DISCONNECT; - - arcmsr_iop_init(acb); - if (strncmp(acb->firm_version, "V1.42", 5) >= 0) - host->max_sectors = ARCMSR_MAX_XFER_SECTORS_B; - - pci_set_drvdata(pdev, host); - - error = scsi_add_host(host, &pdev->dev); - if (error) - return PCI_ERS_RESULT_DISCONNECT; + for (i = 0; i < ARCMSR_MAX_TARGETID; i++) + for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) + acb->devstate[i][j] = ARECA_RAID_GONE; - error = arcmsr_alloc_sysfs_attr(acb); - if (error) - return PCI_ERS_RESULT_DISCONNECT; + arcmsr_wait_firmware_ready(acb); + arcmsr_iop_confirm(acb); + /* disable all outbound interrupt */ + arcmsr_get_firmware_spec(acb); + /*start background rebuild*/ + arcmsr_start_adapter_bgrb(acb); + /* empty doorbell Qbuffer if door bell ringed */ + arcmsr_clear_doorbell_queue_buffer(acb); + /* enable outbound Post Queue,outbound doorbell Interrupt */ + arcmsr_enable_outbound_ints(acb, intmask_org); + acb->acb_flags |= ACB_F_IOP_INITED; - scsi_scan_host(host); + pci_enable_pcie_error_reporting(pdev); return PCI_ERS_RESULT_RECOVERED; } static void arcmsr_pci_ers_need_reset_forepart(struct pci_dev *pdev) { struct Scsi_Host *host = pci_get_drvdata(pdev); - struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; - struct MessageUnit __iomem *reg = acb->pmu; + struct AdapterControlBlock *acb = (struct AdapterControlBlock *)host->hostdata; struct CommandControlBlock *ccb; - /*clear and abort all outbound posted Q*/ - int i = 0, found = 0; - int id, lun; - uint32_t flag_ccb, outbound_intstatus; - - while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) && - (i++ < 256)){ - ccb = (struct CommandControlBlock *)(acb->vir2phy_offset - + (flag_ccb << 5)); - if (ccb){ - if ((ccb->acb != acb)||(ccb->startdone != - ARCMSR_CCB_START)){ - printk(KERN_NOTICE "arcmsr%d: polling \ - get an illegal ccb"" command done ccb = '0x%p'" - "ccboutstandingcount = %d \n", - acb->host->host_no, ccb, - atomic_read(&acb->ccboutstandingcount)); - continue; - } - - id = ccb->pcmd->device->id; - lun = ccb->pcmd->device->lun; - if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { - if (acb->devstate[id][lun] == - ARECA_RAID_GONE) - acb->devstate[id][lun] = - ARECA_RAID_GOOD; - ccb->pcmd->result = DID_OK << 16; - arcmsr_ccb_complete(ccb, 1); - } - else { - switch(ccb->arcmsr_cdb.DeviceStatus) { - case ARCMSR_DEV_SELECT_TIMEOUT: { - acb->devstate[id][lun] = - ARECA_RAID_GONE; - ccb->pcmd->result = - DID_NO_CONNECT << 16; - arcmsr_ccb_complete(ccb, 1); - } - break; - - case ARCMSR_DEV_ABORTED: - - case ARCMSR_DEV_INIT_FAIL: { - acb->devstate[id][lun] = - ARECA_RAID_GONE; - ccb->pcmd->result = - DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); - } - break; - - case ARCMSR_DEV_CHECK_CONDITION: { - acb->devstate[id][lun] = - ARECA_RAID_GOOD; - arcmsr_report_sense_info(ccb); - arcmsr_ccb_complete(ccb, 1); - } - break; + uint32_t intmask_org; + int i = 0; - default: - printk(KERN_NOTICE - "arcmsr%d: scsi \ - id = %d lun = %d" - " polling and \ - getting command \ - error done" - "but got unknown \ - DeviceStatus = 0x%x \n" - , acb->host->host_no, - id, lun, - ccb->arcmsr_cdb.DeviceStatus); - acb->devstate[id][lun] = - ARECA_RAID_GONE; - ccb->pcmd->result = - DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); - break; - } - } - found = 1; + if (atomic_read(&acb->ccboutstandingcount) != 0) { + /* talk to iop 331 outstanding command aborted */ + arcmsr_abort_allcmd(acb); + /* wait for 3 sec for all command aborted*/ + ssleep(3); + /* disable all outbound interrupt */ + intmask_org = arcmsr_disable_outbound_ints(acb); + /* clear all outbound posted Q */ + arcmsr_done4abort_postqueue(acb); + for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { + ccb = acb->pccb_pool[i]; + if (ccb->startdone == ARCMSR_CCB_START) { + ccb->startdone = ARCMSR_CCB_ABORTED; + arcmsr_ccb_complete(ccb, 1); } } - if (found){ - outbound_intstatus = readl(®->outbound_intstatus) & - acb->outbound_int_enable; - writel(outbound_intstatus, ®->outbound_intstatus); - /*clear interrupt*/ - } - return; + /* enable all outbound interrupt */ + arcmsr_enable_outbound_ints(acb, intmask_org); + } + pci_disable_device(pdev); } - static void arcmsr_pci_ers_disconnect_forepart(struct pci_dev *pdev) { - struct Scsi_Host *host = pci_get_drvdata(pdev); - struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; - struct MessageUnit __iomem *reg = acb->pmu; - struct CommandControlBlock *ccb; - /*clear and abort all outbound posted Q*/ - int i = 0, found = 0; - int id, lun; - uint32_t flag_ccb, outbound_intstatus; - - while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) && - (i++ < 256)){ - ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + - (flag_ccb << 5)); - if (ccb){ - if ((ccb->acb != acb)||(ccb->startdone != - ARCMSR_CCB_START)){ - printk(KERN_NOTICE - "arcmsr%d: polling get an illegal ccb" - " command done ccb = '0x%p'" - "ccboutstandingcount = %d \n", - acb->host->host_no, ccb, - atomic_read(&acb->ccboutstandingcount)); - continue; - } - - id = ccb->pcmd->device->id; - lun = ccb->pcmd->device->lun; - if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { - if (acb->devstate[id][lun] == ARECA_RAID_GONE) - acb->devstate[id][lun] = ARECA_RAID_GOOD; - ccb->pcmd->result = DID_OK << 16; - arcmsr_ccb_complete(ccb, 1); - } - else { - switch(ccb->arcmsr_cdb.DeviceStatus) { - case ARCMSR_DEV_SELECT_TIMEOUT: { - acb->devstate[id][lun] = - ARECA_RAID_GONE; - ccb->pcmd->result = - DID_NO_CONNECT << 16; - arcmsr_ccb_complete(ccb, 1); - } - break; - - case ARCMSR_DEV_ABORTED: - - case ARCMSR_DEV_INIT_FAIL: { - acb->devstate[id][lun] = - ARECA_RAID_GONE; - ccb->pcmd->result = - DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); - } - break; - - case ARCMSR_DEV_CHECK_CONDITION: { - acb->devstate[id][lun] = - ARECA_RAID_GOOD; - arcmsr_report_sense_info(ccb); - arcmsr_ccb_complete(ccb, 1); - } - break; + struct Scsi_Host *host = pci_get_drvdata(pdev); + struct AdapterControlBlock *acb = \ + (struct AdapterControlBlock *)host->hostdata; - default: - printk(KERN_NOTICE "arcmsr%d: \ - scsi id = %d lun = %d" - " polling and \ - getting command error done" - "but got unknown \ - DeviceStatus = 0x%x \n" - , acb->host->host_no, - id, lun, ccb->arcmsr_cdb.DeviceStatus); - acb->devstate[id][lun] = - ARECA_RAID_GONE; - ccb->pcmd->result = - DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); - break; - } - } - found = 1; - } - } - if (found){ - outbound_intstatus = readl(®->outbound_intstatus) & - acb->outbound_int_enable; - writel(outbound_intstatus, ®->outbound_intstatus); - /*clear interrupt*/ - } - return; + arcmsr_stop_adapter_bgrb(acb); + arcmsr_flush_adapter_cache(acb); } static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, @@ -1840,5 +2312,6 @@ static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, break; default: return PCI_ERS_RESULT_NEED_RESET; - } + } } +#endif diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 715a23e4a1e9..92dc6ca840d4 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2057,6 +2057,9 @@ #define PCI_DEVICE_ID_ARECA_1130 0x1130 #define PCI_DEVICE_ID_ARECA_1160 0x1160 #define PCI_DEVICE_ID_ARECA_1170 0x1170 +#define PCI_DEVICE_ID_ARECA_1200 0x1200 +#define PCI_DEVICE_ID_ARECA_1201 0x1201 +#define PCI_DEVICE_ID_ARECA_1202 0x1202 #define PCI_DEVICE_ID_ARECA_1210 0x1210 #define PCI_DEVICE_ID_ARECA_1220 0x1220 #define PCI_DEVICE_ID_ARECA_1230 0x1230 -- cgit v1.2.3 From 7f9a6bc4e9d59e7fcf03ed23f60cd81ca5d80b65 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 4 Aug 2007 10:06:25 -0500 Subject: [SCSI] move ULD attachment into the prep function One of the intents of the block prep function was to allow ULDs to use it for preprocessing. The original SCSI model was to have a single prep function and add a pointer indirect filter to build the necessary commands. This patch reverses that, does away with the init_command field of the scsi_driver structure and makes ULDs attach directly to the prep function instead. The value is really that it allows us to begin to separate the ULDs from the SCSI mid layer (as long as they don't use any core functions---which is hard at the moment---a ULD doesn't even need SCSI to bind). Acked-by: Jens Axboe Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 84 ++++++++++++++++++++-------------------------- drivers/scsi/sd.c | 48 ++++++++++++++++++-------- drivers/scsi/sr.c | 59 +++++++++++++++++++++----------- include/scsi/scsi_driver.h | 9 ++++- include/scsi/sd.h | 1 - 5 files changed, 119 insertions(+), 82 deletions(-) (limited to 'include') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 47d3cdd6ddf1..94d82cb96626 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1039,9 +1039,6 @@ static int scsi_init_io(struct scsi_cmnd *cmd) printk(KERN_ERR "req nr_sec %lu, cur_nr_sec %u\n", req->nr_sectors, req->current_nr_sectors); - /* release the command and kill it */ - scsi_release_buffers(cmd); - scsi_put_command(cmd); return BLKPREP_KILL; } @@ -1078,9 +1075,13 @@ static void scsi_blk_pc_done(struct scsi_cmnd *cmd) scsi_io_completion(cmd, cmd->request_bufflen); } -static int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) +int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) { struct scsi_cmnd *cmd; + int ret = scsi_prep_state_check(sdev, req); + + if (ret != BLKPREP_OK) + return ret; cmd = scsi_get_cmd_from_req(sdev, req); if (unlikely(!cmd)) @@ -1126,18 +1127,20 @@ static int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) cmd->done = scsi_blk_pc_done; return BLKPREP_OK; } +EXPORT_SYMBOL(scsi_setup_blk_pc_cmnd); /* * Setup a REQ_TYPE_FS command. These are simple read/write request * from filesystems that still need to be translated to SCSI CDBs from * the ULD. */ -static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) +int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) { struct scsi_cmnd *cmd; - struct scsi_driver *drv; - int ret; + int ret = scsi_prep_state_check(sdev, req); + if (ret != BLKPREP_OK) + return ret; /* * Filesystem requests must transfer data. */ @@ -1147,26 +1150,12 @@ static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) if (unlikely(!cmd)) return BLKPREP_DEFER; - ret = scsi_init_io(cmd); - if (unlikely(ret)) - return ret; - - /* - * Initialize the actual SCSI command for this request. - */ - drv = *(struct scsi_driver **)req->rq_disk->private_data; - if (unlikely(!drv->init_command(cmd))) { - scsi_release_buffers(cmd); - scsi_put_command(cmd); - return BLKPREP_KILL; - } - - return BLKPREP_OK; + return scsi_init_io(cmd); } +EXPORT_SYMBOL(scsi_setup_fs_cmnd); -static int scsi_prep_fn(struct request_queue *q, struct request *req) +int scsi_prep_state_check(struct scsi_device *sdev, struct request *req) { - struct scsi_device *sdev = q->queuedata; int ret = BLKPREP_OK; /* @@ -1212,35 +1201,25 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) ret = BLKPREP_KILL; break; } - - if (ret != BLKPREP_OK) - goto out; } + return ret; +} +EXPORT_SYMBOL(scsi_prep_state_check); - switch (req->cmd_type) { - case REQ_TYPE_BLOCK_PC: - ret = scsi_setup_blk_pc_cmnd(sdev, req); - break; - case REQ_TYPE_FS: - ret = scsi_setup_fs_cmnd(sdev, req); - break; - default: - /* - * All other command types are not supported. - * - * Note that these days the SCSI subsystem does not use - * REQ_TYPE_SPECIAL requests anymore. These are only used - * (directly or via blk_insert_request) by non-SCSI drivers. - */ - blk_dump_rq_flags(req, "SCSI bad req"); - ret = BLKPREP_KILL; - break; - } +int scsi_prep_return(struct request_queue *q, struct request *req, int ret) +{ + struct scsi_device *sdev = q->queuedata; - out: switch (ret) { case BLKPREP_KILL: req->errors = DID_NO_CONNECT << 16; + /* release the command and kill it */ + if (req->special) { + struct scsi_cmnd *cmd = req->special; + scsi_release_buffers(cmd); + scsi_put_command(cmd); + req->special = NULL; + } break; case BLKPREP_DEFER: /* @@ -1257,6 +1236,17 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) return ret; } +EXPORT_SYMBOL(scsi_prep_return); + +static int scsi_prep_fn(struct request_queue *q, struct request *req) +{ + struct scsi_device *sdev = q->queuedata; + int ret = BLKPREP_KILL; + + if (req->cmd_type == REQ_TYPE_BLOCK_PC) + ret = scsi_setup_blk_pc_cmnd(sdev, req); + return scsi_prep_return(q, req, ret); +} /* * scsi_dev_queue_ready: if we can send requests to sdev, return 1 else diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 2c6116fd4578..38a41415004b 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -240,7 +240,6 @@ static struct scsi_driver sd_template = { .shutdown = sd_shutdown, }, .rescan = sd_rescan, - .init_command = sd_init_command, }; /* @@ -331,14 +330,31 @@ static void scsi_disk_put(struct scsi_disk *sdkp) * * Returns 1 if successful and 0 if error (or cannot be done now). **/ -static int sd_init_command(struct scsi_cmnd * SCpnt) +static int sd_prep_fn(struct request_queue *q, struct request *rq) { - struct scsi_device *sdp = SCpnt->device; - struct request *rq = SCpnt->request; + struct scsi_cmnd *SCpnt; + struct scsi_device *sdp = q->queuedata; struct gendisk *disk = rq->rq_disk; sector_t block = rq->sector; - unsigned int this_count = SCpnt->request_bufflen >> 9; + unsigned int this_count = rq->nr_sectors; unsigned int timeout = sdp->timeout; + int ret; + + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { + ret = scsi_setup_blk_pc_cmnd(sdp, rq); + goto out; + } else if (rq->cmd_type != REQ_TYPE_FS) { + ret = BLKPREP_KILL; + goto out; + } + ret = scsi_setup_fs_cmnd(sdp, rq); + if (ret != BLKPREP_OK) + goto out; + SCpnt = rq->special; + + /* from here on until we're complete, any goto out + * is used for a killable error condition */ + ret = BLKPREP_KILL; SCSI_LOG_HLQUEUE(1, scmd_printk(KERN_INFO, SCpnt, "sd_init_command: block=%llu, " @@ -353,7 +369,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) rq->nr_sectors)); SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "Retry with 0x%p\n", SCpnt)); - return 0; + goto out; } if (sdp->changed) { @@ -362,8 +378,9 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) * the changed bit has been reset */ /* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */ - return 0; + goto out; } + SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n", (unsigned long long)block)); @@ -382,7 +399,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) if ((block & 1) || (rq->nr_sectors & 1)) { scmd_printk(KERN_ERR, SCpnt, "Bad block number requested\n"); - return 0; + goto out; } else { block = block >> 1; this_count = this_count >> 1; @@ -392,7 +409,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) if ((block & 3) || (rq->nr_sectors & 3)) { scmd_printk(KERN_ERR, SCpnt, "Bad block number requested\n"); - return 0; + goto out; } else { block = block >> 2; this_count = this_count >> 2; @@ -402,7 +419,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) if ((block & 7) || (rq->nr_sectors & 7)) { scmd_printk(KERN_ERR, SCpnt, "Bad block number requested\n"); - return 0; + goto out; } else { block = block >> 3; this_count = this_count >> 3; @@ -410,7 +427,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) } if (rq_data_dir(rq) == WRITE) { if (!sdp->writeable) { - return 0; + goto out; } SCpnt->cmnd[0] = WRITE_6; SCpnt->sc_data_direction = DMA_TO_DEVICE; @@ -419,7 +436,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) SCpnt->sc_data_direction = DMA_FROM_DEVICE; } else { scmd_printk(KERN_ERR, SCpnt, "Unknown command %x\n", rq->cmd_flags); - return 0; + goto out; } SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, @@ -470,7 +487,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) */ scmd_printk(KERN_ERR, SCpnt, "FUA write on READ/WRITE(6) drive\n"); - return 0; + goto out; } SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f); @@ -501,7 +518,9 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) * This indicates that the command is ready from our end to be * queued. */ - return 1; + ret = BLKPREP_OK; + out: + return scsi_prep_return(q, rq, ret); } /** @@ -1669,6 +1688,7 @@ static int sd_probe(struct device *dev) sd_revalidate_disk(gd); + blk_queue_prep_rq(sdp->request_queue, sd_prep_fn); blk_queue_issue_flush_fn(sdp->request_queue, sd_issue_flush); gd->driverfs_dev = &sdp->sdev_gendev; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 902eb11ffe8a..a0c4e13d4dab 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -78,7 +78,6 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM); static int sr_probe(struct device *); static int sr_remove(struct device *); -static int sr_init_command(struct scsi_cmnd *); static struct scsi_driver sr_template = { .owner = THIS_MODULE, @@ -87,7 +86,6 @@ static struct scsi_driver sr_template = { .probe = sr_probe, .remove = sr_remove, }, - .init_command = sr_init_command, }; static unsigned long sr_index_bits[SR_DISKS / BITS_PER_LONG]; @@ -296,19 +294,39 @@ static void rw_intr(struct scsi_cmnd * SCpnt) scsi_io_completion(SCpnt, good_bytes); } -static int sr_init_command(struct scsi_cmnd * SCpnt) +static int sr_prep_fn(struct request_queue *q, struct request *rq) { int block=0, this_count, s_size, timeout = SR_TIMEOUT; - struct scsi_cd *cd = scsi_cd(SCpnt->request->rq_disk); + struct scsi_cd *cd; + struct scsi_cmnd *SCpnt; + struct scsi_device *sdp = q->queuedata; + int ret; + + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { + ret = scsi_setup_blk_pc_cmnd(sdp, rq); + goto out; + } else if (rq->cmd_type != REQ_TYPE_FS) { + ret = BLKPREP_KILL; + goto out; + } + ret = scsi_setup_fs_cmnd(sdp, rq); + if (ret != BLKPREP_OK) + goto out; + SCpnt = rq->special; + cd = scsi_cd(rq->rq_disk); + + /* from here on until we're complete, any goto out + * is used for a killable error condition */ + ret = BLKPREP_KILL; SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %s, block = %d\n", cd->disk->disk_name, block)); if (!cd->device || !scsi_device_online(cd->device)) { SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", - SCpnt->request->nr_sectors)); + rq->nr_sectors)); SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt)); - return 0; + goto out; } if (cd->device->changed) { @@ -316,7 +334,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) * quietly refuse to do anything to a changed disc until the * changed bit has been reset */ - return 0; + goto out; } /* @@ -333,21 +351,21 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) if (s_size != 512 && s_size != 1024 && s_size != 2048) { scmd_printk(KERN_ERR, SCpnt, "bad sector size %d\n", s_size); - return 0; + goto out; } - if (rq_data_dir(SCpnt->request) == WRITE) { + if (rq_data_dir(rq) == WRITE) { if (!cd->device->writeable) - return 0; + goto out; SCpnt->cmnd[0] = WRITE_10; SCpnt->sc_data_direction = DMA_TO_DEVICE; cd->cdi.media_written = 1; - } else if (rq_data_dir(SCpnt->request) == READ) { + } else if (rq_data_dir(rq) == READ) { SCpnt->cmnd[0] = READ_10; SCpnt->sc_data_direction = DMA_FROM_DEVICE; } else { - blk_dump_rq_flags(SCpnt->request, "Unknown sr command"); - return 0; + blk_dump_rq_flags(rq, "Unknown sr command"); + goto out; } { @@ -368,10 +386,10 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) /* * request doesn't start on hw block boundary, add scatter pads */ - if (((unsigned int)SCpnt->request->sector % (s_size >> 9)) || + if (((unsigned int)rq->sector % (s_size >> 9)) || (SCpnt->request_bufflen % s_size)) { scmd_printk(KERN_NOTICE, SCpnt, "unaligned transfer\n"); - return 0; + goto out; } this_count = (SCpnt->request_bufflen >> 9) / (s_size >> 9); @@ -379,12 +397,12 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n", cd->cdi.name, - (rq_data_dir(SCpnt->request) == WRITE) ? + (rq_data_dir(rq) == WRITE) ? "writing" : "reading", - this_count, SCpnt->request->nr_sectors)); + this_count, rq->nr_sectors)); SCpnt->cmnd[1] = 0; - block = (unsigned int)SCpnt->request->sector / (s_size >> 9); + block = (unsigned int)rq->sector / (s_size >> 9); if (this_count > 0xffff) { this_count = 0xffff; @@ -419,7 +437,9 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) * This indicates that the command is ready from our end to be * queued. */ - return 1; + ret = BLKPREP_OK; + out: + return scsi_prep_return(q, rq, ret); } static int sr_block_open(struct inode *inode, struct file *file) @@ -590,6 +610,7 @@ static int sr_probe(struct device *dev) /* FIXME: need to handle a get_capabilities failure properly ?? */ get_capabilities(cd); + blk_queue_prep_rq(sdev->request_queue, sr_prep_fn); sr_vendor_init(cd); disk->driverfs_dev = &sdev->sdev_gendev; diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h index 3465f31a21c4..56a304709fde 100644 --- a/include/scsi/scsi_driver.h +++ b/include/scsi/scsi_driver.h @@ -5,13 +5,15 @@ struct module; struct scsi_cmnd; +struct scsi_device; +struct request; +struct request_queue; struct scsi_driver { struct module *owner; struct device_driver gendrv; - int (*init_command)(struct scsi_cmnd *); void (*rescan)(struct device *); }; #define to_scsi_driver(drv) \ @@ -25,4 +27,9 @@ extern int scsi_register_interface(struct class_interface *); #define scsi_unregister_interface(intf) \ class_interface_unregister(intf) +int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req); +int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req); +int scsi_prep_state_check(struct scsi_device *sdev, struct request *req); +int scsi_prep_return(struct request_queue *q, struct request *req, int ret); + #endif /* _SCSI_SCSI_DRIVER_H */ diff --git a/include/scsi/sd.h b/include/scsi/sd.h index ce02ad1f5185..aa1e71613010 100644 --- a/include/scsi/sd.h +++ b/include/scsi/sd.h @@ -55,7 +55,6 @@ static void sd_shutdown(struct device *dev); static int sd_suspend(struct device *dev, pm_message_t state); static int sd_resume(struct device *dev); static void sd_rescan(struct device *); -static int sd_init_command(struct scsi_cmnd *); static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer); static void scsi_disk_release(struct class_device *cdev); static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); -- cgit v1.2.3 From 12a441622b753684cc73d1c6f225e9ac53e0bf77 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 18 Sep 2007 19:54:43 -0600 Subject: [SCSI] Remove ->pid field from scsi_cmnd The pid field is a duplicate of the serial_number field and has been scheduled for removal for a long time. A few drivers were still using it, so just change them to use serial_number instead. Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/dc395x.c | 110 +++++++++++++++++++++++----------------------- drivers/scsi/eata.c | 44 +++++++++---------- drivers/scsi/eata_pio.c | 12 ++--- drivers/scsi/in2000.c | 30 ++++++------- drivers/scsi/ncr53c8xx.c | 7 +-- drivers/scsi/qla1280.c | 2 +- drivers/scsi/scsi.c | 6 +-- drivers/scsi/scsi_error.c | 6 --- drivers/scsi/tmscsim.c | 18 ++++---- drivers/scsi/u14-34f.c | 44 +++++++++---------- drivers/scsi/wd33c93.c | 32 +++++++------- include/scsi/scsi_cmnd.h | 11 ++--- include/scsi/scsi_host.h | 2 +- 13 files changed, 153 insertions(+), 171 deletions(-) (limited to 'include') diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index 7b8a3457b696..1591824cf4b3 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -778,7 +778,7 @@ static void srb_waiting_insert(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { dprintkdbg(DBG_0, "srb_waiting_insert: (pid#%li) <%02i-%i> srb=%p\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_add(&srb->list, &dcb->srb_waiting_list); } @@ -787,7 +787,7 @@ static void srb_waiting_append(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { dprintkdbg(DBG_0, "srb_waiting_append: (pid#%li) <%02i-%i> srb=%p\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_add_tail(&srb->list, &dcb->srb_waiting_list); } @@ -795,7 +795,7 @@ static void srb_waiting_append(struct DeviceCtlBlk *dcb, static void srb_going_append(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { dprintkdbg(DBG_0, "srb_going_append: (pid#%li) <%02i-%i> srb=%p\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_add_tail(&srb->list, &dcb->srb_going_list); } @@ -805,7 +805,7 @@ static void srb_going_remove(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) struct ScsiReqBlk *i; struct ScsiReqBlk *tmp; dprintkdbg(DBG_0, "srb_going_remove: (pid#%li) <%02i-%i> srb=%p\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_for_each_entry_safe(i, tmp, &dcb->srb_going_list, list) if (i == srb) { @@ -821,7 +821,7 @@ static void srb_waiting_remove(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *i; struct ScsiReqBlk *tmp; dprintkdbg(DBG_0, "srb_waiting_remove: (pid#%li) <%02i-%i> srb=%p\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_for_each_entry_safe(i, tmp, &dcb->srb_waiting_list, list) if (i == srb) { @@ -836,7 +836,7 @@ static void srb_going_to_waiting_move(struct DeviceCtlBlk *dcb, { dprintkdbg(DBG_0, "srb_going_to_waiting_move: (pid#%li) <%02i-%i> srb=%p\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_move(&srb->list, &dcb->srb_waiting_list); } @@ -846,7 +846,7 @@ static void srb_waiting_to_going_move(struct DeviceCtlBlk *dcb, { dprintkdbg(DBG_0, "srb_waiting_to_going_move: (pid#%li) <%02i-%i> srb=%p\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_move(&srb->list, &dcb->srb_going_list); } @@ -982,7 +982,7 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, int nseg; enum dma_data_direction dir = cmd->sc_data_direction; dprintkdbg(DBG_0, "build_srb: (pid#%li) <%02i-%i>\n", - cmd->pid, dcb->target_id, dcb->target_lun); + cmd->serial_number, dcb->target_id, dcb->target_lun); srb->dcb = dcb; srb->cmd = cmd; @@ -1086,7 +1086,7 @@ static int dc395x_queue_command(struct scsi_cmnd *cmd, void (*done)(struct scsi_ struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)cmd->device->host->hostdata; dprintkdbg(DBG_0, "queue_command: (pid#%li) <%02i-%i> cmnd=0x%02x\n", - cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); /* Assume BAD_TARGET; will be cleared later */ cmd->result = DID_BAD_TARGET << 16; @@ -1139,7 +1139,7 @@ static int dc395x_queue_command(struct scsi_cmnd *cmd, void (*done)(struct scsi_ /* process immediately */ send_srb(acb, srb); } - dprintkdbg(DBG_1, "queue_command: (pid#%li) done\n", cmd->pid); + dprintkdbg(DBG_1, "queue_command: (pid#%li) done\n", cmd->serial_number); return 0; complete: @@ -1203,7 +1203,7 @@ static void dump_register_info(struct AdapterCtlBlk *acb, else dprintkl(KERN_INFO, "dump: srb=%p cmd=%p (pid#%li) " "cmnd=0x%02x <%02i-%i>\n", - srb, srb->cmd, srb->cmd->pid, + srb, srb->cmd, srb->cmd->serial_number, srb->cmd->cmnd[0], srb->cmd->device->id, srb->cmd->device->lun); printk(" sglist=%p cnt=%i idx=%i len=%zu\n", @@ -1300,7 +1300,7 @@ static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd) (struct AdapterCtlBlk *)cmd->device->host->hostdata; dprintkl(KERN_INFO, "eh_bus_reset: (pid#%li) target=<%02i-%i> cmd=%p\n", - cmd->pid, cmd->device->id, cmd->device->lun, cmd); + cmd->serial_number, cmd->device->id, cmd->device->lun, cmd); if (timer_pending(&acb->waiting_timer)) del_timer(&acb->waiting_timer); @@ -1367,7 +1367,7 @@ static int dc395x_eh_abort(struct scsi_cmnd *cmd) struct DeviceCtlBlk *dcb; struct ScsiReqBlk *srb; dprintkl(KERN_INFO, "eh_abort: (pid#%li) target=<%02i-%i> cmd=%p\n", - cmd->pid, cmd->device->id, cmd->device->lun, cmd); + cmd->serial_number, cmd->device->id, cmd->device->lun, cmd); dcb = find_dcb(acb, cmd->device->id, cmd->device->lun); if (!dcb) { @@ -1494,7 +1494,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, u8 s_stat, scsicommand, i, identify_message; u8 *ptr; dprintkdbg(DBG_0, "start_scsi: (pid#%li) <%02i-%i> srb=%p\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); srb->tag_number = TAG_NONE; /* acb->tag_max_num: had error read in eeprom */ @@ -1504,7 +1504,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, #if 1 if (s_stat & 0x20 /* s_stat2 & 0x02000 */ ) { dprintkdbg(DBG_KG, "start_scsi: (pid#%li) BUSY %02x %04x\n", - srb->cmd->pid, s_stat, s_stat2); + srb->cmd->serial_number, s_stat, s_stat2); /* * Try anyway? * @@ -1522,14 +1522,14 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, if (acb->active_dcb) { dprintkl(KERN_DEBUG, "start_scsi: (pid#%li) Attempt to start a" "command while another command (pid#%li) is active.", - srb->cmd->pid, + srb->cmd->serial_number, acb->active_dcb->active_srb ? - acb->active_dcb->active_srb->cmd->pid : 0); + acb->active_dcb->active_srb->cmd->serial_number : 0); return 1; } if (DC395x_read16(acb, TRM_S1040_SCSI_STATUS) & SCSIINTERRUPT) { dprintkdbg(DBG_KG, "start_scsi: (pid#%li) Failed (busy)\n", - srb->cmd->pid); + srb->cmd->serial_number); return 1; } /* Allow starting of SCSI commands half a second before we allow the mid-level @@ -1603,7 +1603,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, if (tag_number >= dcb->max_command) { dprintkl(KERN_WARNING, "start_scsi: (pid#%li) " "Out of tags target=<%02i-%i>)\n", - srb->cmd->pid, srb->cmd->device->id, + srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun); srb->state = SRB_READY; DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, @@ -1622,7 +1622,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, /*polling:*/ /* Send CDB ..command block ......... */ dprintkdbg(DBG_KG, "start_scsi: (pid#%li) <%02i-%i> cmnd=0x%02x tag=%i\n", - srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun, + srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun, srb->cmd->cmnd[0], srb->tag_number); if (srb->flag & AUTO_REQSENSE) { DC395x_write8(acb, TRM_S1040_SCSI_FIFO, REQUEST_SENSE); @@ -1647,7 +1647,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, * : Let's process it first! */ dprintkdbg(DBG_0, "start_scsi: (pid#%li) <%02i-%i> Failed - busy\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun); srb->state = SRB_READY; free_tag(dcb, srb); srb->msg_count = 0; @@ -1842,7 +1842,7 @@ static irqreturn_t dc395x_interrupt(int irq, void *dev_id) static void msgout_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { - dprintkdbg(DBG_0, "msgout_phase0: (pid#%li)\n", srb->cmd->pid); + dprintkdbg(DBG_0, "msgout_phase0: (pid#%li)\n", srb->cmd->serial_number); if (srb->state & (SRB_UNEXPECT_RESEL + SRB_ABORT_SENT)) *pscsi_status = PH_BUS_FREE; /*.. initial phase */ @@ -1856,18 +1856,18 @@ static void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, { u16 i; u8 *ptr; - dprintkdbg(DBG_0, "msgout_phase1: (pid#%li)\n", srb->cmd->pid); + dprintkdbg(DBG_0, "msgout_phase1: (pid#%li)\n", srb->cmd->serial_number); clear_fifo(acb, "msgout_phase1"); if (!(srb->state & SRB_MSGOUT)) { srb->state |= SRB_MSGOUT; dprintkl(KERN_DEBUG, "msgout_phase1: (pid#%li) Phase unexpected\n", - srb->cmd->pid); /* So what ? */ + srb->cmd->serial_number); /* So what ? */ } if (!srb->msg_count) { dprintkdbg(DBG_0, "msgout_phase1: (pid#%li) NOP msg\n", - srb->cmd->pid); + srb->cmd->serial_number); DC395x_write8(acb, TRM_S1040_SCSI_FIFO, MSG_NOP); DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_FIFO_OUT); @@ -1887,7 +1887,7 @@ static void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, static void command_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { - dprintkdbg(DBG_0, "command_phase0: (pid#%li)\n", srb->cmd->pid); + dprintkdbg(DBG_0, "command_phase0: (pid#%li)\n", srb->cmd->serial_number); DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); } @@ -1898,7 +1898,7 @@ static void command_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, struct DeviceCtlBlk *dcb; u8 *ptr; u16 i; - dprintkdbg(DBG_0, "command_phase1: (pid#%li)\n", srb->cmd->pid); + dprintkdbg(DBG_0, "command_phase1: (pid#%li)\n", srb->cmd->serial_number); clear_fifo(acb, "command_phase1"); DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_CLRATN); @@ -2042,7 +2042,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 scsi_status = *pscsi_status; u32 d_left_counter = 0; dprintkdbg(DBG_0, "data_out_phase0: (pid#%li) <%02i-%i>\n", - srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun); /* * KG: We need to drain the buffers before we draw any conclusions! @@ -2172,7 +2172,7 @@ static void data_out_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { dprintkdbg(DBG_0, "data_out_phase1: (pid#%li) <%02i-%i>\n", - srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun); clear_fifo(acb, "data_out_phase1"); /* do prepare before transfer when data out phase */ data_io_transfer(acb, srb, XFERDATAOUT); @@ -2184,7 +2184,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 scsi_status = *pscsi_status; dprintkdbg(DBG_0, "data_in_phase0: (pid#%li) <%02i-%i>\n", - srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun); /* * KG: DataIn is much more tricky than DataOut. When the device is finished @@ -2205,7 +2205,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, if (scsi_status & PARITYERROR) { dprintkl(KERN_INFO, "data_in_phase0: (pid#%li) " - "Parity Error\n", srb->cmd->pid); + "Parity Error\n", srb->cmd->serial_number); srb->status |= PARITY_ERROR; } /* @@ -2395,7 +2395,7 @@ static void data_in_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { dprintkdbg(DBG_0, "data_in_phase1: (pid#%li) <%02i-%i>\n", - srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun); data_io_transfer(acb, srb, XFERDATAIN); } @@ -2407,7 +2407,7 @@ static void data_io_transfer(struct AdapterCtlBlk *acb, u8 bval; dprintkdbg(DBG_0, "data_io_transfer: (pid#%li) <%02i-%i> %c len=%i, sg=(%i/%i)\n", - srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun, + srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun, ((io_dir & DMACMD_DIR) ? 'r' : 'w'), srb->total_xfer_length, srb->sg_index, srb->sg_count); if (srb == acb->tmp_srb) @@ -2580,7 +2580,7 @@ static void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { dprintkdbg(DBG_0, "status_phase0: (pid#%li) <%02i-%i>\n", - srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun); srb->target_status = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); srb->end_message = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); /* get message */ srb->state = SRB_COMPLETED; @@ -2594,7 +2594,7 @@ static void status_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { dprintkdbg(DBG_0, "status_phase1: (pid#%li) <%02i-%i>\n", - srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun); srb->state = SRB_STATUS; DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_COMP); @@ -2636,7 +2636,7 @@ static struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb = NULL; struct ScsiReqBlk *i; dprintkdbg(DBG_0, "msgin_qtag: (pid#%li) tag=%i srb=%p\n", - srb->cmd->pid, tag, srb); + srb->cmd->serial_number, tag, srb); if (!(dcb->tag_mask & (1 << tag))) dprintkl(KERN_DEBUG, @@ -2655,7 +2655,7 @@ static struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb, goto mingx0; dprintkdbg(DBG_0, "msgin_qtag: (pid#%li) <%02i-%i>\n", - srb->cmd->pid, srb->dcb->target_id, srb->dcb->target_lun); + srb->cmd->serial_number, srb->dcb->target_id, srb->dcb->target_lun); if (dcb->flag & ABORT_DEV_) { /*srb->state = SRB_ABORT_SENT; */ enable_msgout_abort(acb, srb); @@ -2865,7 +2865,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { struct DeviceCtlBlk *dcb = acb->active_dcb; - dprintkdbg(DBG_0, "msgin_phase0: (pid#%li)\n", srb->cmd->pid); + dprintkdbg(DBG_0, "msgin_phase0: (pid#%li)\n", srb->cmd->serial_number); srb->msgin_buf[acb->msg_len++] = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); if (msgin_completed(srb->msgin_buf, acb->msg_len)) { @@ -2933,7 +2933,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, */ dprintkdbg(DBG_0, "msgin_phase0: (pid#%li) " "SAVE POINTER rem=%i Ignore\n", - srb->cmd->pid, srb->total_xfer_length); + srb->cmd->serial_number, srb->total_xfer_length); break; case RESTORE_POINTERS: @@ -2943,7 +2943,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, case ABORT: dprintkdbg(DBG_0, "msgin_phase0: (pid#%li) " "<%02i-%i> ABORT msg\n", - srb->cmd->pid, dcb->target_id, + srb->cmd->serial_number, dcb->target_id, dcb->target_lun); dcb->flag |= ABORT_DEV_; enable_msgout_abort(acb, srb); @@ -2975,7 +2975,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, static void msgin_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { - dprintkdbg(DBG_0, "msgin_phase1: (pid#%li)\n", srb->cmd->pid); + dprintkdbg(DBG_0, "msgin_phase1: (pid#%li)\n", srb->cmd->serial_number); clear_fifo(acb, "msgin_phase1"); DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, 1); if (!(srb->state & SRB_MSGIN)) { @@ -3041,7 +3041,7 @@ static void disconnect(struct AdapterCtlBlk *acb) } srb = dcb->active_srb; acb->active_dcb = NULL; - dprintkdbg(DBG_0, "disconnect: (pid#%li)\n", srb->cmd->pid); + dprintkdbg(DBG_0, "disconnect: (pid#%li)\n", srb->cmd->serial_number); srb->scsi_phase = PH_BUS_FREE; /* initial phase */ clear_fifo(acb, "disconnect"); @@ -3072,13 +3072,13 @@ static void disconnect(struct AdapterCtlBlk *acb) srb->state = SRB_READY; dprintkl(KERN_DEBUG, "disconnect: (pid#%li) Unexpected\n", - srb->cmd->pid); + srb->cmd->serial_number); srb->target_status = SCSI_STAT_SEL_TIMEOUT; goto disc1; } else { /* Normal selection timeout */ dprintkdbg(DBG_KG, "disconnect: (pid#%li) " - "<%02i-%i> SelTO\n", srb->cmd->pid, + "<%02i-%i> SelTO\n", srb->cmd->serial_number, dcb->target_id, dcb->target_lun); if (srb->retry_count++ > DC395x_MAX_RETRIES || acb->scan_devices) { @@ -3090,7 +3090,7 @@ static void disconnect(struct AdapterCtlBlk *acb) srb_going_to_waiting_move(dcb, srb); dprintkdbg(DBG_KG, "disconnect: (pid#%li) Retry\n", - srb->cmd->pid); + srb->cmd->serial_number); waiting_set_timer(acb, HZ / 20); } } else if (srb->state & SRB_DISCONNECT) { @@ -3144,7 +3144,7 @@ static void reselect(struct AdapterCtlBlk *acb) if (!acb->scan_devices) { dprintkdbg(DBG_KG, "reselect: (pid#%li) <%02i-%i> " "Arb lost but Resel win rsel=%i stat=0x%04x\n", - srb->cmd->pid, dcb->target_id, + srb->cmd->serial_number, dcb->target_id, dcb->target_lun, rsel_tar_lun_id, DC395x_read16(acb, TRM_S1040_SCSI_STATUS)); arblostflag = 1; @@ -3318,7 +3318,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, enum dma_data_direction dir = cmd->sc_data_direction; int ckc_only = 1; - dprintkdbg(DBG_1, "srb_done: (pid#%li) <%02i-%i>\n", srb->cmd->pid, + dprintkdbg(DBG_1, "srb_done: (pid#%li) <%02i-%i>\n", srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun); dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p\n", srb, scsi_sg_count(cmd), srb->sg_index, srb->sg_count, @@ -3499,7 +3499,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, if (srb->total_xfer_length) dprintkdbg(DBG_KG, "srb_done: (pid#%li) <%02i-%i> " "cmnd=0x%02x Missed %i bytes\n", - cmd->pid, cmd->device->id, cmd->device->lun, + cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0], srb->total_xfer_length); } @@ -3509,7 +3509,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, dprintkl(KERN_ERR, "srb_done: ERROR! Completed cmd with tmp_srb\n"); else { dprintkdbg(DBG_0, "srb_done: (pid#%li) done result=0x%08x\n", - cmd->pid, cmd->result); + cmd->serial_number, cmd->result); srb_free_insert(acb, srb); } pci_unmap_srb(acb, srb); @@ -3538,7 +3538,7 @@ static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag, p = srb->cmd; dir = p->sc_data_direction; result = MK_RES(0, did_flag, 0, 0); - printk("G:%li(%02i-%i) ", p->pid, + printk("G:%li(%02i-%i) ", p->serial_number, p->device->id, p->device->lun); srb_going_remove(dcb, srb); free_tag(dcb, srb); @@ -3568,7 +3568,7 @@ static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag, p = srb->cmd; result = MK_RES(0, did_flag, 0, 0); - printk("W:%li<%02i-%i>", p->pid, p->device->id, + printk("W:%li<%02i-%i>", p->serial_number, p->device->id, p->device->lun); srb_waiting_remove(dcb, srb); srb_free_insert(acb, srb); @@ -3678,7 +3678,7 @@ static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, { struct scsi_cmnd *cmd = srb->cmd; dprintkdbg(DBG_1, "request_sense: (pid#%li) <%02i-%i>\n", - cmd->pid, cmd->device->id, cmd->device->lun); + cmd->serial_number, cmd->device->id, cmd->device->lun); srb->flag |= AUTO_REQSENSE; srb->adapter_status = 0; @@ -3709,7 +3709,7 @@ static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, if (start_scsi(acb, dcb, srb)) { /* Should only happen, if sb. else grabs the bus */ dprintkl(KERN_DEBUG, "request_sense: (pid#%li) failed <%02i-%i>\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun); srb_going_to_waiting_move(dcb, srb); waiting_set_timer(acb, HZ / 100); } @@ -4717,13 +4717,13 @@ static int dc395x_proc_info(struct Scsi_Host *host, char *buffer, dcb->target_id, dcb->target_lun, list_size(&dcb->srb_waiting_list)); list_for_each_entry(srb, &dcb->srb_waiting_list, list) - SPRINTF(" %li", srb->cmd->pid); + SPRINTF(" %li", srb->cmd->serial_number); if (!list_empty(&dcb->srb_going_list)) SPRINTF("\nDCB (%02i-%i): Going : %i:", dcb->target_id, dcb->target_lun, list_size(&dcb->srb_going_list)); list_for_each_entry(srb, &dcb->srb_going_list, list) - SPRINTF(" %li", srb->cmd->pid); + SPRINTF(" %li", srb->cmd->serial_number); if (!list_empty(&dcb->srb_waiting_list) || !list_empty(&dcb->srb_going_list)) SPRINTF("\n"); } diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index a83e9f150b97..ec2233114bc9 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c @@ -1758,7 +1758,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt, if (SCpnt->host_scribble) panic("%s: qcomm, pid %ld, SCpnt %p already active.\n", - ha->board_name, SCpnt->pid, SCpnt); + ha->board_name, SCpnt->serial_number, SCpnt); /* i is the mailbox number, look for the first free mailbox starting from last_cp_used */ @@ -1792,7 +1792,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt, if (do_trace) scmd_printk(KERN_INFO, SCpnt, - "qcomm, mbox %d, pid %ld.\n", i, SCpnt->pid); + "qcomm, mbox %d, pid %ld.\n", i, SCpnt->serial_number); cpp->reqsen = 1; cpp->dispri = 1; @@ -1825,7 +1825,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt, unmap_dma(i, ha); SCpnt->host_scribble = NULL; scmd_printk(KERN_INFO, SCpnt, - "qcomm, pid %ld, adapter busy.\n", SCpnt->pid); + "qcomm, pid %ld, adapter busy.\n", SCpnt->serial_number); return 1; } @@ -1841,13 +1841,13 @@ static int eata2x_eh_abort(struct scsi_cmnd *SCarg) if (SCarg->host_scribble == NULL) { scmd_printk(KERN_INFO, SCarg, - "abort, pid %ld inactive.\n", SCarg->pid); + "abort, pid %ld inactive.\n", SCarg->serial_number); return SUCCESS; } i = *(unsigned int *)SCarg->host_scribble; scmd_printk(KERN_WARNING, SCarg, - "abort, mbox %d, pid %ld.\n", i, SCarg->pid); + "abort, mbox %d, pid %ld.\n", i, SCarg->serial_number); if (i >= shost->can_queue) panic("%s: abort, invalid SCarg->host_scribble.\n", ha->board_name); @@ -1892,7 +1892,7 @@ static int eata2x_eh_abort(struct scsi_cmnd *SCarg) SCarg->host_scribble = NULL; ha->cp_stat[i] = FREE; printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n", - ha->board_name, i, SCarg->pid); + ha->board_name, i, SCarg->serial_number); SCarg->scsi_done(SCarg); return SUCCESS; } @@ -1909,12 +1909,12 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg) struct hostdata *ha = (struct hostdata *)shost->hostdata; scmd_printk(KERN_INFO, SCarg, - "reset, enter, pid %ld.\n", SCarg->pid); + "reset, enter, pid %ld.\n", SCarg->serial_number); spin_lock_irq(shost->host_lock); if (SCarg->host_scribble == NULL) - printk("%s: reset, pid %ld inactive.\n", ha->board_name, SCarg->pid); + printk("%s: reset, pid %ld inactive.\n", ha->board_name, SCarg->serial_number); if (ha->in_reset) { printk("%s: reset, exit, already in reset.\n", ha->board_name); @@ -1954,13 +1954,13 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg) if (ha->cp_stat[i] == READY || ha->cp_stat[i] == ABORTING) { ha->cp_stat[i] = ABORTING; printk("%s: reset, mbox %d aborting, pid %ld.\n", - ha->board_name, i, SCpnt->pid); + ha->board_name, i, SCpnt->serial_number); } else { ha->cp_stat[i] = IN_RESET; printk("%s: reset, mbox %d in reset, pid %ld.\n", - ha->board_name, i, SCpnt->pid); + ha->board_name, i, SCpnt->serial_number); } if (SCpnt->host_scribble == NULL) @@ -2015,7 +2015,7 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg) printk ("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n", - ha->board_name, i, SCpnt->pid); + ha->board_name, i, SCpnt->serial_number); } else if (ha->cp_stat[i] == ABORTING) { @@ -2029,7 +2029,7 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg) printk ("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n", - ha->board_name, i, SCpnt->pid); + ha->board_name, i, SCpnt->serial_number); } else @@ -2043,7 +2043,7 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg) do_trace = 0; if (arg_done) - printk("%s: reset, exit, pid %ld done.\n", ha->board_name, SCarg->pid); + printk("%s: reset, exit, pid %ld done.\n", ha->board_name, SCarg->serial_number); else printk("%s: reset, exit.\n", ha->board_name); @@ -2182,7 +2182,7 @@ static int reorder(struct hostdata *ha, unsigned long cursec, cpp = &ha->cp[k]; SCpnt = cpp->SCpnt; ll[n] = SCpnt->request->nr_sectors; - pl[n] = SCpnt->pid; + pl[n] = SCpnt->serial_number; if (!n) continue; @@ -2230,7 +2230,7 @@ static int reorder(struct hostdata *ha, unsigned long cursec, "%s pid %ld mb %d fc %d nr %d sec %ld ns %ld" " cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n", (ihdlr ? "ihdlr" : "qcomm"), - SCpnt->pid, k, flushcount, + SCpnt->serial_number, k, flushcount, n_ready, SCpnt->request->sector, SCpnt->request->nr_sectors, cursec, YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only), @@ -2277,7 +2277,7 @@ static void flush_dev(struct scsi_device *dev, unsigned long cursec, "%s, pid %ld, mbox %d, adapter" " busy, will abort.\n", (ihdlr ? "ihdlr" : "qcomm"), - SCpnt->pid, k); + SCpnt->serial_number, k); ha->cp_stat[k] = ABORTING; continue; } @@ -2391,11 +2391,11 @@ static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost) if (SCpnt->host_scribble == NULL) panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", ha->board_name, - i, SCpnt->pid, SCpnt); + i, SCpnt->serial_number, SCpnt); if (*(unsigned int *)SCpnt->host_scribble != i) panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n", - ha->board_name, i, SCpnt->pid, + ha->board_name, i, SCpnt->serial_number, *(unsigned int *)SCpnt->host_scribble); sync_dma(i, ha); @@ -2445,12 +2445,12 @@ static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost) "target_status 0x%x, sense key 0x%x.\n", ha->board_name, SCpnt->device->channel, SCpnt->device->id, - SCpnt->device->lun, SCpnt->pid, + SCpnt->device->lun, SCpnt->serial_number, spp->target_status, SCpnt->sense_buffer[2]); ha->target_to[SCpnt->device->id][SCpnt->device->channel] = 0; - if (ha->last_retried_pid == SCpnt->pid) + if (ha->last_retried_pid == SCpnt->serial_number) ha->retries = 0; break; @@ -2485,7 +2485,7 @@ static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost) #endif ha->retries++; - ha->last_retried_pid = SCpnt->pid; + ha->last_retried_pid = SCpnt->serial_number; } else status = DID_ERROR << 16; @@ -2516,7 +2516,7 @@ static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost) scmd_printk(KERN_INFO, SCpnt, "ihdlr, mbox %2d, err 0x%x:%x," " pid %ld, reg 0x%x, count %d.\n", i, spp->adapter_status, spp->target_status, - SCpnt->pid, reg, ha->iocount); + SCpnt->serial_number, reg, ha->iocount); unmap_dma(i, ha); diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c index 73260e590f22..96180bb47e41 100644 --- a/drivers/scsi/eata_pio.c +++ b/drivers/scsi/eata_pio.c @@ -375,7 +375,7 @@ static int eata_pio_queue(struct scsi_cmnd *cmd, DBG(DBG_QUEUE, scmd_printk(KERN_DEBUG, cmd, "eata_pio_queue pid %ld, y %d\n", - cmd->pid, y)); + cmd->serial_number, y)); cmd->scsi_done = (void *) done; @@ -420,7 +420,7 @@ static int eata_pio_queue(struct scsi_cmnd *cmd, cmd->result = DID_BUS_BUSY << 16; scmd_printk(KERN_NOTICE, cmd, "eata_pio_queue pid %ld, HBA busy, " - "returning DID_BUS_BUSY, done.\n", cmd->pid); + "returning DID_BUS_BUSY, done.\n", cmd->serial_number); done(cmd); cp->status = FREE; return 0; @@ -435,7 +435,7 @@ static int eata_pio_queue(struct scsi_cmnd *cmd, DBG(DBG_QUEUE, scmd_printk(KERN_DEBUG, cmd, "Queued base %#.4lx pid: %ld " - "slot %d irq %d\n", sh->base, cmd->pid, y, sh->irq)); + "slot %d irq %d\n", sh->base, cmd->serial_number, y, sh->irq)); return 0; } @@ -446,7 +446,7 @@ static int eata_pio_abort(struct scsi_cmnd *cmd) DBG(DBG_ABNORM, scmd_printk(KERN_WARNING, cmd, "eata_pio_abort called pid: %ld\n", - cmd->pid)); + cmd->serial_number)); while (inb(cmd->device->host->base + HA_RAUXSTAT) & HA_ABUSY) if (--loop == 0) { @@ -482,7 +482,7 @@ static int eata_pio_host_reset(struct scsi_cmnd *cmd) DBG(DBG_ABNORM, scmd_printk(KERN_WARNING, cmd, "eata_pio_reset called pid:%ld\n", - cmd->pid)); + cmd->serial_number)); spin_lock_irq(host->host_lock); @@ -501,7 +501,7 @@ static int eata_pio_host_reset(struct scsi_cmnd *cmd) sp = HD(cmd)->ccb[x].cmd; HD(cmd)->ccb[x].status = RESET; - printk(KERN_WARNING "eata_pio_reset: slot %d in reset, pid %ld.\n", x, sp->pid); + printk(KERN_WARNING "eata_pio_reset: slot %d in reset, pid %ld.\n", x, sp->serial_number); if (sp == NULL) panic("eata_pio_reset: slot %d, sp==NULL.\n", x); diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c index 312190a69389..ab7cbf3449ce 100644 --- a/drivers/scsi/in2000.c +++ b/drivers/scsi/in2000.c @@ -343,7 +343,7 @@ static int in2000_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) instance = cmd->device->host; hostdata = (struct IN2000_hostdata *) instance->hostdata; - DB(DB_QUEUE_COMMAND, scmd_printk(KERN_DEBUG, cmd, "Q-%02x-%ld(", cmd->cmnd[0], cmd->pid)) + DB(DB_QUEUE_COMMAND, scmd_printk(KERN_DEBUG, cmd, "Q-%02x-%ld(", cmd->cmnd[0], cmd->serial_number)) /* Set up a few fields in the Scsi_Cmnd structure for our own use: * - host_scribble is the pointer to the next cmd in the input queue @@ -427,7 +427,7 @@ static int in2000_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) in2000_execute(cmd->device->host); - DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->pid)) + DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->serial_number)) return 0; } @@ -703,7 +703,7 @@ static void in2000_execute(struct Scsi_Host *instance) * to search the input_Q again... */ - DB(DB_EXECUTE, printk("%s%ld)EX-2 ", (cmd->SCp.phase) ? "d:" : "", cmd->pid)) + DB(DB_EXECUTE, printk("%s%ld)EX-2 ", (cmd->SCp.phase) ? "d:" : "", cmd->serial_number)) } @@ -1147,7 +1147,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id) case CSR_XFER_DONE | PHS_COMMAND: case CSR_UNEXP | PHS_COMMAND: case CSR_SRV_REQ | PHS_COMMAND: - DB(DB_INTR, printk("CMND-%02x,%ld", cmd->cmnd[0], cmd->pid)) + DB(DB_INTR, printk("CMND-%02x,%ld", cmd->cmnd[0], cmd->serial_number)) transfer_pio(cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata); hostdata->state = S_CONNECTED; break; @@ -1189,7 +1189,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id) switch (msg) { case COMMAND_COMPLETE: - DB(DB_INTR, printk("CCMP-%ld", cmd->pid)) + DB(DB_INTR, printk("CCMP-%ld", cmd->serial_number)) write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); hostdata->state = S_PRE_CMP_DISC; break; @@ -1327,7 +1327,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id) write_3393(hostdata, WD_SOURCE_ID, SRCID_ER); if (phs == 0x60) { - DB(DB_INTR, printk("SX-DONE-%ld", cmd->pid)) + DB(DB_INTR, printk("SX-DONE-%ld", cmd->serial_number)) cmd->SCp.Message = COMMAND_COMPLETE; lun = read_3393(hostdata, WD_TARGET_LUN); DB(DB_INTR, printk(":%d.%d", cmd->SCp.Status, lun)) @@ -1348,7 +1348,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id) in2000_execute(instance); } else { - printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---", asr, sr, phs, cmd->pid); + printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---", asr, sr, phs, cmd->serial_number); } break; @@ -1415,7 +1415,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id) spin_unlock_irqrestore(instance->host_lock, flags); return IRQ_HANDLED; } - DB(DB_INTR, printk("UNEXP_DISC-%ld", cmd->pid)) + DB(DB_INTR, printk("UNEXP_DISC-%ld", cmd->serial_number)) hostdata->connected = NULL; hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); hostdata->state = S_UNCONNECTED; @@ -1440,7 +1440,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id) */ write_3393(hostdata, WD_SOURCE_ID, SRCID_ER); - DB(DB_INTR, printk("DISC-%ld", cmd->pid)) + DB(DB_INTR, printk("DISC-%ld", cmd->serial_number)) if (cmd == NULL) { printk(" - Already disconnected! "); hostdata->state = S_UNCONNECTED; @@ -1573,7 +1573,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id) } else hostdata->state = S_CONNECTED; - DB(DB_INTR, printk("-%ld", cmd->pid)) + DB(DB_INTR, printk("-%ld", cmd->serial_number)) break; default: @@ -1702,7 +1702,7 @@ static int __in2000_abort(Scsi_Cmnd * cmd) prev->host_scribble = cmd->host_scribble; cmd->host_scribble = NULL; cmd->result = DID_ABORT << 16; - printk(KERN_WARNING "scsi%d: Abort - removing command %ld from input_Q. ", instance->host_no, cmd->pid); + printk(KERN_WARNING "scsi%d: Abort - removing command %ld from input_Q. ", instance->host_no, cmd->serial_number); cmd->scsi_done(cmd); return SUCCESS; } @@ -1723,7 +1723,7 @@ static int __in2000_abort(Scsi_Cmnd * cmd) if (hostdata->connected == cmd) { - printk(KERN_WARNING "scsi%d: Aborting connected command %ld - ", instance->host_no, cmd->pid); + printk(KERN_WARNING "scsi%d: Aborting connected command %ld - ", instance->host_no, cmd->serial_number); printk("sending wd33c93 ABORT command - "); write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); @@ -2268,7 +2268,7 @@ static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start, strcat(bp, "\nconnected: "); if (hd->connected) { cmd = (Scsi_Cmnd *) hd->connected; - sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); strcat(bp, tbuf); } } @@ -2276,7 +2276,7 @@ static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start, strcat(bp, "\ninput_Q: "); cmd = (Scsi_Cmnd *) hd->input_Q; while (cmd) { - sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); strcat(bp, tbuf); cmd = (Scsi_Cmnd *) cmd->host_scribble; } @@ -2285,7 +2285,7 @@ static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start, strcat(bp, "\ndisconnected_Q:"); cmd = (Scsi_Cmnd *) hd->disconnected_Q; while (cmd) { - sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); strcat(bp, tbuf); cmd = (Scsi_Cmnd *) cmd->host_scribble; } diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 91fa66c3ec98..016c462bc771 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -8143,12 +8143,7 @@ static int ncr53c8xx_abort(struct scsi_cmnd *cmd) 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); diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 54d8bdf86852..fba8aa8a81b5 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -4086,7 +4086,7 @@ __qla1280_print_scsi_cmd(struct scsi_cmnd *cmd) } */ printk(" tag=%d, transfersize=0x%x \n", cmd->tag, cmd->transfersize); - printk(" Pid=%li, SP=0x%p\n", cmd->pid, CMD_SP(cmd)); + printk(" Pid=%li, SP=0x%p\n", cmd->serial_number, CMD_SP(cmd)); printk(" underflow size = 0x%x, direction=0x%x\n", cmd->underflow, cmd->sc_data_direction); } diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index a5de1a829a76..07a7c2a70a3f 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -442,7 +442,7 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) #endif /* - * Assign a serial number and pid to the request for error recovery + * Assign a serial number to the request for error recovery * and debugging purposes. Protected by the Host_Lock of host. */ static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd) @@ -450,10 +450,6 @@ static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd cmd->serial_number = host->cmd_serial_number++; if (cmd->serial_number == 0) cmd->serial_number = host->cmd_serial_number++; - - cmd->pid = host->cmd_pid++; - if (cmd->pid == 0) - cmd->pid = host->cmd_pid++; } /* diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index c05d020bf926..44e6721ddea6 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1681,12 +1681,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag) init_timer(&scmd->eh_timeout); - /* - * Sometimes the command can get back into the timer chain, - * so use the pid as an identifier. - */ - scmd->pid = 0; - spin_lock_irqsave(shost->host_lock, flags); shost->tmf_in_progress = 1; spin_unlock_irqrestore(shost->host_lock, flags); diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index 5db1520f8ba9..5c72ca31a47a 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c @@ -567,12 +567,12 @@ dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_sr pDCB->TagMask |= 1 << tag[1]; pSRB->TagNumber = tag[1]; DC390_write8(ScsiFifo, tag[1]); - DEBUG1(printk(KERN_INFO "DC390: Select w/DisCn for Cmd %li (SRB %p), block tag %02x\n", scmd->pid, pSRB, tag[1])); + DEBUG1(printk(KERN_INFO "DC390: Select w/DisCn for Cmd %li (SRB %p), block tag %02x\n", scmd->serial_number, pSRB, tag[1])); cmd = SEL_W_ATN3; } else { /* No TagQ */ //no_tag: - DEBUG1(printk(KERN_INFO "DC390: Select w%s/DisCn for Cmd %li (SRB %p), No TagQ\n", disc_allowed ? "" : "o", scmd->pid, pSRB)); + DEBUG1(printk(KERN_INFO "DC390: Select w%s/DisCn for Cmd %li (SRB %p), No TagQ\n", disc_allowed ? "" : "o", scmd->serial_number, pSRB)); } pSRB->SRBState = SRB_START_; @@ -623,7 +623,7 @@ dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_sr { dc390_freetag (pDCB, pSRB); DEBUG0(printk ("DC390: Interrupt during Start SCSI (pid %li, target %02i-%02i)\n", - scmd->pid, scmd->device->id, scmd->device->lun)); + scmd->serial_number, scmd->device->id, scmd->device->lun)); pSRB->SRBState = SRB_READY; //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); pACB->SelLost++; @@ -1708,7 +1708,7 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* status = pSRB->TargetStatus; DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p, pid %li\n", status, pcmd->result,\ - pSRB, pcmd->pid)); + pSRB, pcmd->serial_number)); if(pSRB->SRBFlag & AUTO_REQSENSE) { /* Last command was a Request Sense */ pSRB->SRBFlag &= ~AUTO_REQSENSE; @@ -1729,7 +1729,7 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* } else { SET_RES_DRV(pcmd->result, DRIVER_SENSE); //pSRB->ScsiCmdLen = (u8) (pSRB->Segment1[0] >> 8); - DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); + DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->serial_number, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); pSRB->TotalXferredLen = 0; SET_RES_DID(pcmd->result, DID_SOFT_ERROR); } @@ -1749,7 +1749,7 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* else if (status == SAM_STAT_TASK_SET_FULL) { scsi_track_queue_full(pcmd->device, pDCB->GoingSRBCnt - 1); - DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); + DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->serial_number, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); pSRB->TotalXferredLen = 0; SET_RES_DID(pcmd->result, DID_SOFT_ERROR); } @@ -1803,7 +1803,7 @@ cmd_done: /* Add to free list */ dc390_Free_insert (pACB, pSRB); - DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done pid %li\n", pcmd->pid)); + DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done pid %li\n", pcmd->serial_number)); pcmd->scsi_done (pcmd); return; @@ -1998,7 +1998,7 @@ static int DC390_abort(struct scsi_cmnd *cmd) struct dc390_dcb *pDCB = (struct dc390_dcb*) cmd->device->hostdata; scmd_printk(KERN_WARNING, cmd, - "DC390: Abort command (pid %li)\n", cmd->pid); + "DC390: Abort command (pid %li)\n", cmd->serial_number); /* abort() is too stupid for already sent commands at the moment. * If it's called we are in trouble anyway, so let's dump some info @@ -2006,7 +2006,7 @@ static int DC390_abort(struct scsi_cmnd *cmd) dc390_dumpinfo(pACB, pDCB, NULL); pDCB->DCBFlag |= ABORT_DEV_; - printk(KERN_INFO "DC390: Aborted pid %li\n", cmd->pid); + printk(KERN_INFO "DC390: Aborted pid %li\n", cmd->serial_number); return FAILED; } diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c index 9e8232a1f169..fc9f51818e8f 100644 --- a/drivers/scsi/u14-34f.c +++ b/drivers/scsi/u14-34f.c @@ -1254,7 +1254,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs if (SCpnt->host_scribble) panic("%s: qcomm, pid %ld, SCpnt %p already active.\n", - BN(j), SCpnt->pid, SCpnt); + BN(j), SCpnt->serial_number, SCpnt); /* i is the mailbox number, look for the first free mailbox starting from last_cp_used */ @@ -1285,7 +1285,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n", BN(j), i, SCpnt->device->channel, SCpnt->device->id, - SCpnt->device->lun, SCpnt->pid); + SCpnt->device->lun, SCpnt->serial_number); cpp->opcode = OP_SCSI; cpp->channel = SCpnt->device->channel; @@ -1312,7 +1312,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs unmap_dma(i, j); SCpnt->host_scribble = NULL; scmd_printk(KERN_INFO, SCpnt, - "qcomm, pid %ld, adapter busy.\n", SCpnt->pid); + "qcomm, pid %ld, adapter busy.\n", SCpnt->serial_number); return 1; } @@ -1333,13 +1333,13 @@ static int u14_34f_eh_abort(struct scsi_cmnd *SCarg) { if (SCarg->host_scribble == NULL) { scmd_printk(KERN_INFO, SCarg, "abort, pid %ld inactive.\n", - SCarg->pid); + SCarg->serial_number); return SUCCESS; } i = *(unsigned int *)SCarg->host_scribble; scmd_printk(KERN_INFO, SCarg, "abort, mbox %d, pid %ld.\n", - i, SCarg->pid); + i, SCarg->serial_number); if (i >= sh[j]->can_queue) panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j)); @@ -1383,7 +1383,7 @@ static int u14_34f_eh_abort(struct scsi_cmnd *SCarg) { SCarg->host_scribble = NULL; HD(j)->cp_stat[i] = FREE; printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n", - BN(j), i, SCarg->pid); + BN(j), i, SCarg->serial_number); SCarg->scsi_done(SCarg); return SUCCESS; } @@ -1397,12 +1397,12 @@ static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) { struct scsi_cmnd *SCpnt; j = ((struct hostdata *) SCarg->device->host->hostdata)->board_number; - scmd_printk(KERN_INFO, SCarg, "reset, enter, pid %ld.\n", SCarg->pid); + scmd_printk(KERN_INFO, SCarg, "reset, enter, pid %ld.\n", SCarg->serial_number); spin_lock_irq(sh[j]->host_lock); if (SCarg->host_scribble == NULL) - printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid); + printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->serial_number); if (HD(j)->in_reset) { printk("%s: reset, exit, already in reset.\n", BN(j)); @@ -1440,13 +1440,13 @@ static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) { if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) { HD(j)->cp_stat[i] = ABORTING; printk("%s: reset, mbox %d aborting, pid %ld.\n", - BN(j), i, SCpnt->pid); + BN(j), i, SCpnt->serial_number); } else { HD(j)->cp_stat[i] = IN_RESET; printk("%s: reset, mbox %d in reset, pid %ld.\n", - BN(j), i, SCpnt->pid); + BN(j), i, SCpnt->serial_number); } if (SCpnt->host_scribble == NULL) @@ -1495,7 +1495,7 @@ static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) { HD(j)->cp_stat[i] = LOCKED; printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n", - BN(j), i, SCpnt->pid); + BN(j), i, SCpnt->serial_number); } else if (HD(j)->cp_stat[i] == ABORTING) { @@ -1508,7 +1508,7 @@ static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) { HD(j)->cp_stat[i] = FREE; printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n", - BN(j), i, SCpnt->pid); + BN(j), i, SCpnt->serial_number); } else @@ -1522,7 +1522,7 @@ static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) { HD(j)->in_reset = FALSE; do_trace = FALSE; - if (arg_done) printk("%s: reset, exit, pid %ld done.\n", BN(j), SCarg->pid); + if (arg_done) printk("%s: reset, exit, pid %ld done.\n", BN(j), SCarg->serial_number); else printk("%s: reset, exit.\n", BN(j)); spin_unlock_irq(sh[j]->host_lock); @@ -1639,7 +1639,7 @@ static int reorder(unsigned int j, unsigned long cursec, if (!input_only) for (n = 0; n < n_ready; n++) { k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; - ll[n] = SCpnt->request->nr_sectors; pl[n] = SCpnt->pid; + ll[n] = SCpnt->request->nr_sectors; pl[n] = SCpnt->serial_number; if (!n) continue; @@ -1666,7 +1666,7 @@ static int reorder(unsigned int j, unsigned long cursec, printk("%s %d.%d:%d pid %ld mb %d fc %d nr %d sec %ld ns %ld"\ " cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n", (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target, - SCpnt->lun, SCpnt->pid, k, flushcount, n_ready, + SCpnt->lun, SCpnt->serial_number, k, flushcount, n_ready, SCpnt->request->sector, SCpnt->request->nr_sectors, cursec, YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only), YESNO(overlap), cpp->xdir); @@ -1703,7 +1703,7 @@ static void flush_dev(struct scsi_device *dev, unsigned long cursec, unsigned in scmd_printk(KERN_INFO, SCpnt, "%s, pid %ld, mbox %d, adapter" " busy, will abort.\n", (ihdlr ? "ihdlr" : "qcomm"), - SCpnt->pid, k); + SCpnt->serial_number, k); HD(j)->cp_stat[k] = ABORTING; continue; } @@ -1787,11 +1787,11 @@ static irqreturn_t ihdlr(int irq, unsigned int j) { if (SCpnt->host_scribble == NULL) panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i, - SCpnt->pid, SCpnt); + SCpnt->serial_number, SCpnt); if (*(unsigned int *)SCpnt->host_scribble != i) panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n", - BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble); + BN(j), i, SCpnt->serial_number, *(unsigned int *)SCpnt->host_scribble); sync_dma(i, j); @@ -1835,12 +1835,12 @@ static irqreturn_t ihdlr(int irq, unsigned int j) { (SCpnt->sense_buffer[2] & 0xf) == NOT_READY))) scmd_printk(KERN_INFO, SCpnt, "ihdlr, pid %ld, target_status 0x%x, sense key 0x%x.\n", - SCpnt->pid, spp->target_status, + SCpnt->serial_number, spp->target_status, SCpnt->sense_buffer[2]); HD(j)->target_to[scmd_id(SCpnt)][scmd_channel(SCpnt)] = 0; - if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0; + if (HD(j)->last_retried_pid == SCpnt->serial_number) HD(j)->retries = 0; break; case ASST: /* Selection Time Out */ @@ -1877,7 +1877,7 @@ static irqreturn_t ihdlr(int irq, unsigned int j) { #endif HD(j)->retries++; - HD(j)->last_retried_pid = SCpnt->pid; + HD(j)->last_retried_pid = SCpnt->serial_number; } else status = DID_ERROR << 16; @@ -1907,7 +1907,7 @@ static irqreturn_t ihdlr(int irq, unsigned int j) { #endif scmd_printk(KERN_INFO, SCpnt, "ihdlr, mbox %2d, err 0x%x:%x,"\ " pid %ld, reg 0x%x, count %d.\n", - i, spp->adapter_status, spp->target_status, SCpnt->pid, + i, spp->adapter_status, spp->target_status, SCpnt->serial_number, reg, HD(j)->iocount); unmap_dma(i, j); diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index b92ff047af38..0e8e642fd3b0 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -381,7 +381,7 @@ wd33c93_queuecommand(struct scsi_cmnd *cmd, hostdata = (struct WD33C93_hostdata *) cmd->device->host->hostdata; DB(DB_QUEUE_COMMAND, - printk("Q-%d-%02x-%ld( ", cmd->device->id, cmd->cmnd[0], cmd->pid)) + printk("Q-%d-%02x-%ld( ", cmd->device->id, cmd->cmnd[0], cmd->serial_number)) /* Set up a few fields in the scsi_cmnd structure for our own use: * - host_scribble is the pointer to the next cmd in the input queue @@ -463,7 +463,7 @@ wd33c93_queuecommand(struct scsi_cmnd *cmd, wd33c93_execute(cmd->device->host); - DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->pid)) + DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->serial_number)) spin_unlock_irq(&hostdata->lock); return 0; @@ -686,7 +686,7 @@ wd33c93_execute(struct Scsi_Host *instance) */ DB(DB_EXECUTE, - printk("%s%ld)EX-2 ", (cmd->SCp.phase) ? "d:" : "", cmd->pid)) + printk("%s%ld)EX-2 ", (cmd->SCp.phase) ? "d:" : "", cmd->serial_number)) } static void @@ -963,7 +963,7 @@ wd33c93_intr(struct Scsi_Host *instance) case CSR_XFER_DONE | PHS_COMMAND: case CSR_UNEXP | PHS_COMMAND: case CSR_SRV_REQ | PHS_COMMAND: - DB(DB_INTR, printk("CMND-%02x,%ld", cmd->cmnd[0], cmd->pid)) + DB(DB_INTR, printk("CMND-%02x,%ld", cmd->cmnd[0], cmd->serial_number)) transfer_pio(regs, cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata); hostdata->state = S_CONNECTED; @@ -1007,7 +1007,7 @@ wd33c93_intr(struct Scsi_Host *instance) switch (msg) { case COMMAND_COMPLETE: - DB(DB_INTR, printk("CCMP-%ld", cmd->pid)) + DB(DB_INTR, printk("CCMP-%ld", cmd->serial_number)) write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK); hostdata->state = S_PRE_CMP_DISC; break; @@ -1174,7 +1174,7 @@ wd33c93_intr(struct Scsi_Host *instance) write_wd33c93(regs, WD_SOURCE_ID, SRCID_ER); if (phs == 0x60) { - DB(DB_INTR, printk("SX-DONE-%ld", cmd->pid)) + DB(DB_INTR, printk("SX-DONE-%ld", cmd->serial_number)) cmd->SCp.Message = COMMAND_COMPLETE; lun = read_wd33c93(regs, WD_TARGET_LUN); DB(DB_INTR, printk(":%d.%d", cmd->SCp.Status, lun)) @@ -1201,7 +1201,7 @@ wd33c93_intr(struct Scsi_Host *instance) } else { printk ("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---", - asr, sr, phs, cmd->pid); + asr, sr, phs, cmd->serial_number); spin_unlock_irqrestore(&hostdata->lock, flags); } break; @@ -1266,7 +1266,7 @@ wd33c93_intr(struct Scsi_Host *instance) spin_unlock_irqrestore(&hostdata->lock, flags); return; } - DB(DB_INTR, printk("UNEXP_DISC-%ld", cmd->pid)) + DB(DB_INTR, printk("UNEXP_DISC-%ld", cmd->serial_number)) hostdata->connected = NULL; hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); hostdata->state = S_UNCONNECTED; @@ -1292,7 +1292,7 @@ wd33c93_intr(struct Scsi_Host *instance) */ write_wd33c93(regs, WD_SOURCE_ID, SRCID_ER); - DB(DB_INTR, printk("DISC-%ld", cmd->pid)) + DB(DB_INTR, printk("DISC-%ld", cmd->serial_number)) if (cmd == NULL) { printk(" - Already disconnected! "); hostdata->state = S_UNCONNECTED; @@ -1491,7 +1491,7 @@ wd33c93_intr(struct Scsi_Host *instance) } else hostdata->state = S_CONNECTED; - DB(DB_INTR, printk("-%ld", cmd->pid)) + DB(DB_INTR, printk("-%ld", cmd->serial_number)) spin_unlock_irqrestore(&hostdata->lock, flags); break; @@ -1638,7 +1638,7 @@ wd33c93_abort(struct scsi_cmnd * cmd) cmd->result = DID_ABORT << 16; printk ("scsi%d: Abort - removing command %ld from input_Q. ", - instance->host_no, cmd->pid); + instance->host_no, cmd->serial_number); enable_irq(cmd->device->host->irq); cmd->scsi_done(cmd); return SUCCESS; @@ -1663,7 +1663,7 @@ wd33c93_abort(struct scsi_cmnd * cmd) unsigned long timeout; printk("scsi%d: Aborting connected command %ld - ", - instance->host_no, cmd->pid); + instance->host_no, cmd->serial_number); printk("stopping DMA - "); if (hostdata->dma == D_DMA_RUNNING) { @@ -1730,7 +1730,7 @@ wd33c93_abort(struct scsi_cmnd * cmd) if (tmp == cmd) { printk ("scsi%d: Abort - command %ld found on disconnected_Q - ", - instance->host_no, cmd->pid); + instance->host_no, cmd->serial_number); printk("Abort SNOOZE. "); enable_irq(cmd->device->host->irq); return FAILED; @@ -2184,7 +2184,7 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off if (hd->connected) { cmd = (struct scsi_cmnd *) hd->connected; sprintf(tbuf, " %ld-%d:%d(%02x)", - cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); strcat(bp, tbuf); } } @@ -2193,7 +2193,7 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off cmd = (struct scsi_cmnd *) hd->input_Q; while (cmd) { sprintf(tbuf, " %ld-%d:%d(%02x)", - cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); strcat(bp, tbuf); cmd = (struct scsi_cmnd *) cmd->host_scribble; } @@ -2203,7 +2203,7 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off cmd = (struct scsi_cmnd *) hd->disconnected_Q; while (cmd) { sprintf(tbuf, " %ld-%d:%d(%02x)", - cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); strcat(bp, tbuf); cmd = (struct scsi_cmnd *) cmd->host_scribble; } diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 53e170586c26..4fddef727467 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -39,14 +39,12 @@ struct scsi_cmnd { * A SCSI Command is assigned a nonzero serial_number before passed * to the driver's queue command function. The serial_number is * cleared when scsi_done is entered indicating that the command - * has been completed. It currently doesn't have much use other - * than printk's. Some lldd's use this number for other purposes. - * It's almost certain that such usages are either incorrect or - * meaningless. Please kill all usages other than printk's. Also, - * as this number is always identical to ->pid, please convert - * printk's to use ->pid, so that we can kill this field. + * has been completed. It is a bug for LLDDs to use this number + * for purposes other than printk (and even that is only useful + * for debugging). */ unsigned long serial_number; + /* * This is set to jiffies as it was when the command was first * allocated. It is used to time how long the command has @@ -116,7 +114,6 @@ struct scsi_cmnd { int result; /* Status code from lower level driver */ unsigned char tag; /* SCSI-II queued command tag */ - unsigned long pid; /* Process ID, starts at 0. Unique per host. */ }; extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t); diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 5b79697a3a80..7d210cd6c38d 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -580,7 +580,7 @@ struct Scsi_Host { * Used to assign serial numbers to the cmds. * Protected by the host lock. */ - unsigned long cmd_serial_number, cmd_pid; + unsigned long cmd_serial_number; unsigned active_mode:2; unsigned unchecked_isa_dma:1; -- cgit v1.2.3 From 311b581e1d87be87f78e6e17fc50f468f2dec561 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 23 Sep 2007 09:08:46 -0500 Subject: [SCSI] Fix device not ready printk Because scsi_print_sense_hdr prefixes with KERN_INFO, the output from scsi_io_completion looks like: sd 0:0:0:0: [sdb] Device not ready: <6>: Sense Key : 0x2 [current] : ASC=0x4 ASCQ=0x3 By using scsi_show_sense_hdr, we can get the much more appealing output: sd 0:0:0:0: [sdb] Device not ready: Sense Key : 0x2 [current] sd 0:0:0:0: [sdb] Device not ready: ASC=0x4 ASCQ=0x3 Acked-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/constants.c | 14 ++++++++++++++ drivers/scsi/scsi_lib.c | 10 +++++----- include/scsi/scsi_dbg.h | 2 ++ 3 files changed, 21 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 7bdeed1c5a56..024553f9c247 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -1235,6 +1235,20 @@ scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr) } EXPORT_SYMBOL(scsi_print_sense_hdr); +/* + * Print normalized SCSI sense header with device information and a prefix. + */ +void +scsi_cmd_print_sense_hdr(struct scsi_cmnd *scmd, const char *desc, + struct scsi_sense_hdr *sshdr) +{ + scmd_printk(KERN_INFO, scmd, "%s: ", desc); + scsi_show_sense_hdr(sshdr); + scmd_printk(KERN_INFO, scmd, "%s: ", desc); + scsi_show_extd_sense(sshdr->asc, sshdr->ascq); +} +EXPORT_SYMBOL(scsi_cmd_print_sense_hdr); + static void scsi_decode_sense_buffer(const unsigned char *sense_buffer, int sense_len, struct scsi_sense_hdr *sshdr) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 94d82cb96626..86fd3abe731a 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -944,11 +944,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) break; } } - if (!(req->cmd_flags & REQ_QUIET)) { - scmd_printk(KERN_INFO, cmd, - "Device not ready: "); - scsi_print_sense_hdr("", &sshdr); - } + if (!(req->cmd_flags & REQ_QUIET)) + scsi_cmd_print_sense_hdr(cmd, + "Device not ready", + &sshdr); + scsi_end_request(cmd, 0, this_count, 1); return; case VOLUME_OVERFLOW: diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h index 5a43a4cd96c6..e89844cc2cd3 100644 --- a/include/scsi/scsi_dbg.h +++ b/include/scsi/scsi_dbg.h @@ -9,6 +9,8 @@ extern void __scsi_print_command(unsigned char *); extern void scsi_show_extd_sense(unsigned char, unsigned char); extern void scsi_show_sense_hdr(struct scsi_sense_hdr *); extern void scsi_print_sense_hdr(const char *, struct scsi_sense_hdr *); +extern void scsi_cmd_print_sense_hdr(struct scsi_cmnd *, const char *, + struct scsi_sense_hdr *); extern void scsi_print_sense(char *, struct scsi_cmnd *); extern void __scsi_print_sense(const char *name, const unsigned char *sense_buffer, -- cgit v1.2.3 From 6f5391c283d7fdcf24bf40786ea79061919d1e1d Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 25 Sep 2007 12:42:04 -0400 Subject: [SCSI] Get rid of scsi_cmnd->done The ULD ->done callback moves into the scsi_driver. By moving the call to scsi_io_completion() from scsi_blk_pc_done() to scsi_finish_command(), we can eliminate the latter entirely. By returning 'good_bytes' from the ->done callback (rather than invoking scsi_io_completion()), we can stop exporting scsi_io_completion(). Also move the prototypes from sd.h to sd.c as they're all internal anyway. Rename sd_rw_intr to sd_done and rw_intr to sr_done. Inspired-by: Christoph Hellwig Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/scsi.c | 20 +++++++++++++++++--- drivers/scsi/scsi_error.c | 1 - drivers/scsi/scsi_lib.c | 14 -------------- drivers/scsi/scsi_priv.h | 1 + drivers/scsi/sd.c | 28 ++++++++++++++++++---------- drivers/scsi/sr.c | 21 ++++++--------------- include/scsi/scsi_cmnd.h | 2 -- include/scsi/scsi_driver.h | 1 + include/scsi/sd.h | 13 ------------- 9 files changed, 43 insertions(+), 58 deletions(-) (limited to 'include') diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 07a7c2a70a3f..192948822455 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -367,9 +368,8 @@ void scsi_log_send(struct scsi_cmnd *cmd) scsi_print_command(cmd); if (level > 3) { printk(KERN_INFO "buffer = 0x%p, bufflen = %d," - " done = 0x%p, queuecommand 0x%p\n", + " queuecommand 0x%p\n", scsi_sglist(cmd), scsi_bufflen(cmd), - cmd->done, cmd->device->host->hostt->queuecommand); } @@ -654,6 +654,12 @@ void __scsi_done(struct scsi_cmnd *cmd) blk_complete_request(rq); } +/* Move this to a header if it becomes more generally useful */ +static struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd) +{ + return *(struct scsi_driver **)cmd->request->rq_disk->private_data; +} + /* * Function: scsi_finish_command * @@ -665,6 +671,8 @@ void scsi_finish_command(struct scsi_cmnd *cmd) { struct scsi_device *sdev = cmd->device; struct Scsi_Host *shost = sdev->host; + struct scsi_driver *drv; + unsigned int good_bytes; scsi_device_unbusy(sdev); @@ -690,7 +698,13 @@ void scsi_finish_command(struct scsi_cmnd *cmd) "Notifying upper driver of completion " "(result %x)\n", cmd->result)); - cmd->done(cmd); + good_bytes = cmd->request_bufflen; + if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) { + drv = scsi_cmd_to_driver(cmd); + if (drv->done) + good_bytes = drv->done(cmd); + } + scsi_io_completion(cmd, good_bytes); } EXPORT_SYMBOL(scsi_finish_command); diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 44e6721ddea6..f49feb9351d0 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1671,7 +1671,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag) memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd)); scmd->scsi_done = scsi_reset_provider_done_command; - scmd->done = NULL; scmd->request_buffer = NULL; scmd->request_bufflen = 0; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 86fd3abe731a..fac34293bef7 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -982,7 +982,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) } scsi_end_request(cmd, 0, this_count, !result); } -EXPORT_SYMBOL(scsi_io_completion); /* * Function: scsi_init_io() @@ -1063,18 +1062,6 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev, return cmd; } -static void scsi_blk_pc_done(struct scsi_cmnd *cmd) -{ - BUG_ON(!blk_pc_request(cmd->request)); - /* - * This will complete the whole command with uptodate=1 so - * as far as the block layer is concerned the command completed - * successfully. Since this is a REQ_BLOCK_PC command the - * caller should check the request's errors value - */ - scsi_io_completion(cmd, cmd->request_bufflen); -} - int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) { struct scsi_cmnd *cmd; @@ -1124,7 +1111,6 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) cmd->transfersize = req->data_len; cmd->allowed = req->retries; cmd->timeout_per_command = req->timeout; - cmd->done = scsi_blk_pc_done; return BLKPREP_OK; } EXPORT_SYMBOL(scsi_setup_blk_pc_cmnd); diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index ee8efe849bf4..eff005951895 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -68,6 +68,7 @@ extern int scsi_maybe_unblock_host(struct scsi_device *sdev); extern void scsi_device_unbusy(struct scsi_device *sdev); extern int scsi_queue_insert(struct scsi_cmnd *cmd, int reason); extern void scsi_next_command(struct scsi_cmnd *cmd); +extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); extern void scsi_run_host_queues(struct Scsi_Host *shost); extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev); extern void scsi_free_queue(struct request_queue *q); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 38a41415004b..0a3a528212c2 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -86,6 +86,19 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_DISK); MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD); MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); +static int sd_revalidate_disk(struct gendisk *); +static int sd_probe(struct device *); +static int sd_remove(struct device *); +static void sd_shutdown(struct device *); +static int sd_suspend(struct device *, pm_message_t state); +static int sd_resume(struct device *); +static void sd_rescan(struct device *); +static int sd_done(struct scsi_cmnd *); +static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer); +static void scsi_disk_release(struct class_device *cdev); +static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); +static void sd_print_result(struct scsi_disk *, int); + static DEFINE_IDR(sd_index_idr); static DEFINE_SPINLOCK(sd_index_lock); @@ -240,6 +253,7 @@ static struct scsi_driver sd_template = { .shutdown = sd_shutdown, }, .rescan = sd_rescan, + .done = sd_done, }; /* @@ -508,12 +522,6 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) SCpnt->allowed = SD_MAX_RETRIES; SCpnt->timeout_per_command = timeout; - /* - * This is the completion routine we use. This is matched in terms - * of capability to this function. - */ - SCpnt->done = sd_rw_intr; - /* * This indicates that the command is ready from our end to be * queued. @@ -908,13 +916,13 @@ static struct block_device_operations sd_fops = { }; /** - * sd_rw_intr - bottom half handler: called when the lower level + * sd_done - bottom half handler: called when the lower level * driver has completed (successfully or otherwise) a scsi command. * @SCpnt: mid-level's per command structure. * * Note: potentially run from within an ISR. Must not block. **/ -static void sd_rw_intr(struct scsi_cmnd * SCpnt) +static int sd_done(struct scsi_cmnd *SCpnt) { int result = SCpnt->result; unsigned int xfer_size = SCpnt->request_bufflen; @@ -935,7 +943,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) SCSI_LOG_HLCOMPLETE(1, scsi_print_result(SCpnt)); if (sense_valid) { SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt, - "sd_rw_intr: sb[respc,sk,asc," + "sd_done: sb[respc,sk,asc," "ascq]=%x,%x,%x,%x\n", sshdr.response_code, sshdr.sense_key, sshdr.asc, @@ -1007,7 +1015,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) break; } out: - scsi_io_completion(SCpnt, good_bytes); + return good_bytes; } static int media_not_present(struct scsi_disk *sdkp, diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index a0c4e13d4dab..c61999031141 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -78,6 +78,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM); static int sr_probe(struct device *); static int sr_remove(struct device *); +static int sr_done(struct scsi_cmnd *); static struct scsi_driver sr_template = { .owner = THIS_MODULE, @@ -86,6 +87,7 @@ static struct scsi_driver sr_template = { .probe = sr_probe, .remove = sr_remove, }, + .done = sr_done, }; static unsigned long sr_index_bits[SR_DISKS / BITS_PER_LONG]; @@ -208,12 +210,12 @@ static int sr_media_change(struct cdrom_device_info *cdi, int slot) } /* - * rw_intr is the interrupt routine for the device driver. + * sr_done is the interrupt routine for the device driver. * - * It will be notified on the end of a SCSI read / write, and will take on + * It will be notified on the end of a SCSI read / write, and will take one * of several actions based on success or failure. */ -static void rw_intr(struct scsi_cmnd * SCpnt) +static int sr_done(struct scsi_cmnd *SCpnt) { int result = SCpnt->result; int this_count = SCpnt->request_bufflen; @@ -286,12 +288,7 @@ static void rw_intr(struct scsi_cmnd * SCpnt) } } - /* - * This calls the generic completion function, now that we know - * how many actual sectors finished, and how many sectors we need - * to say have failed. - */ - scsi_io_completion(SCpnt, good_bytes); + return good_bytes; } static int sr_prep_fn(struct request_queue *q, struct request *rq) @@ -427,12 +424,6 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) SCpnt->allowed = MAX_RETRIES; SCpnt->timeout_per_command = timeout; - /* - * This is the completion routine we use. This is matched in terms - * of capability to this function. - */ - SCpnt->done = rw_intr; - /* * This indicates that the command is ready from our end to be * queued. diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 4fddef727467..65ab5145a09b 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -33,7 +33,6 @@ struct scsi_cmnd { struct list_head list; /* scsi_cmnd participates in queue lists */ struct list_head eh_entry; /* entry for the host eh_cmd_q */ int eh_eflags; /* Used by error handlr */ - void (*done) (struct scsi_cmnd *); /* Mid-level done function */ /* * A SCSI Command is assigned a nonzero serial_number before passed @@ -121,7 +120,6 @@ extern struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *, gfp_t); extern void scsi_put_command(struct scsi_cmnd *); extern void __scsi_put_command(struct Scsi_Host *, struct scsi_cmnd *, struct device *); -extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); extern void scsi_finish_command(struct scsi_cmnd *cmd); extern void scsi_req_abort_cmd(struct scsi_cmnd *cmd); diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h index 56a304709fde..1f5ca7f62116 100644 --- a/include/scsi/scsi_driver.h +++ b/include/scsi/scsi_driver.h @@ -15,6 +15,7 @@ struct scsi_driver { struct device_driver gendrv; void (*rescan)(struct device *); + int (*done)(struct scsi_cmnd *); }; #define to_scsi_driver(drv) \ container_of((drv), struct scsi_driver, gendrv) diff --git a/include/scsi/sd.h b/include/scsi/sd.h index aa1e71613010..f7513313ef0d 100644 --- a/include/scsi/sd.h +++ b/include/scsi/sd.h @@ -47,19 +47,6 @@ struct scsi_disk { }; #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,cdev) -static int sd_revalidate_disk(struct gendisk *disk); -static void sd_rw_intr(struct scsi_cmnd * SCpnt); -static int sd_probe(struct device *); -static int sd_remove(struct device *); -static void sd_shutdown(struct device *dev); -static int sd_suspend(struct device *dev, pm_message_t state); -static int sd_resume(struct device *dev); -static void sd_rescan(struct device *); -static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer); -static void scsi_disk_release(struct class_device *cdev); -static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); -static void sd_print_result(struct scsi_disk *, int); - #define sd_printk(prefix, sdsk, fmt, a...) \ (sdsk)->disk ? \ sdev_printk(prefix, (sdsk)->device, "[%s] " fmt, \ -- cgit v1.2.3 From d773c082da27c445c832324cfb4a357498613a38 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Tue, 2 Oct 2007 14:38:05 -0700 Subject: [SCSI] scsi_transport_iscsi: add list, mutex includes scsi/scsi_transport_iscsi.h uses struct mutex and struct list_head, so while linux/mutex.h and linux/list.h seem to be pulled in indirectly by one of the headers it includes, the right thing is to include linux/mutex.h and linus/list.h directly. Signed-off-by: Michael S. Tsirkin Acked-by: Mike Christie Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- include/scsi/scsi_transport_iscsi.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 706c0cd36c14..7ff6199cbd55 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -24,6 +24,8 @@ #define SCSI_TRANSPORT_ISCSI_H #include +#include +#include #include struct scsi_transport_template; -- cgit v1.2.3 From e1c234685c50807e10a3e7873e6e006976a4d8e8 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Mon, 8 Oct 2007 16:36:45 +0200 Subject: [SCSI] scsi_error: Refactoring scsi_error to facilitate in synchronous REQUEST_SENSE - Drivers/transports that want to send a synchronous REQUEST_SENSE command as part of their .queuecommand sequence, have 2 new API's that facilitate in doing so and abstract them from scsi-ml internals. void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *sesci, unsigned char *cmnd, int cmnd_size, int sense_bytes) Will hijack a command and prepare it for request sense if needed. And will save any later needed info into a scsi_eh_save structure. void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *sesci); Will undo any changes done to a command by above function. Making it ready for completion. - Re-factor scsi_send_eh_cmnd() to use above APIs Signed-off-by: Boaz Harrosh Signed-off-by: James Bottomley --- drivers/scsi/scsi_error.c | 114 +++++++++++++++++++++++++++------------------- include/scsi/scsi_eh.h | 23 +++++++++- 2 files changed, 90 insertions(+), 47 deletions(-) (limited to 'include') diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 4d535019e04b..d29f8464b74f 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -590,42 +590,23 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd) } /** - * scsi_send_eh_cmnd - submit a scsi command as part of error recory + * scsi_eh_prep_cmnd - Save a scsi command info as part of error recory * @scmd: SCSI command structure to hijack + * @ses: structure to save restore information * @cmnd: CDB to send. Can be NULL if no new cmnd is needed * @cmnd_size: size in bytes of @cmnd - * @timeout: timeout for this request * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored) * - * This function is used to send a scsi command down to a target device + * This function is used to save a scsi command information before re-execution * as part of the error recovery process. If @sense_bytes is 0 the command * sent must be one that does not transfer any data. If @sense_bytes != 0 * @cmnd is ignored and this functions sets up a REQUEST_SENSE command * and cmnd buffers to read @sense_bytes into @scmd->sense_buffer. - * - * Return value: - * SUCCESS or FAILED or NEEDS_RETRY **/ -static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, - int cmnd_size, int timeout, unsigned sense_bytes) +void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, + unsigned char *cmnd, int cmnd_size, unsigned sense_bytes) { struct scsi_device *sdev = scmd->device; - struct Scsi_Host *shost = sdev->host; - DECLARE_COMPLETION_ONSTACK(done); - unsigned long timeleft; - unsigned long flags; - - unsigned char old_cmd_len; - unsigned char old_cmnd[MAX_COMMAND_SIZE]; - enum dma_data_direction old_data_direction; - unsigned old_bufflen; - void *old_buffer; - unsigned short old_use_sg; - int old_resid; - int old_result; - - struct scatterlist sgl; - int rtn; /* * We need saved copies of a number of fields - this is because @@ -634,20 +615,21 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, * we will need to restore these values prior to running the actual * command. */ - old_cmd_len = scmd->cmd_len; - memcpy(old_cmnd, scmd->cmnd, sizeof(scmd->cmnd)); - old_data_direction = scmd->sc_data_direction; - old_bufflen = scmd->request_bufflen; - old_buffer = scmd->request_buffer; - old_use_sg = scmd->use_sg; - old_resid = scmd->resid; - old_result = scmd->result; + ses->cmd_len = scmd->cmd_len; + memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd)); + ses->data_direction = scmd->sc_data_direction; + ses->bufflen = scmd->request_bufflen; + ses->buffer = scmd->request_buffer; + ses->use_sg = scmd->use_sg; + ses->resid = scmd->resid; + ses->result = scmd->result; if (sense_bytes) { scmd->request_bufflen = min_t(unsigned, sizeof(scmd->sense_buffer), sense_bytes); - sg_init_one(&sgl, scmd->sense_buffer, scmd->request_bufflen); - scmd->request_buffer = &sgl; + sg_init_one(&ses->sense_sgl, scmd->sense_buffer, + scmd->request_bufflen); + scmd->request_buffer = &ses->sense_sgl; scmd->sc_data_direction = DMA_FROM_DEVICE; scmd->use_sg = 1; memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); @@ -677,7 +659,58 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, * untransferred sense data should be interpreted as being zero. */ memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer)); +} +EXPORT_SYMBOL(scsi_eh_prep_cmnd); + +/** + * scsi_eh_restore_cmnd - Restore a scsi command info as part of error recory + * @scmd: SCSI command structure to restore + * @ses: saved information from a coresponding call to scsi_prep_eh_cmnd + * + * Undo any damage done by above scsi_prep_eh_cmnd(). + **/ +void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses) +{ + /* + * Restore original data + */ + scmd->cmd_len = ses->cmd_len; + memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd)); + scmd->sc_data_direction = ses->data_direction; + scmd->request_bufflen = ses->bufflen; + scmd->request_buffer = ses->buffer; + scmd->use_sg = ses->use_sg; + scmd->resid = ses->resid; + scmd->result = ses->result; +} +EXPORT_SYMBOL(scsi_eh_restore_cmnd); +/** + * scsi_send_eh_cmnd - submit a scsi command as part of error recory + * @scmd: SCSI command structure to hijack + * @cmnd: CDB to send + * @cmnd_size: size in bytes of @cmnd + * @timeout: timeout for this request + * @sense_bytes: size of sense data to copy or 0 + * + * This function is used to send a scsi command down to a target device + * as part of the error recovery process. See also scsi_eh_prep_cmnd() above. + * + * Return value: + * SUCCESS or FAILED or NEEDS_RETRY + **/ +static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, + int cmnd_size, int timeout, unsigned sense_bytes) +{ + struct scsi_device *sdev = scmd->device; + struct Scsi_Host *shost = sdev->host; + DECLARE_COMPLETION_ONSTACK(done); + unsigned long timeleft; + unsigned long flags; + struct scsi_eh_save ses; + int rtn; + + scsi_eh_prep_cmnd(scmd, &ses, cmnd, cmnd_size, sense_bytes); shost->eh_action = &done; spin_lock_irqsave(shost->host_lock, flags); @@ -721,18 +754,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, rtn = FAILED; } - - /* - * Restore original data - */ - scmd->cmd_len = old_cmd_len; - memcpy(scmd->cmnd, old_cmnd, sizeof(scmd->cmnd)); - scmd->sc_data_direction = old_data_direction; - scmd->request_bufflen = old_bufflen; - scmd->request_buffer = old_buffer; - scmd->use_sg = old_use_sg; - scmd->resid = old_resid; - scmd->result = old_result; + scsi_eh_restore_cmnd(scmd, &ses); return rtn; } diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index c5c0f6762a01..44224ba4dd90 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -1,7 +1,7 @@ #ifndef _SCSI_SCSI_EH_H #define _SCSI_SCSI_EH_H -struct scsi_cmnd; +#include struct scsi_device; struct Scsi_Host; @@ -65,4 +65,25 @@ extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len, extern int scsi_reset_provider(struct scsi_device *, int); +struct scsi_eh_save { + int result; + enum dma_data_direction data_direction; + unsigned char cmd_len; + unsigned char cmnd[MAX_COMMAND_SIZE]; + + void *buffer; + unsigned bufflen; + unsigned short use_sg; + int resid; + + struct scatterlist sense_sgl; +}; + +extern void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, + struct scsi_eh_save *ses, unsigned char *cmnd, + int cmnd_size, unsigned sense_bytes); + +extern void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, + struct scsi_eh_save *ses); + #endif /* _SCSI_SCSI_EH_H */ -- cgit v1.2.3