Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 253021 Details for
Bug 318521
iscsi fixes needed against 2.6.21 realtime kernel
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Upstream ISCSI fixes backported to 2.6.21-rt kernel
iscsi-driver-backport.patch (text/plain), 193.15 KB, created by
Clark Williams
on 2007-11-09 16:45:09 UTC
(
hide
)
Description:
Upstream ISCSI fixes backported to 2.6.21-rt kernel
Filename:
MIME Type:
Creator:
Clark Williams
Created:
2007-11-09 16:45:09 UTC
Size:
193.15 KB
patch
obsolete
>From: Mike Christie <mchristi@redhat.com> > > This is for BZ 318521. > > This patch was made against the rt kernel in cvs based on 2.6.21. It > basically syncs up those iscsi drivers with upstream (a lot of patches > that went into RHEL5.1 went into 2.6.22, .23, .24 or are in the iscsi > tree to be sent to the scsi maintainer when the .25 feature window > opens). > > >diff -aurp linux-2.6.21.noarch/drivers/infiniband/ulp/iser/iscsi_iser.c linux-2.6.21.noarch.iscsi2/drivers/infiniband/ulp/iser/iscsi_iser.c >--- linux-2.6.21.noarch/drivers/infiniband/ulp/iser/iscsi_iser.c 2007-10-22 10:47:07.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/infiniband/ulp/iser/iscsi_iser.c 2007-10-24 22:26:00.000000000 -0500 >@@ -140,8 +140,6 @@ iscsi_iser_cmd_init(struct iscsi_cmd_tas > iser_ctask->iser_conn = iser_conn; > > if (sc->sc_data_direction == DMA_TO_DEVICE) { >- BUG_ON(ctask->total_length == 0); >- > debug_scsi("cmd [itt %x total %d imm %d unsol_data %d\n", > ctask->itt, ctask->total_length, ctask->imm_count, > ctask->unsol_count); >@@ -222,12 +220,6 @@ iscsi_iser_ctask_xmit(struct iscsi_conn > debug_scsi("ctask deq [cid %d itt 0x%x]\n", > conn->id, ctask->itt); > >- /* >- * serialize with TMF AbortTask >- */ >- if (ctask->mtask) >- return error; >- > /* Send the cmd PDU */ > if (!iser_ctask->command_sent) { > error = iser_send_command(conn, ctask); >@@ -375,7 +367,8 @@ static struct iscsi_transport iscsi_iser > static struct iscsi_cls_session * > iscsi_iser_session_create(struct iscsi_transport *iscsit, > struct scsi_transport_template *scsit, >- uint32_t initial_cmdsn, uint32_t *hostno) >+ uint16_t cmds_max, uint16_t qdepth, >+ uint32_t initial_cmdsn, uint32_t *hostno) > { > struct iscsi_cls_session *cls_session; > struct iscsi_session *session; >@@ -386,7 +379,13 @@ iscsi_iser_session_create(struct iscsi_t > struct iscsi_iser_cmd_task *iser_ctask; > struct iser_desc *desc; > >+ /* >+ * we do not support setting can_queue cmd_per_lun from userspace yet >+ * because we preallocate so many resources >+ */ > cls_session = iscsi_session_setup(iscsit, scsit, >+ ISCSI_DEF_XMIT_CMDS_MAX, >+ ISCSI_MAX_CMD_PER_LUN, > sizeof(struct iscsi_iser_cmd_task), > sizeof(struct iser_desc), > initial_cmdsn, &hn); >@@ -543,9 +542,10 @@ iscsi_iser_ep_disconnect(__u64 ep_handle > } > > static struct scsi_host_template iscsi_iser_sht = { >+ .module = THIS_MODULE, > .name = "iSCSI Initiator over iSER, v." DRV_VER, > .queuecommand = iscsi_queuecommand, >- .can_queue = ISCSI_XMIT_CMDS_MAX - 1, >+ .can_queue = ISCSI_DEF_XMIT_CMDS_MAX - 1, > .sg_tablesize = ISCSI_ISER_SG_TABLESIZE, > .max_sectors = 1024, > .cmd_per_lun = ISCSI_MAX_CMD_PER_LUN, >@@ -574,8 +574,13 @@ static struct iscsi_transport iscsi_iser > ISCSI_EXP_STATSN | > ISCSI_PERSISTENT_PORT | > ISCSI_PERSISTENT_ADDRESS | >- ISCSI_TARGET_NAME | >- ISCSI_TPGT, >+ ISCSI_TARGET_NAME | ISCSI_TPGT, >+ ISCSI_USERNAME | ISCSI_PASSWORD | >+ ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN | >+ ISCSI_FAST_ABORT, >+ .host_param_mask = ISCSI_HOST_HWADDRESS | >+ ISCSI_HOST_NETDEV_NAME | >+ ISCSI_HOST_INITIATOR_NAME, > .host_template = &iscsi_iser_sht, > .conndata_size = sizeof(struct iscsi_conn), > .max_lun = ISCSI_ISER_MAX_LUN, >@@ -592,6 +597,9 @@ static struct iscsi_transport iscsi_iser > .get_session_param = iscsi_session_get_param, > .start_conn = iscsi_iser_conn_start, > .stop_conn = iscsi_conn_stop, >+ /* iscsi host params */ >+ .get_host_param = iscsi_host_get_param, >+ .set_host_param = iscsi_host_set_param, > /* IO */ > .send_pdu = iscsi_conn_send_pdu, > .get_stats = iscsi_iser_conn_get_stats, >diff -aurp linux-2.6.21.noarch/drivers/infiniband/ulp/iser/iscsi_iser.h linux-2.6.21.noarch.iscsi2/drivers/infiniband/ulp/iser/iscsi_iser.h >--- linux-2.6.21.noarch/drivers/infiniband/ulp/iser/iscsi_iser.h 2007-10-22 10:47:07.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/infiniband/ulp/iser/iscsi_iser.h 2007-10-24 22:26:00.000000000 -0500 >@@ -98,7 +98,7 @@ > #define ISER_MAX_TX_MISC_PDUS 6 /* NOOP_OUT(2), TEXT(1), * > * SCSI_TMFUNC(2), LOGOUT(1) */ > >-#define ISER_QP_MAX_RECV_DTOS (ISCSI_XMIT_CMDS_MAX + \ >+#define ISER_QP_MAX_RECV_DTOS (ISCSI_DEF_XMIT_CMDS_MAX + \ > ISER_MAX_RX_MISC_PDUS + \ > ISER_MAX_TX_MISC_PDUS) > >@@ -110,7 +110,7 @@ > > #define ISER_INFLIGHT_DATAOUTS 8 > >-#define ISER_QP_MAX_REQ_DTOS (ISCSI_XMIT_CMDS_MAX * \ >+#define ISER_QP_MAX_REQ_DTOS (ISCSI_DEF_XMIT_CMDS_MAX * \ > (1 + ISER_INFLIGHT_DATAOUTS) + \ > ISER_MAX_TX_MISC_PDUS + \ > ISER_MAX_RX_MISC_PDUS) >@@ -310,8 +310,6 @@ int iser_conn_init(struct iser_conn **i > > void iser_conn_terminate(struct iser_conn *ib_conn); > >-void iser_conn_release(struct iser_conn *ib_conn); >- > void iser_rcv_completion(struct iser_desc *desc, > unsigned long dto_xfer_len); > >@@ -329,9 +327,6 @@ void iser_reg_single(struct iser_device > struct iser_regd_buf *regd_buf, > enum dma_data_direction direction); > >-int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *ctask, >- enum iser_data_dir cmd_dir); >- > void iser_finalize_rdma_unaligned_sg(struct iscsi_iser_cmd_task *ctask, > enum iser_data_dir cmd_dir); > >diff -aurp linux-2.6.21.noarch/drivers/infiniband/ulp/iser/iser_initiator.c linux-2.6.21.noarch.iscsi2/drivers/infiniband/ulp/iser/iser_initiator.c >--- linux-2.6.21.noarch/drivers/infiniband/ulp/iser/iser_initiator.c 2007-10-22 10:47:07.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/infiniband/ulp/iser/iser_initiator.c 2007-10-24 22:26:00.000000000 -0500 >@@ -34,8 +34,6 @@ > #include <linux/kernel.h> > #include <linux/slab.h> > #include <linux/mm.h> >-#include <asm/io.h> >-#include <asm/scatterlist.h> > #include <linux/scatterlist.h> > #include <linux/kfifo.h> > #include <scsi/scsi_cmnd.h> >@@ -201,7 +199,7 @@ static int iser_post_receive_control(str > * what's common for both schemes is that the connection is not started > */ > if (conn->c_stage != ISCSI_CONN_STARTED) >- rx_data_size = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; >+ rx_data_size = ISCSI_DEF_MAX_RECV_SEG_LEN; > else /* FIXME till user space sets conn->max_recv_dlength correctly */ > rx_data_size = 128; > >@@ -567,7 +565,7 @@ void iser_rcv_completion(struct iser_des > opcode = hdr->opcode & ISCSI_OPCODE_MASK; > > if (opcode == ISCSI_OP_SCSI_CMD_RSP) { >- itt = hdr->itt & ISCSI_ITT_MASK; /* mask out cid and age bits */ >+ itt = get_itt(hdr->itt); /* mask out cid and age bits */ > if (!(itt < session->cmds_max)) > iser_err("itt can't be matched to task!!!" > "conn %p opcode %d cmds_max %d itt %d\n", >diff -aurp linux-2.6.21.noarch/drivers/infiniband/ulp/iser/iser_memory.c linux-2.6.21.noarch.iscsi2/drivers/infiniband/ulp/iser/iser_memory.c >--- linux-2.6.21.noarch/drivers/infiniband/ulp/iser/iser_memory.c 2007-10-22 10:47:07.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/infiniband/ulp/iser/iser_memory.c 2007-10-24 22:26:00.000000000 -0500 >@@ -36,8 +36,6 @@ > #include <linux/slab.h> > #include <linux/mm.h> > #include <linux/highmem.h> >-#include <asm/io.h> >-#include <asm/scatterlist.h> > #include <linux/scatterlist.h> > > #include "iscsi_iser.h" >@@ -103,8 +101,8 @@ void iser_reg_single(struct iser_device > /** > * iser_start_rdma_unaligned_sg > */ >-int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, >- enum iser_data_dir cmd_dir) >+static int iser_start_rdma_unaligned_sg(struct iscsi_iser_cmd_task *iser_ctask, >+ enum iser_data_dir cmd_dir) > { > int dma_nents; > struct ib_device *dev; >diff -aurp linux-2.6.21.noarch/drivers/infiniband/ulp/iser/iser_verbs.c linux-2.6.21.noarch.iscsi2/drivers/infiniband/ulp/iser/iser_verbs.c >--- linux-2.6.21.noarch/drivers/infiniband/ulp/iser/iser_verbs.c 2007-10-22 10:47:07.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/infiniband/ulp/iser/iser_verbs.c 2007-10-24 22:26:00.000000000 -0500 >@@ -32,10 +32,8 @@ > * > * $Id: iser_verbs.c 7051 2006-05-10 12:29:11Z ogerlitz $ > */ >-#include <asm/io.h> > #include <linux/kernel.h> > #include <linux/module.h> >-#include <linux/smp_lock.h> > #include <linux/delay.h> > #include <linux/version.h> > >@@ -156,8 +154,8 @@ static int iser_create_ib_conn_res(struc > params.max_pages_per_fmr = ISCSI_ISER_SG_TABLESIZE + 1; > /* make the pool size twice the max number of SCSI commands * > * the ML is expected to queue, watermark for unmap at 50% */ >- params.pool_size = ISCSI_XMIT_CMDS_MAX * 2; >- params.dirty_watermark = ISCSI_XMIT_CMDS_MAX; >+ params.pool_size = ISCSI_DEF_XMIT_CMDS_MAX * 2; >+ params.dirty_watermark = ISCSI_DEF_XMIT_CMDS_MAX; > params.cache = 0; > params.flush_function = NULL; > params.access = (IB_ACCESS_LOCAL_WRITE | >@@ -312,6 +310,29 @@ static int iser_conn_state_comp_exch(str > } > > /** >+ * Frees all conn objects and deallocs conn descriptor >+ */ >+static void iser_conn_release(struct iser_conn *ib_conn) >+{ >+ struct iser_device *device = ib_conn->device; >+ >+ BUG_ON(ib_conn->state != ISER_CONN_DOWN); >+ >+ mutex_lock(&ig.connlist_mutex); >+ list_del(&ib_conn->conn_list); >+ mutex_unlock(&ig.connlist_mutex); >+ >+ iser_free_ib_conn_res(ib_conn); >+ ib_conn->device = NULL; >+ /* on EVENT_ADDR_ERROR there's no device yet for this conn */ >+ if (device != NULL) >+ iser_device_try_release(device); >+ if (ib_conn->iser_conn) >+ ib_conn->iser_conn->ib_conn = NULL; >+ kfree(ib_conn); >+} >+ >+/** > * triggers start of the disconnect procedures and wait for them to be done > */ > void iser_conn_terminate(struct iser_conn *ib_conn) >@@ -551,30 +572,6 @@ connect_failure: > } > > /** >- * Frees all conn objects and deallocs conn descriptor >- */ >-void iser_conn_release(struct iser_conn *ib_conn) >-{ >- struct iser_device *device = ib_conn->device; >- >- BUG_ON(ib_conn->state != ISER_CONN_DOWN); >- >- mutex_lock(&ig.connlist_mutex); >- list_del(&ib_conn->conn_list); >- mutex_unlock(&ig.connlist_mutex); >- >- iser_free_ib_conn_res(ib_conn); >- ib_conn->device = NULL; >- /* on EVENT_ADDR_ERROR there's no device yet for this conn */ >- if (device != NULL) >- iser_device_try_release(device); >- if (ib_conn->iser_conn) >- ib_conn->iser_conn->ib_conn = NULL; >- kfree(ib_conn); >-} >- >- >-/** > * iser_reg_page_vec - Register physical memory > * > * returns: 0 on success, errno code on failure >diff -aurp linux-2.6.21.noarch/drivers/infiniband/ulp/iser/Kconfig linux-2.6.21.noarch.iscsi2/drivers/infiniband/ulp/iser/Kconfig >--- linux-2.6.21.noarch/drivers/infiniband/ulp/iser/Kconfig 2007-10-22 10:47:07.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/infiniband/ulp/iser/Kconfig 2007-10-24 22:26:00.000000000 -0500 >@@ -1,6 +1,6 @@ > config INFINIBAND_ISER > tristate "iSCSI Extensions for RDMA (iSER)" >- depends on INFINIBAND && SCSI && INET >+ depends on SCSI && INET > select SCSI_ISCSI_ATTRS > ---help--- > Support for the iSCSI Extensions for RDMA (iSER) Protocol >diff -aurp linux-2.6.21.noarch/drivers/scsi/iscsi_tcp.c linux-2.6.21.noarch.iscsi2/drivers/scsi/iscsi_tcp.c >--- linux-2.6.21.noarch/drivers/scsi/iscsi_tcp.c 2007-10-22 10:47:06.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/scsi/iscsi_tcp.c 2007-10-24 22:26:00.000000000 -0500 >@@ -29,14 +29,15 @@ > #include <linux/types.h> > #include <linux/list.h> > #include <linux/inet.h> >+#include <linux/file.h> > #include <linux/blkdev.h> > #include <linux/crypto.h> > #include <linux/delay.h> > #include <linux/kfifo.h> > #include <linux/scatterlist.h> >-#include <linux/mutex.h> > #include <net/tcp.h> > #include <scsi/scsi_cmnd.h> >+#include <scsi/scsi_device.h> > #include <scsi/scsi_host.h> > #include <scsi/scsi.h> > #include <scsi/scsi_transport_iscsi.h> >@@ -109,7 +110,7 @@ iscsi_hdr_digest(struct iscsi_conn *conn > struct iscsi_tcp_conn *tcp_conn = conn->dd_data; > > crypto_hash_digest(&tcp_conn->tx_hash, &buf->sg, buf->sg.length, crc); >- buf->sg.length = tcp_conn->hdr_size; >+ buf->sg.length += sizeof(u32); > } > > static inline int >@@ -211,16 +212,14 @@ iscsi_tcp_cleanup_ctask(struct iscsi_con > static int > iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) > { >- int rc; > struct iscsi_tcp_conn *tcp_conn = conn->dd_data; > struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; > struct iscsi_data_rsp *rhdr = (struct iscsi_data_rsp *)tcp_conn->in.hdr; > struct iscsi_session *session = conn->session; >+ struct scsi_cmnd *sc = ctask->sc; > int datasn = be32_to_cpu(rhdr->datasn); > >- rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr); >- if (rc) >- return rc; >+ iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr); > /* > * setup Data-In byte counter (gets decremented..) > */ >@@ -229,18 +228,23 @@ iscsi_data_rsp(struct iscsi_conn *conn, > if (tcp_conn->in.datalen == 0) > return 0; > >- if (ctask->datasn != datasn) >+ if (tcp_ctask->exp_datasn != datasn) { >+ debug_tcp("%s: ctask->exp_datasn(%d) != rhdr->datasn(%d)\n", >+ __FUNCTION__, tcp_ctask->exp_datasn, datasn); > return ISCSI_ERR_DATASN; >+ } > >- ctask->datasn++; >+ tcp_ctask->exp_datasn++; > > tcp_ctask->data_offset = be32_to_cpu(rhdr->offset); >- if (tcp_ctask->data_offset + tcp_conn->in.datalen > ctask->total_length) >+ if (tcp_ctask->data_offset + tcp_conn->in.datalen > sc->request_bufflen) { >+ debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n", >+ __FUNCTION__, tcp_ctask->data_offset, >+ tcp_conn->in.datalen, sc->request_bufflen); > return ISCSI_ERR_DATA_OFFSET; >+ } > > if (rhdr->flags & ISCSI_FLAG_DATA_STATUS) { >- struct scsi_cmnd *sc = ctask->sc; >- > conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; > if (rhdr->flags & ISCSI_FLAG_DATA_UNDERFLOW) { > int res_count = be32_to_cpu(rhdr->residual_count); >@@ -365,19 +369,17 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, s > return ISCSI_ERR_DATALEN; > } > >- if (tcp_ctask->exp_r2tsn && tcp_ctask->exp_r2tsn != r2tsn) >+ if (tcp_ctask->exp_datasn != r2tsn){ >+ debug_tcp("%s: ctask->exp_datasn(%d) != rhdr->r2tsn(%d)\n", >+ __FUNCTION__, tcp_ctask->exp_datasn, r2tsn); > return ISCSI_ERR_R2TSN; >- >- rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr); >- if (rc) >- return rc; >- >- /* FIXME: use R2TSN to detect missing R2T */ >+ } > > /* fill-in new R2T associated with the task */ > spin_lock(&session->lock); >- if (!ctask->sc || ctask->mtask || >- session->state != ISCSI_STATE_LOGGED_IN) { >+ iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr); >+ >+ if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) { > printk(KERN_INFO "iscsi_tcp: dropping R2T itt %d in " > "recovery...\n", ctask->itt); > spin_unlock(&session->lock); >@@ -401,11 +403,11 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, s > r2t->data_length, session->max_burst); > > r2t->data_offset = be32_to_cpu(rhdr->data_offset); >- if (r2t->data_offset + r2t->data_length > ctask->total_length) { >+ if (r2t->data_offset + r2t->data_length > ctask->sc->request_bufflen) { > spin_unlock(&session->lock); > printk(KERN_ERR "iscsi_tcp: invalid R2T with data len %u at " > "offset %u and total length %d\n", r2t->data_length, >- r2t->data_offset, ctask->total_length); >+ r2t->data_offset, ctask->sc->request_bufflen); > return ISCSI_ERR_DATALEN; > } > >@@ -414,13 +416,12 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, s > > iscsi_solicit_data_init(conn, ctask, r2t); > >- tcp_ctask->exp_r2tsn = r2tsn + 1; >+ tcp_ctask->exp_datasn = r2tsn + 1; > __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); >- tcp_ctask->xmstate |= XMSTATE_SOL_HDR; >- list_move_tail(&ctask->running, &conn->xmitqueue); >- >- scsi_queue_work(session->host, &conn->xmitwork); >+ tcp_ctask->xmstate |= XMSTATE_SOL_HDR_INIT; > conn->r2t_pdus_cnt++; >+ >+ iscsi_requeue_ctask(ctask); > spin_unlock(&session->lock); > > return 0; >@@ -527,12 +528,12 @@ iscsi_tcp_hdr_recv(struct iscsi_conn *co > * than 8K, but there are no targets that currently do this. > * For now we fail until we find a vendor that needs it > */ >- if (DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH < >+ if (ISCSI_DEF_MAX_RECV_SEG_LEN < > tcp_conn->in.datalen) { > printk(KERN_ERR "iscsi_tcp: received buffer of len %u " > "but conn buffer is only %u (opcode %0x)\n", > tcp_conn->in.datalen, >- DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, opcode); >+ ISCSI_DEF_MAX_RECV_SEG_LEN, opcode); > rc = ISCSI_ERR_PROTO; > break; > } >@@ -600,7 +601,7 @@ iscsi_ctask_copy(struct iscsi_tcp_conn * > { > struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; > int buf_left = buf_size - (tcp_conn->data_copied + offset); >- int size = min(tcp_conn->in.copy, buf_left); >+ unsigned size = min(tcp_conn->in.copy, buf_left); > int rc; > > size = min(size, ctask->data_count); >@@ -609,7 +610,7 @@ iscsi_ctask_copy(struct iscsi_tcp_conn * > size, tcp_conn->in.offset, tcp_conn->in.copied); > > BUG_ON(size <= 0); >- BUG_ON(tcp_ctask->sent + size > ctask->total_length); >+ BUG_ON(tcp_ctask->sent + size > ctask->sc->request_bufflen); > > rc = skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, > (char*)buf + (offset + tcp_conn->data_copied), size); >@@ -895,11 +896,27 @@ more: > } > } > >- if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV) { >+ if (tcp_conn->in_progress == IN_PROGRESS_DDIGEST_RECV && >+ tcp_conn->in.copy) { > uint32_t recv_digest; > > debug_tcp("extra data_recv offset %d copy %d\n", > tcp_conn->in.offset, tcp_conn->in.copy); >+ >+ if (!tcp_conn->data_copied) { >+ if (tcp_conn->in.padding) { >+ debug_tcp("padding -> %d\n", >+ tcp_conn->in.padding); >+ memset(pad, 0, tcp_conn->in.padding); >+ sg_init_one(&sg, pad, tcp_conn->in.padding); >+ crypto_hash_update(&tcp_conn->rx_hash, >+ &sg, sg.length); >+ } >+ crypto_hash_final(&tcp_conn->rx_hash, >+ (u8 *) &tcp_conn->in.datadgst); >+ debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst); >+ } >+ > rc = iscsi_tcp_copy(conn, sizeof(uint32_t)); > if (rc) { > if (rc == -EAGAIN) >@@ -924,8 +941,7 @@ more: > } > > if (tcp_conn->in_progress == IN_PROGRESS_DATA_RECV && >- tcp_conn->in.copy) { >- >+ tcp_conn->in.copy) { > debug_tcp("data_recv offset %d copy %d\n", > tcp_conn->in.offset, tcp_conn->in.copy); > >@@ -936,24 +952,32 @@ more: > iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); > return 0; > } >- tcp_conn->in.copy -= tcp_conn->in.padding; >- tcp_conn->in.offset += tcp_conn->in.padding; >- if (conn->datadgst_en) { >- if (tcp_conn->in.padding) { >- debug_tcp("padding -> %d\n", >- tcp_conn->in.padding); >- memset(pad, 0, tcp_conn->in.padding); >- sg_init_one(&sg, pad, tcp_conn->in.padding); >- crypto_hash_update(&tcp_conn->rx_hash, >- &sg, sg.length); >- } >- crypto_hash_final(&tcp_conn->rx_hash, >- (u8 *) &tcp_conn->in.datadgst); >- debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst); >+ >+ if (tcp_conn->in.padding) >+ tcp_conn->in_progress = IN_PROGRESS_PAD_RECV; >+ else if (conn->datadgst_en) > tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV; >- tcp_conn->data_copied = 0; >- } else >+ else > tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; >+ tcp_conn->data_copied = 0; >+ } >+ >+ if (tcp_conn->in_progress == IN_PROGRESS_PAD_RECV && >+ tcp_conn->in.copy) { >+ int copylen = min(tcp_conn->in.padding - tcp_conn->data_copied, >+ tcp_conn->in.copy); >+ >+ tcp_conn->in.copy -= copylen; >+ tcp_conn->in.offset += copylen; >+ tcp_conn->data_copied += copylen; >+ >+ if (tcp_conn->data_copied != tcp_conn->in.padding) >+ tcp_conn->in_progress = IN_PROGRESS_PAD_RECV; >+ else if (conn->datadgst_en) >+ tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV; >+ else >+ tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; >+ tcp_conn->data_copied = 0; > } > > debug_tcp("f, processed %d from out of %d padding %d\n", >@@ -1277,41 +1301,10 @@ static void iscsi_set_padding(struct isc > static void > iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) > { >- struct scsi_cmnd *sc = ctask->sc; > struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; > > BUG_ON(__kfifo_len(tcp_ctask->r2tqueue)); >- >- tcp_ctask->sent = 0; >- tcp_ctask->sg_count = 0; >- >- if (sc->sc_data_direction == DMA_TO_DEVICE) { >- tcp_ctask->xmstate = XMSTATE_W_HDR; >- tcp_ctask->exp_r2tsn = 0; >- BUG_ON(ctask->total_length == 0); >- >- if (sc->use_sg) { >- struct scatterlist *sg = sc->request_buffer; >- >- iscsi_buf_init_sg(&tcp_ctask->sendbuf, sg); >- tcp_ctask->sg = sg + 1; >- tcp_ctask->bad_sg = sg + sc->use_sg; >- } else { >- iscsi_buf_init_iov(&tcp_ctask->sendbuf, >- sc->request_buffer, >- sc->request_bufflen); >- tcp_ctask->sg = NULL; >- tcp_ctask->bad_sg = NULL; >- } >- debug_scsi("cmd [itt 0x%x total %d imm_data %d " >- "unsol count %d, unsol offset %d]\n", >- ctask->itt, ctask->total_length, ctask->imm_count, >- ctask->unsol_count, ctask->unsol_offset); >- } else >- tcp_ctask->xmstate = XMSTATE_R_HDR; >- >- iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr, >- sizeof(struct iscsi_hdr)); >+ tcp_ctask->xmstate = XMSTATE_CMD_HDR_INIT; > } > > /** >@@ -1324,9 +1317,11 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task > * call it again later, or recover. '0' return code means successful > * xmit. > * >- * Management xmit state machine consists of two states: >- * IN_PROGRESS_IMM_HEAD - PDU Header xmit in progress >- * IN_PROGRESS_IMM_DATA - PDU Data xmit in progress >+ * Management xmit state machine consists of these states: >+ * XMSTATE_IMM_HDR_INIT - calculate digest of PDU Header >+ * XMSTATE_IMM_HDR - PDU Header xmit in progress >+ * XMSTATE_IMM_DATA - PDU Data xmit in progress >+ * XMSTATE_IDLE - management PDU is done > **/ > static int > iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) >@@ -1337,23 +1332,34 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn * > debug_scsi("mtask deq [cid %d state %x itt 0x%x]\n", > conn->id, tcp_mtask->xmstate, mtask->itt); > >- if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) { >- tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR; >- if (mtask->data_count) >+ if (tcp_mtask->xmstate & XMSTATE_IMM_HDR_INIT) { >+ iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr, >+ sizeof(struct iscsi_hdr)); >+ >+ if (mtask->data_count) { > tcp_mtask->xmstate |= XMSTATE_IMM_DATA; >+ iscsi_buf_init_iov(&tcp_mtask->sendbuf, >+ (char*)mtask->data, >+ mtask->data_count); >+ } >+ > if (conn->c_stage != ISCSI_CONN_INITIAL_STAGE && > conn->stop_stage != STOP_CONN_RECOVER && > conn->hdrdgst_en) > iscsi_hdr_digest(conn, &tcp_mtask->headbuf, > (u8*)tcp_mtask->hdrext); >+ >+ tcp_mtask->sent = 0; >+ tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR_INIT; >+ tcp_mtask->xmstate |= XMSTATE_IMM_HDR; >+ } >+ >+ if (tcp_mtask->xmstate & XMSTATE_IMM_HDR) { > rc = iscsi_sendhdr(conn, &tcp_mtask->headbuf, > mtask->data_count); >- if (rc) { >- tcp_mtask->xmstate |= XMSTATE_IMM_HDR; >- if (mtask->data_count) >- tcp_mtask->xmstate &= ~XMSTATE_IMM_DATA; >+ if (rc) > return rc; >- } >+ tcp_mtask->xmstate &= ~XMSTATE_IMM_HDR; > } > > if (tcp_mtask->xmstate & XMSTATE_IMM_DATA) { >@@ -1387,55 +1393,75 @@ iscsi_tcp_mtask_xmit(struct iscsi_conn * > return 0; > } > >-static inline int >-iscsi_send_read_hdr(struct iscsi_conn *conn, >- struct iscsi_tcp_cmd_task *tcp_ctask) >+static int >+iscsi_send_cmd_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) > { >- int rc; >+ struct scsi_cmnd *sc = ctask->sc; >+ struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; >+ int rc = 0; > >- tcp_ctask->xmstate &= ~XMSTATE_R_HDR; >- if (conn->hdrdgst_en) >- iscsi_hdr_digest(conn, &tcp_ctask->headbuf, >- (u8*)tcp_ctask->hdrext); >- rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, 0); >- if (!rc) { >- BUG_ON(tcp_ctask->xmstate != XMSTATE_IDLE); >- return 0; /* wait for Data-In */ >- } >- tcp_ctask->xmstate |= XMSTATE_R_HDR; >- return rc; >-} >+ if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_INIT) { >+ tcp_ctask->sent = 0; >+ tcp_ctask->sg_count = 0; >+ tcp_ctask->exp_datasn = 0; >+ >+ if (sc->sc_data_direction == DMA_TO_DEVICE) { >+ if (sc->use_sg) { >+ struct scatterlist *sg = sc->request_buffer; >+ >+ iscsi_buf_init_sg(&tcp_ctask->sendbuf, sg); >+ tcp_ctask->sg = sg + 1; >+ tcp_ctask->bad_sg = sg + sc->use_sg; >+ } else { >+ iscsi_buf_init_iov(&tcp_ctask->sendbuf, >+ sc->request_buffer, >+ sc->request_bufflen); >+ tcp_ctask->sg = NULL; >+ tcp_ctask->bad_sg = NULL; >+ } > >-static inline int >-iscsi_send_write_hdr(struct iscsi_conn *conn, >- struct iscsi_cmd_task *ctask) >-{ >- struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; >- int rc; >+ debug_scsi("cmd [itt 0x%x total %d imm_data %d " >+ "unsol count %d, unsol offset %d]\n", >+ ctask->itt, sc->request_bufflen, >+ ctask->imm_count, ctask->unsol_count, >+ ctask->unsol_offset); >+ } > >- tcp_ctask->xmstate &= ~XMSTATE_W_HDR; >- if (conn->hdrdgst_en) >- iscsi_hdr_digest(conn, &tcp_ctask->headbuf, >- (u8*)tcp_ctask->hdrext); >- rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count); >- if (rc) { >- tcp_ctask->xmstate |= XMSTATE_W_HDR; >- return rc; >+ iscsi_buf_init_iov(&tcp_ctask->headbuf, (char*)ctask->hdr, >+ sizeof(struct iscsi_hdr)); >+ >+ if (conn->hdrdgst_en) >+ iscsi_hdr_digest(conn, &tcp_ctask->headbuf, >+ (u8*)tcp_ctask->hdrext); >+ tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_INIT; >+ tcp_ctask->xmstate |= XMSTATE_CMD_HDR_XMIT; > } > >- if (ctask->imm_count) { >- tcp_ctask->xmstate |= XMSTATE_IMM_DATA; >- iscsi_set_padding(tcp_ctask, ctask->imm_count); >+ if (tcp_ctask->xmstate & XMSTATE_CMD_HDR_XMIT) { >+ rc = iscsi_sendhdr(conn, &tcp_ctask->headbuf, ctask->imm_count); >+ if (rc) >+ return rc; >+ tcp_ctask->xmstate &= ~XMSTATE_CMD_HDR_XMIT; >+ >+ if (sc->sc_data_direction != DMA_TO_DEVICE) >+ return 0; > >- if (ctask->conn->datadgst_en) { >- iscsi_data_digest_init(ctask->conn->dd_data, tcp_ctask); >- tcp_ctask->immdigest = 0; >+ if (ctask->imm_count) { >+ tcp_ctask->xmstate |= XMSTATE_IMM_DATA; >+ iscsi_set_padding(tcp_ctask, ctask->imm_count); >+ >+ if (ctask->conn->datadgst_en) { >+ iscsi_data_digest_init(ctask->conn->dd_data, >+ tcp_ctask); >+ tcp_ctask->immdigest = 0; >+ } > } >- } > >- if (ctask->unsol_count) >- tcp_ctask->xmstate |= XMSTATE_UNS_HDR | XMSTATE_UNS_INIT; >- return 0; >+ if (ctask->unsol_count) >+ tcp_ctask->xmstate |= >+ XMSTATE_UNS_HDR | XMSTATE_UNS_INIT; >+ } >+ return rc; > } > > static int >@@ -1624,9 +1650,7 @@ static int iscsi_send_sol_pdu(struct isc > struct iscsi_data_task *dtask; > int left, rc; > >- if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) { >- tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; >- tcp_ctask->xmstate |= XMSTATE_SOL_DATA; >+ if (tcp_ctask->xmstate & XMSTATE_SOL_HDR_INIT) { > if (!tcp_ctask->r2t) { > spin_lock_bh(&session->lock); > __kfifo_get(tcp_ctask->r2tqueue, (void*)&tcp_ctask->r2t, >@@ -1640,12 +1664,19 @@ send_hdr: > if (conn->hdrdgst_en) > iscsi_hdr_digest(conn, &r2t->headbuf, > (u8*)dtask->hdrext); >+ tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR_INIT; >+ tcp_ctask->xmstate |= XMSTATE_SOL_HDR; >+ } >+ >+ if (tcp_ctask->xmstate & XMSTATE_SOL_HDR) { >+ r2t = tcp_ctask->r2t; >+ dtask = &r2t->dtask; >+ > rc = iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count); >- if (rc) { >- tcp_ctask->xmstate &= ~XMSTATE_SOL_DATA; >- tcp_ctask->xmstate |= XMSTATE_SOL_HDR; >+ if (rc) > return rc; >- } >+ tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; >+ tcp_ctask->xmstate |= XMSTATE_SOL_DATA; > > if (conn->datadgst_en) { > iscsi_data_digest_init(conn->dd_data, tcp_ctask); >@@ -1677,8 +1708,6 @@ send_hdr: > left = r2t->data_length - r2t->sent; > if (left) { > iscsi_solicit_data_cont(conn, ctask, r2t, left); >- tcp_ctask->xmstate |= XMSTATE_SOL_DATA; >- tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; > goto send_hdr; > } > >@@ -1693,8 +1722,6 @@ send_hdr: > if (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, > sizeof(void*))) { > tcp_ctask->r2t = r2t; >- tcp_ctask->xmstate |= XMSTATE_SOL_DATA; >- tcp_ctask->xmstate &= ~XMSTATE_SOL_HDR; > spin_unlock_bh(&session->lock); > goto send_hdr; > } >@@ -1703,6 +1730,46 @@ send_hdr: > return 0; > } > >+/** >+ * iscsi_tcp_ctask_xmit - xmit normal PDU task >+ * @conn: iscsi connection >+ * @ctask: iscsi command task >+ * >+ * Notes: >+ * The function can return -EAGAIN in which case caller must >+ * call it again later, or recover. '0' return code means successful >+ * xmit. >+ * The function is devided to logical helpers (above) for the different >+ * xmit stages. >+ * >+ *iscsi_send_cmd_hdr() >+ * XMSTATE_CMD_HDR_INIT - prepare Header and Data buffers Calculate >+ * Header Digest >+ * XMSTATE_CMD_HDR_XMIT - Transmit header in progress >+ * >+ *iscsi_send_padding >+ * XMSTATE_W_PAD - Prepare and send pading >+ * XMSTATE_W_RESEND_PAD - retry send pading >+ * >+ *iscsi_send_digest >+ * XMSTATE_W_RESEND_DATA_DIGEST - Finalize and send Data Digest >+ * XMSTATE_W_RESEND_DATA_DIGEST - retry sending digest >+ * >+ *iscsi_send_unsol_hdr >+ * XMSTATE_UNS_INIT - prepare un-solicit data header and digest >+ * XMSTATE_UNS_HDR - send un-solicit header >+ * >+ *iscsi_send_unsol_pdu >+ * XMSTATE_UNS_DATA - send un-solicit data in progress >+ * >+ *iscsi_send_sol_pdu >+ * XMSTATE_SOL_HDR_INIT - solicit data header and digest initialize >+ * XMSTATE_SOL_HDR - send solicit header >+ * XMSTATE_SOL_DATA - send solicit data >+ * >+ *iscsi_tcp_ctask_xmit >+ * XMSTATE_IMM_DATA - xmit managment data (??) >+ **/ > static int > iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) > { >@@ -1712,20 +1779,11 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn * > debug_scsi("ctask deq [cid %d xmstate %x itt 0x%x]\n", > conn->id, tcp_ctask->xmstate, ctask->itt); > >- /* >- * serialize with TMF AbortTask >- */ >- if (ctask->mtask) >+ rc = iscsi_send_cmd_hdr(conn, ctask); >+ if (rc) > return rc; >- >- if (tcp_ctask->xmstate & XMSTATE_R_HDR) >- return iscsi_send_read_hdr(conn, tcp_ctask); >- >- if (tcp_ctask->xmstate & XMSTATE_W_HDR) { >- rc = iscsi_send_write_hdr(conn, ctask); >- if (rc) >- return rc; >- } >+ if (ctask->sc->sc_data_direction != DMA_TO_DEVICE) >+ return 0; > > if (tcp_ctask->xmstate & XMSTATE_IMM_DATA) { > rc = iscsi_send_data(ctask, &tcp_ctask->sendbuf, &tcp_ctask->sg, >@@ -1762,7 +1820,7 @@ iscsi_tcp_conn_create(struct iscsi_cls_s > * due to strange issues with iser these are not set > * in iscsi_conn_setup > */ >- conn->max_recv_dlength = DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH; >+ conn->max_recv_dlength = ISCSI_DEF_MAX_RECV_SEG_LEN; > > tcp_conn = kzalloc(sizeof(*tcp_conn), GFP_KERNEL); > if (!tcp_conn) >@@ -1777,14 +1835,24 @@ iscsi_tcp_conn_create(struct iscsi_cls_s > tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0, > CRYPTO_ALG_ASYNC); > tcp_conn->tx_hash.flags = 0; >- if (IS_ERR(tcp_conn->tx_hash.tfm)) >+ if (IS_ERR(tcp_conn->tx_hash.tfm)) { >+ printk(KERN_ERR "Could not create connection due to crc32c " >+ "loading error %ld. Make sure the crc32c module is " >+ "built as a module or into the kernel\n", >+ PTR_ERR(tcp_conn->tx_hash.tfm)); > goto free_tcp_conn; >+ } > > tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0, > CRYPTO_ALG_ASYNC); > tcp_conn->rx_hash.flags = 0; >- if (IS_ERR(tcp_conn->rx_hash.tfm)) >+ if (IS_ERR(tcp_conn->rx_hash.tfm)) { >+ printk(KERN_ERR "Could not create connection due to crc32c " >+ "loading error %ld. Make sure the crc32c module is " >+ "built as a module or into the kernel\n", >+ PTR_ERR(tcp_conn->rx_hash.tfm)); > goto free_tx_tfm; >+ } > > return cls_conn; > >@@ -1800,18 +1868,22 @@ tcp_conn_alloc_fail: > static void > iscsi_tcp_release_conn(struct iscsi_conn *conn) > { >+ struct iscsi_session *session = conn->session; > struct iscsi_tcp_conn *tcp_conn = conn->dd_data; >+ struct socket *sock = tcp_conn->sock; > >- if (!tcp_conn->sock) >+ if (!sock) > return; > >- sock_hold(tcp_conn->sock->sk); >+ sock_hold(sock->sk); > iscsi_conn_restore_callbacks(tcp_conn); >- sock_put(tcp_conn->sock->sk); >+ sock_put(sock->sk); > >- sock_release(tcp_conn->sock); >+ spin_lock_bh(&session->lock); > tcp_conn->sock = NULL; > conn->recv_lock = NULL; >+ spin_unlock_bh(&session->lock); >+ sockfd_put(sock); > } > > static void >@@ -1842,6 +1914,46 @@ iscsi_tcp_conn_stop(struct iscsi_cls_con > tcp_conn->hdr_size = sizeof(struct iscsi_hdr); > } > >+static int iscsi_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock, >+ char *buf, int *port, >+ int (*getname)(struct socket *, struct sockaddr *, >+ int *addrlen)) >+{ >+ struct sockaddr_storage *addr; >+ struct sockaddr_in6 *sin6; >+ struct sockaddr_in *sin; >+ int rc = 0, len; >+ >+ addr = kmalloc(sizeof(*addr), GFP_KERNEL); >+ if (!addr) >+ return -ENOMEM; >+ >+ if (getname(sock, (struct sockaddr *) addr, &len)) { >+ rc = -ENODEV; >+ goto free_addr; >+ } >+ >+ switch (addr->ss_family) { >+ case AF_INET: >+ sin = (struct sockaddr_in *)addr; >+ spin_lock_bh(&conn->session->lock); >+ sprintf(buf, NIPQUAD_FMT, NIPQUAD(sin->sin_addr.s_addr)); >+ *port = be16_to_cpu(sin->sin_port); >+ spin_unlock_bh(&conn->session->lock); >+ break; >+ case AF_INET6: >+ sin6 = (struct sockaddr_in6 *)addr; >+ spin_lock_bh(&conn->session->lock); >+ sprintf(buf, NIP6_FMT, NIP6(sin6->sin6_addr)); >+ *port = be16_to_cpu(sin6->sin6_port); >+ spin_unlock_bh(&conn->session->lock); >+ break; >+ } >+free_addr: >+ kfree(addr); >+ return rc; >+} >+ > static int > iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, > struct iscsi_cls_conn *cls_conn, uint64_t transport_eph, >@@ -1859,10 +1971,24 @@ iscsi_tcp_conn_bind(struct iscsi_cls_ses > printk(KERN_ERR "iscsi_tcp: sockfd_lookup failed %d\n", err); > return -EEXIST; > } >+ /* >+ * copy these values now because if we drop the session >+ * userspace may still want to query the values since we will >+ * be using them for the reconnect >+ */ >+ err = iscsi_tcp_get_addr(conn, sock, conn->portal_address, >+ &conn->portal_port, kernel_getpeername); >+ if (err) >+ goto free_socket; >+ >+ err = iscsi_tcp_get_addr(conn, sock, conn->local_address, >+ &conn->local_port, kernel_getsockname); >+ if (err) >+ goto free_socket; > > err = iscsi_conn_bind(cls_session, cls_conn, is_leading); > if (err) >- return err; >+ goto free_socket; > > /* bind iSCSI connection and socket */ > tcp_conn->sock = sock; >@@ -1886,25 +2012,19 @@ iscsi_tcp_conn_bind(struct iscsi_cls_ses > * set receive state machine into initial state > */ > tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; >- > return 0; >+ >+free_socket: >+ sockfd_put(sock); >+ return err; > } > > /* called with host lock */ > static void >-iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask, >- char *data, uint32_t data_size) >+iscsi_tcp_mgmt_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask) > { > struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data; >- >- iscsi_buf_init_iov(&tcp_mtask->headbuf, (char*)mtask->hdr, >- sizeof(struct iscsi_hdr)); >- tcp_mtask->xmstate = XMSTATE_IMM_HDR; >- tcp_mtask->sent = 0; >- >- if (mtask->data_count) >- iscsi_buf_init_iov(&tcp_mtask->sendbuf, (char*)mtask->data, >- mtask->data_count); >+ tcp_mtask->xmstate = XMSTATE_IMM_HDR_INIT; > } > > static int >@@ -2016,41 +2136,18 @@ iscsi_tcp_conn_get_param(struct iscsi_cl > enum iscsi_param param, char *buf) > { > struct iscsi_conn *conn = cls_conn->dd_data; >- struct iscsi_tcp_conn *tcp_conn = conn->dd_data; >- struct inet_sock *inet; >- struct ipv6_pinfo *np; >- struct sock *sk; > int len; > > switch(param) { > case ISCSI_PARAM_CONN_PORT: >- mutex_lock(&conn->xmitmutex); >- if (!tcp_conn->sock) { >- mutex_unlock(&conn->xmitmutex); >- return -EINVAL; >- } >- >- inet = inet_sk(tcp_conn->sock->sk); >- len = sprintf(buf, "%hu\n", be16_to_cpu(inet->dport)); >- mutex_unlock(&conn->xmitmutex); >+ spin_lock_bh(&conn->session->lock); >+ len = sprintf(buf, "%hu\n", conn->portal_port); >+ spin_unlock_bh(&conn->session->lock); > break; > case ISCSI_PARAM_CONN_ADDRESS: >- mutex_lock(&conn->xmitmutex); >- if (!tcp_conn->sock) { >- mutex_unlock(&conn->xmitmutex); >- return -EINVAL; >- } >- >- sk = tcp_conn->sock->sk; >- if (sk->sk_family == PF_INET) { >- inet = inet_sk(sk); >- len = sprintf(buf, NIPQUAD_FMT "\n", >- NIPQUAD(inet->daddr)); >- } else { >- np = inet6_sk(sk); >- len = sprintf(buf, NIP6_FMT "\n", NIP6(np->daddr)); >- } >- mutex_unlock(&conn->xmitmutex); >+ spin_lock_bh(&conn->session->lock); >+ len = sprintf(buf, "%s\n", conn->portal_address); >+ spin_unlock_bh(&conn->session->lock); > break; > default: > return iscsi_conn_get_param(cls_conn, param, buf); >@@ -2059,6 +2156,29 @@ iscsi_tcp_conn_get_param(struct iscsi_cl > return len; > } > >+static int >+iscsi_tcp_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param, >+ char *buf) >+{ >+ struct iscsi_session *session = iscsi_hostdata(shost->hostdata); >+ int len; >+ >+ switch (param) { >+ case ISCSI_HOST_PARAM_IPADDRESS: >+ spin_lock_bh(&session->lock); >+ if (!session->leadconn) >+ len = -ENODEV; >+ else >+ len = sprintf(buf, "%s\n", >+ session->leadconn->local_address); >+ spin_unlock_bh(&session->lock); >+ break; >+ default: >+ return iscsi_host_get_param(shost, param, buf); >+ } >+ return len; >+} >+ > static void > iscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, struct iscsi_stats *stats) > { >@@ -2086,6 +2206,7 @@ iscsi_conn_get_stats(struct iscsi_cls_co > static struct iscsi_cls_session * > iscsi_tcp_session_create(struct iscsi_transport *iscsit, > struct scsi_transport_template *scsit, >+ uint16_t cmds_max, uint16_t qdepth, > uint32_t initial_cmdsn, uint32_t *hostno) > { > struct iscsi_cls_session *cls_session; >@@ -2093,7 +2214,7 @@ iscsi_tcp_session_create(struct iscsi_tr > uint32_t hn; > int cmd_i; > >- cls_session = iscsi_session_setup(iscsit, scsit, >+ cls_session = iscsi_session_setup(iscsit, scsit, cmds_max, qdepth, > sizeof(struct iscsi_tcp_cmd_task), > sizeof(struct iscsi_tcp_mgmt_task), > initial_cmdsn, &hn); >@@ -2132,16 +2253,27 @@ static void iscsi_tcp_session_destroy(st > iscsi_session_teardown(cls_session); > } > >+static int iscsi_tcp_slave_configure(struct scsi_device *sdev) >+{ >+ blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_ANY); >+ blk_queue_dma_alignment(sdev->request_queue, 0); >+ return 0; >+} >+ > static struct scsi_host_template iscsi_sht = { >+ .module = THIS_MODULE, > .name = "iSCSI Initiator over TCP/IP", > .queuecommand = iscsi_queuecommand, > .change_queue_depth = iscsi_change_queue_depth, >- .can_queue = ISCSI_XMIT_CMDS_MAX - 1, >+ .can_queue = ISCSI_DEF_XMIT_CMDS_MAX - 1, > .sg_tablesize = ISCSI_SG_TABLESIZE, >+ .max_sectors = 0xFFFF, > .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, > .eh_abort_handler = iscsi_eh_abort, >+ .eh_device_reset_handler= iscsi_eh_device_reset, > .eh_host_reset_handler = iscsi_eh_host_reset, > .use_clustering = DISABLE_CLUSTERING, >+ .slave_configure = iscsi_tcp_slave_configure, > .proc_name = "iscsi_tcp", > .this_id = -1, > }; >@@ -2168,8 +2300,13 @@ static struct iscsi_transport iscsi_tcp_ > ISCSI_EXP_STATSN | > ISCSI_PERSISTENT_PORT | > ISCSI_PERSISTENT_ADDRESS | >- ISCSI_TARGET_NAME | >- ISCSI_TPGT, >+ ISCSI_TARGET_NAME | ISCSI_TPGT | >+ ISCSI_USERNAME | ISCSI_PASSWORD | >+ ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN | >+ ISCSI_FAST_ABORT, >+ .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | >+ ISCSI_HOST_INITIATOR_NAME | >+ ISCSI_HOST_NETDEV_NAME, > .host_template = &iscsi_sht, > .conndata_size = sizeof(struct iscsi_conn), > .max_conn = 1, >@@ -2186,6 +2323,9 @@ static struct iscsi_transport iscsi_tcp_ > .get_session_param = iscsi_session_get_param, > .start_conn = iscsi_conn_start, > .stop_conn = iscsi_tcp_conn_stop, >+ /* iscsi host params */ >+ .get_host_param = iscsi_tcp_host_get_param, >+ .set_host_param = iscsi_host_set_param, > /* IO */ > .send_pdu = iscsi_conn_send_pdu, > .get_stats = iscsi_conn_get_stats, >diff -aurp linux-2.6.21.noarch/drivers/scsi/iscsi_tcp.h linux-2.6.21.noarch.iscsi2/drivers/scsi/iscsi_tcp.h >--- linux-2.6.21.noarch/drivers/scsi/iscsi_tcp.h 2007-10-22 10:47:06.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/scsi/iscsi_tcp.h 2007-10-24 22:26:00.000000000 -0500 >@@ -29,11 +29,12 @@ > #define IN_PROGRESS_HEADER_GATHER 0x1 > #define IN_PROGRESS_DATA_RECV 0x2 > #define IN_PROGRESS_DDIGEST_RECV 0x3 >+#define IN_PROGRESS_PAD_RECV 0x4 > > /* xmit state machine */ > #define XMSTATE_IDLE 0x0 >-#define XMSTATE_R_HDR 0x1 >-#define XMSTATE_W_HDR 0x2 >+#define XMSTATE_CMD_HDR_INIT 0x1 >+#define XMSTATE_CMD_HDR_XMIT 0x2 > #define XMSTATE_IMM_HDR 0x4 > #define XMSTATE_IMM_DATA 0x8 > #define XMSTATE_UNS_INIT 0x10 >@@ -44,6 +45,8 @@ > #define XMSTATE_W_PAD 0x200 > #define XMSTATE_W_RESEND_PAD 0x400 > #define XMSTATE_W_RESEND_DATA_DIGEST 0x800 >+#define XMSTATE_IMM_HDR_INIT 0x1000 >+#define XMSTATE_SOL_HDR_INIT 0x2000 > > #define ISCSI_PAD_LEN 4 > #define ISCSI_SG_TABLESIZE SG_ALL >@@ -152,7 +155,7 @@ struct iscsi_tcp_cmd_task { > struct scatterlist *sg; /* per-cmd SG list */ > struct scatterlist *bad_sg; /* assert statement */ > int sg_count; /* SG's to process */ >- uint32_t exp_r2tsn; >+ uint32_t exp_datasn; /* expected target's R2TSN/DataSN */ > int data_offset; > struct iscsi_r2t_info *r2t; /* in progress R2T */ > struct iscsi_queue r2tpool; >diff -aurp linux-2.6.21.noarch/drivers/scsi/libiscsi.c linux-2.6.21.noarch.iscsi2/drivers/scsi/libiscsi.c >--- linux-2.6.21.noarch/drivers/scsi/libiscsi.c 2007-10-22 10:47:06.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/scsi/libiscsi.c 2007-10-25 00:24:59.000000000 -0500 >@@ -22,9 +22,9 @@ > * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. > */ > #include <linux/types.h> >-#include <linux/mutex.h> > #include <linux/kfifo.h> > #include <linux/delay.h> >+#include <asm/unaligned.h> > #include <net/tcp.h> > #include <scsi/scsi_cmnd.h> > #include <scsi/scsi_device.h> >@@ -32,7 +32,7 @@ > #include <scsi/scsi_tcq.h> > #include <scsi/scsi_host.h> > #include <scsi/scsi.h> >-#include <scsi/iscsi_proto.h> >+#include <scsi/scsi_transport.h> > #include <scsi/scsi_transport.h> > #include <scsi/scsi_transport_iscsi.h> > #include <scsi/libiscsi.h> >@@ -45,27 +45,53 @@ class_to_transport_session(struct iscsi_ > } > EXPORT_SYMBOL_GPL(class_to_transport_session); > >-#define INVALID_SN_DELTA 0xffff >+/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */ >+#define SNA32_CHECK 2147483648UL > >-int >-iscsi_check_assign_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) >+static int iscsi_sna_lt(u32 n1, u32 n2) >+{ >+ return n1 != n2 && ((n1 < n2 && (n2 - n1 < SNA32_CHECK)) || >+ (n1 > n2 && (n2 - n1 < SNA32_CHECK))); >+} >+ >+/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */ >+static int iscsi_sna_lte(u32 n1, u32 n2) >+{ >+ return n1 == n2 || ((n1 < n2 && (n2 - n1 < SNA32_CHECK)) || >+ (n1 > n2 && (n2 - n1 < SNA32_CHECK))); >+} >+ >+void >+iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr) > { > uint32_t max_cmdsn = be32_to_cpu(hdr->max_cmdsn); > uint32_t exp_cmdsn = be32_to_cpu(hdr->exp_cmdsn); > >- if (max_cmdsn < exp_cmdsn -1 && >- max_cmdsn > exp_cmdsn - INVALID_SN_DELTA) >- return ISCSI_ERR_MAX_CMDSN; >- if (max_cmdsn > session->max_cmdsn || >- max_cmdsn < session->max_cmdsn - INVALID_SN_DELTA) >- session->max_cmdsn = max_cmdsn; >- if (exp_cmdsn > session->exp_cmdsn || >- exp_cmdsn < session->exp_cmdsn - INVALID_SN_DELTA) >+ /* >+ * standard specifies this check for when to update expected and >+ * max sequence numbers >+ */ >+ if (iscsi_sna_lt(max_cmdsn, exp_cmdsn - 1)) >+ return; >+ >+ if (exp_cmdsn != session->exp_cmdsn && >+ !iscsi_sna_lt(exp_cmdsn, session->exp_cmdsn)) > session->exp_cmdsn = exp_cmdsn; > >- return 0; >+ if (max_cmdsn != session->max_cmdsn && >+ !iscsi_sna_lt(max_cmdsn, session->max_cmdsn)) { >+ session->max_cmdsn = max_cmdsn; >+ /* >+ * if the window closed with IO queued, then kick the >+ * xmit thread >+ */ >+ if (!list_empty(&session->leadconn->xmitqueue) || >+ !list_empty(&session->leadconn->mgmtqueue)) >+ scsi_queue_work(session->host, >+ &session->leadconn->xmitwork); >+ } > } >-EXPORT_SYMBOL_GPL(iscsi_check_assign_cmdsn); >+EXPORT_SYMBOL_GPL(iscsi_update_cmdsn); > > void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *ctask, > struct iscsi_data *hdr) >@@ -119,9 +145,12 @@ static void iscsi_prep_scsi_cmd_pdu(stru > session->cmdsn++; > hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); > memcpy(hdr->cdb, sc->cmnd, sc->cmd_len); >- memset(&hdr->cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len); >+ if (sc->cmd_len < MAX_COMMAND_SIZE) >+ memset(&hdr->cdb[sc->cmd_len], 0, >+ MAX_COMMAND_SIZE - sc->cmd_len); > > ctask->data_count = 0; >+ ctask->imm_count = 0; > if (sc->sc_data_direction == DMA_TO_DEVICE) { > hdr->flags |= ISCSI_FLAG_CMD_WRITE; > /* >@@ -138,25 +167,24 @@ static void iscsi_prep_scsi_cmd_pdu(stru > * > * pad_count bytes to be sent as zero-padding > */ >- ctask->imm_count = 0; > ctask->unsol_count = 0; > ctask->unsol_offset = 0; > ctask->unsol_datasn = 0; > > if (session->imm_data_en) { >- if (ctask->total_length >= session->first_burst) >+ if (sc->request_bufflen >= session->first_burst) > ctask->imm_count = min(session->first_burst, > conn->max_xmit_dlength); > else >- ctask->imm_count = min(ctask->total_length, >+ ctask->imm_count = min(sc->request_bufflen, > conn->max_xmit_dlength); > hton24(ctask->hdr->dlength, ctask->imm_count); > } else > zero_data(ctask->hdr->dlength); > > if (!session->initial_r2t_en) { >- ctask->unsol_count = min(session->first_burst, >- ctask->total_length) - ctask->imm_count; >+ ctask->unsol_count = min((session->first_burst), >+ (sc->request_bufflen)) - ctask->imm_count; > ctask->unsol_offset = ctask->imm_count; > } > >@@ -164,7 +192,6 @@ static void iscsi_prep_scsi_cmd_pdu(stru > /* No unsolicit Data-Out's */ > ctask->hdr->flags |= ISCSI_FLAG_CMD_FINAL; > } else { >- ctask->datasn = 0; > hdr->flags |= ISCSI_FLAG_CMD_FINAL; > zero_data(hdr->dlength); > >@@ -173,8 +200,13 @@ static void iscsi_prep_scsi_cmd_pdu(stru > } > > conn->scsicmd_pdus_cnt++; >+ >+ debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d " >+ "cmdsn %d win %d]\n", >+ sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", >+ conn->id, sc, sc->cmnd[0], ctask->itt, sc->request_bufflen, >+ session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); > } >-EXPORT_SYMBOL_GPL(iscsi_prep_scsi_cmd_pdu); > > /** > * iscsi_complete_command - return command back to scsi-ml >@@ -203,26 +235,12 @@ static void __iscsi_get_ctask(struct isc > atomic_inc(&ctask->refcount); > } > >-static void iscsi_get_ctask(struct iscsi_cmd_task *ctask) >-{ >- spin_lock_bh(&ctask->conn->session->lock); >- __iscsi_get_ctask(ctask); >- spin_unlock_bh(&ctask->conn->session->lock); >-} >- > static void __iscsi_put_ctask(struct iscsi_cmd_task *ctask) > { > if (atomic_dec_and_test(&ctask->refcount)) > iscsi_complete_command(ctask); > } > >-static void iscsi_put_ctask(struct iscsi_cmd_task *ctask) >-{ >- spin_lock_bh(&ctask->conn->session->lock); >- __iscsi_put_ctask(ctask); >- spin_unlock_bh(&ctask->conn->session->lock); >-} >- > /** > * iscsi_cmd_rsp - SCSI Command Response processing > * @conn: iscsi connection >@@ -234,21 +252,15 @@ static void iscsi_put_ctask(struct iscsi > * iscsi_cmd_rsp sets up the scsi_cmnd fields based on the PDU and > * then completes the command and task. > **/ >-static int iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, >- struct iscsi_cmd_task *ctask, char *data, >- int datalen) >+static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, >+ struct iscsi_cmd_task *ctask, char *data, >+ int datalen) > { >- int rc; > struct iscsi_cmd_rsp *rhdr = (struct iscsi_cmd_rsp *)hdr; > struct iscsi_session *session = conn->session; > struct scsi_cmnd *sc = ctask->sc; > >- rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr); >- if (rc) { >- sc->result = DID_ERROR << 16; >- goto out; >- } >- >+ iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr); > conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; > > sc->result = (DID_OK << 16) | rhdr->cmd_status; >@@ -269,14 +281,14 @@ invalid_datalen: > goto out; > } > >- senselen = be16_to_cpu(*(__be16 *)data); >+ senselen = be16_to_cpu(get_unaligned((__be16 *) data)); > if (datalen < senselen) > goto invalid_datalen; > > memcpy(sc->sense_buffer, data + 2, > min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE)); > debug_scsi("copied %d bytes of sense\n", >- min(senselen, SCSI_SENSE_BUFFERSIZE)); >+ min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE)); > } > > if (sc->sc_data_direction == DMA_TO_DEVICE) >@@ -300,7 +312,6 @@ out: > conn->scsirsp_pdus_cnt++; > > __iscsi_put_ctask(ctask); >- return rc; > } > > static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) >@@ -310,15 +321,15 @@ static void iscsi_tmf_rsp(struct iscsi_c > conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; > conn->tmfrsp_pdus_cnt++; > >- if (conn->tmabort_state != TMABORT_INITIAL) >+ if (conn->tmf_state != TMF_QUEUED) > return; > > if (tmf->response == ISCSI_TMF_RSP_COMPLETE) >- conn->tmabort_state = TMABORT_SUCCESS; >+ conn->tmf_state = TMF_SUCCESS; > else if (tmf->response == ISCSI_TMF_RSP_NO_TASK) >- conn->tmabort_state = TMABORT_NOT_FOUND; >+ conn->tmf_state = TMF_NOT_FOUND; > else >- conn->tmabort_state = TMABORT_FAILED; >+ conn->tmf_state = TMF_FAILED; > wake_up(&conn->ehwait); > } > >@@ -380,8 +391,8 @@ int __iscsi_complete_pdu(struct iscsi_co > switch(opcode) { > case ISCSI_OP_SCSI_CMD_RSP: > BUG_ON((void*)ctask != ctask->sc->SCp.ptr); >- rc = iscsi_scsi_cmd_rsp(conn, hdr, ctask, data, >- datalen); >+ iscsi_scsi_cmd_rsp(conn, hdr, ctask, data, >+ datalen); > break; > case ISCSI_OP_SCSI_DATA_IN: > BUG_ON((void*)ctask != ctask->sc->SCp.ptr); >@@ -404,11 +415,7 @@ int __iscsi_complete_pdu(struct iscsi_co > debug_scsi("immrsp [op 0x%x cid %d itt 0x%x len %d]\n", > opcode, conn->id, mtask->itt, datalen); > >- rc = iscsi_check_assign_cmdsn(session, >- (struct iscsi_nopin*)hdr); >- if (rc) >- goto done; >- >+ iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); > switch(opcode) { > case ISCSI_OP_LOGOUT_RSP: > if (datalen) { >@@ -425,7 +432,7 @@ int __iscsi_complete_pdu(struct iscsi_co > */ > if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) > rc = ISCSI_ERR_CONN_FAILED; >- list_del(&mtask->running); >+ list_del_init(&mtask->running); > if (conn->login_mtask != mtask) > __kfifo_put(session->mgmtpool.queue, > (void*)&mtask, sizeof(void*)); >@@ -447,20 +454,16 @@ int __iscsi_complete_pdu(struct iscsi_co > > if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) > rc = ISCSI_ERR_CONN_FAILED; >- list_del(&mtask->running); >- if (conn->login_mtask != mtask) >- __kfifo_put(session->mgmtpool.queue, >- (void*)&mtask, sizeof(void*)); >+ list_del_init(&mtask->running); >+ __kfifo_put(session->mgmtpool.queue, >+ (void*)&mtask, sizeof(void*)); > break; > default: > rc = ISCSI_ERR_BAD_OPCODE; > break; > } > } else if (itt == ~0U) { >- rc = iscsi_check_assign_cmdsn(session, >- (struct iscsi_nopin*)hdr); >- if (rc) >- goto done; >+ iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr); > > switch(opcode) { > case ISCSI_OP_NOOP_IN: >@@ -490,7 +493,6 @@ int __iscsi_complete_pdu(struct iscsi_co > } else > rc = ISCSI_ERR_BAD_ITT; > >-done: > return rc; > } > EXPORT_SYMBOL_GPL(__iscsi_complete_pdu); >@@ -577,20 +579,56 @@ void iscsi_conn_failure(struct iscsi_con > } > EXPORT_SYMBOL_GPL(iscsi_conn_failure); > >-static int iscsi_xmit_imm_task(struct iscsi_conn *conn) >+static void iscsi_prep_mtask(struct iscsi_conn *conn, >+ struct iscsi_mgmt_task *mtask) >+{ >+ struct iscsi_session *session = conn->session; >+ struct iscsi_hdr *hdr = mtask->hdr; >+ struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; >+ >+ if (hdr->opcode != (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) && >+ hdr->opcode != (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE)) >+ nop->exp_statsn = cpu_to_be32(conn->exp_statsn); >+ /* >+ * pre-format CmdSN for outgoing PDU. >+ */ >+ nop->cmdsn = cpu_to_be32(session->cmdsn); >+ if (hdr->itt != RESERVED_ITT) { >+ hdr->itt = build_itt(mtask->itt, conn->id, session->age); >+ if (conn->c_stage == ISCSI_CONN_STARTED && >+ !(hdr->opcode & ISCSI_OP_IMMEDIATE)) { >+ session->queued_cmdsn++; >+ session->cmdsn++; >+ } >+ } >+ >+ if (session->tt->init_mgmt_task) >+ session->tt->init_mgmt_task(conn, mtask); >+ >+ debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", >+ hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt, >+ mtask->data_count); >+} >+ >+static int iscsi_xmit_mtask(struct iscsi_conn *conn) > { > struct iscsi_hdr *hdr = conn->mtask->hdr; > int rc, was_logout = 0; > > if ((hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) { > conn->session->state = ISCSI_STATE_IN_RECOVERY; >- iscsi_block_session(session_to_cls(conn->session)); > was_logout = 1; > } >+ spin_unlock_bh(&conn->session->lock); >+ > rc = conn->session->tt->xmit_mgmt_task(conn, conn->mtask); >+ spin_lock_bh(&conn->session->lock); > if (rc) > return rc; > >+ /* done with this in-progress mtask */ >+ conn->mtask = NULL; >+ > if (was_logout) { > set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); > return -ENODATA; >@@ -598,6 +636,55 @@ static int iscsi_xmit_imm_task(struct is > return 0; > } > >+static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn) >+{ >+ struct iscsi_session *session = conn->session; >+ >+ /* >+ * Check for iSCSI window and take care of CmdSN wrap-around >+ */ >+ if (!iscsi_sna_lte(session->queued_cmdsn, session->max_cmdsn)) { >+ debug_scsi("iSCSI CmdSN closed. ExpCmdSn %u MaxCmdSN %u " >+ "CmdSN %u/%u\n", session->exp_cmdsn, >+ session->max_cmdsn, session->cmdsn, >+ session->queued_cmdsn); >+ return -ENOSPC; >+ } >+ return 0; >+} >+ >+static int iscsi_xmit_ctask(struct iscsi_conn *conn) >+{ >+ struct iscsi_cmd_task *ctask = conn->ctask; >+ int rc; >+ >+ __iscsi_get_ctask(ctask); >+ spin_unlock_bh(&conn->session->lock); >+ rc = conn->session->tt->xmit_cmd_task(conn, ctask); >+ spin_lock_bh(&conn->session->lock); >+ __iscsi_put_ctask(ctask); >+ if (!rc) >+ /* done with this ctask */ >+ conn->ctask = NULL; >+ return rc; >+} >+ >+/** >+ * iscsi_requeue_ctask - requeue ctask to run from session workqueue >+ * @ctask: ctask to requeue >+ * >+ * LLDs that need to run a ctask from the session workqueue should call >+ * this. The session lock must be held. >+ */ >+void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask) >+{ >+ struct iscsi_conn *conn = ctask->conn; >+ >+ list_move_tail(&ctask->running, &conn->requeue); >+ scsi_queue_work(conn->session->host, &conn->xmitwork); >+} >+EXPORT_SYMBOL_GPL(iscsi_requeue_ctask); >+ > /** > * iscsi_data_xmit - xmit any command into the scheduled connection > * @conn: iscsi connection >@@ -609,112 +696,87 @@ static int iscsi_xmit_imm_task(struct is > **/ > static int iscsi_data_xmit(struct iscsi_conn *conn) > { >- struct iscsi_transport *tt; > int rc = 0; > >+ spin_lock_bh(&conn->session->lock); > if (unlikely(conn->suspend_tx)) { > debug_scsi("conn %d Tx suspended!\n", conn->id); >+ spin_unlock_bh(&conn->session->lock); > return -ENODATA; > } >- tt = conn->session->tt; >- >- /* >- * Transmit in the following order: >- * >- * 1) un-finished xmit (ctask or mtask) >- * 2) immediate control PDUs >- * 3) write data >- * 4) SCSI commands >- * 5) non-immediate control PDUs >- * >- * No need to lock around __kfifo_get as long as >- * there's one producer and one consumer. >- */ >- >- BUG_ON(conn->ctask && conn->mtask); > > if (conn->ctask) { >- iscsi_get_ctask(conn->ctask); >- rc = tt->xmit_cmd_task(conn, conn->ctask); >- iscsi_put_ctask(conn->ctask); >+ rc = iscsi_xmit_ctask(conn); > if (rc) > goto again; >- /* done with this in-progress ctask */ >- conn->ctask = NULL; > } >+ > if (conn->mtask) { >- rc = iscsi_xmit_imm_task(conn); >+ rc = iscsi_xmit_mtask(conn); > if (rc) > goto again; >- /* done with this in-progress mtask */ >- conn->mtask = NULL; > } > >- /* process immediate first */ >- if (unlikely(__kfifo_len(conn->immqueue))) { >- while (__kfifo_get(conn->immqueue, (void*)&conn->mtask, >- sizeof(void*))) { >- spin_lock_bh(&conn->session->lock); >- list_add_tail(&conn->mtask->running, >- &conn->mgmt_run_list); >- spin_unlock_bh(&conn->session->lock); >- rc = iscsi_xmit_imm_task(conn); >- if (rc) >- goto again; >- } >- /* done with this mtask */ >- conn->mtask = NULL; >+ /* >+ * process mgmt pdus like nops before commands since we should >+ * only have one nop-out as a ping from us and targets should not >+ * overflow us with nop-ins >+ */ >+check_mgmt: >+ while (!list_empty(&conn->mgmtqueue)) { >+ conn->mtask = list_entry(conn->mgmtqueue.next, >+ struct iscsi_mgmt_task, running); >+ iscsi_prep_mtask(conn, conn->mtask); >+ list_move_tail(conn->mgmtqueue.next, &conn->mgmt_run_list); >+ rc = iscsi_xmit_mtask(conn); >+ if (rc) >+ goto again; > } > >- /* process command queue */ >- spin_lock_bh(&conn->session->lock); >+ /* process pending command queue */ > while (!list_empty(&conn->xmitqueue)) { >- /* >- * iscsi tcp may readd the task to the xmitqueue to send >- * write data >- */ >+ if (conn->tmf_state == TMF_QUEUED) >+ break; >+ > conn->ctask = list_entry(conn->xmitqueue.next, > struct iscsi_cmd_task, running); >+ iscsi_prep_scsi_cmd_pdu(conn->ctask); >+ conn->session->tt->init_cmd_task(conn->ctask); > conn->ctask->state = ISCSI_TASK_RUNNING; > list_move_tail(conn->xmitqueue.next, &conn->run_list); >- __iscsi_get_ctask(conn->ctask); >- spin_unlock_bh(&conn->session->lock); >+ rc = iscsi_xmit_ctask(conn); >+ if (rc) >+ goto again; >+ /* >+ * we could continuously get new ctask requests so >+ * we need to check the mgmt queue for nops that need to >+ * be sent to aviod starvation >+ */ >+ if (!list_empty(&conn->mgmtqueue)) >+ goto check_mgmt; >+ } > >- rc = tt->xmit_cmd_task(conn, conn->ctask); >+ while (!list_empty(&conn->requeue)) { >+ if (conn->session->fast_abort && conn->tmf_state != TMF_INITIAL) >+ break; > >- spin_lock_bh(&conn->session->lock); >- __iscsi_put_ctask(conn->ctask); >- if (rc) { >- spin_unlock_bh(&conn->session->lock); >+ conn->ctask = list_entry(conn->requeue.next, >+ struct iscsi_cmd_task, running); >+ conn->ctask->state = ISCSI_TASK_RUNNING; >+ list_move_tail(conn->requeue.next, &conn->run_list); >+ rc = iscsi_xmit_ctask(conn); >+ if (rc) > goto again; >- } >+ if (!list_empty(&conn->mgmtqueue)) >+ goto check_mgmt; > } > spin_unlock_bh(&conn->session->lock); >- /* done with this ctask */ >- conn->ctask = NULL; >- >- /* process the rest control plane PDUs, if any */ >- if (unlikely(__kfifo_len(conn->mgmtqueue))) { >- while (__kfifo_get(conn->mgmtqueue, (void*)&conn->mtask, >- sizeof(void*))) { >- spin_lock_bh(&conn->session->lock); >- list_add_tail(&conn->mtask->running, >- &conn->mgmt_run_list); >- spin_unlock_bh(&conn->session->lock); >- rc = tt->xmit_mgmt_task(conn, conn->mtask); >- if (rc) >- goto again; >- } >- /* done with this mtask */ >- conn->mtask = NULL; >- } >- > return -ENODATA; > > again: > if (unlikely(conn->suspend_tx)) >- return -ENODATA; >- >+ rc = -ENODATA; >+ spin_unlock_bh(&conn->session->lock); > return rc; > } > >@@ -726,11 +788,9 @@ static void iscsi_xmitworker(struct work > /* > * serialize Xmit worker on a per-connection basis. > */ >- mutex_lock(&conn->xmitmutex); > do { > rc = iscsi_data_xmit(conn); > } while (rc >= 0 || rc == -EAGAIN); >- mutex_unlock(&conn->xmitmutex); > } > > enum { >@@ -788,46 +848,34 @@ int iscsi_queuecommand(struct scsi_cmnd > goto fault; > } > >- /* >- * Check for iSCSI window and take care of CmdSN wrap-around >- */ >- if ((int)(session->max_cmdsn - session->cmdsn) < 0) { >- reason = FAILURE_WINDOW_CLOSED; >- goto reject; >- } >- > conn = session->leadconn; > if (!conn) { > reason = FAILURE_SESSION_FREED; > goto fault; > } > >+ if (iscsi_check_cmdsn_window_closed(conn)) { >+ reason = FAILURE_WINDOW_CLOSED; >+ goto reject; >+ } >+ > if (!__kfifo_get(session->cmdpool.queue, (void*)&ctask, > sizeof(void*))) { > reason = FAILURE_OOM; > goto reject; > } >+ session->queued_cmdsn++; >+ > sc->SCp.phase = session->age; > sc->SCp.ptr = (char *)ctask; > > atomic_set(&ctask->refcount, 1); > ctask->state = ISCSI_TASK_PENDING; >- ctask->mtask = NULL; > ctask->conn = conn; > ctask->sc = sc; > INIT_LIST_HEAD(&ctask->running); >- ctask->total_length = sc->request_bufflen; >- iscsi_prep_scsi_cmd_pdu(ctask); >- >- session->tt->init_cmd_task(ctask); > > list_add_tail(&ctask->running, &conn->xmitqueue); >- debug_scsi( >- "ctask enq [%s cid %d sc %p cdb 0x%x itt 0x%x len %d cmdsn %d " >- "win %d]\n", >- sc->sc_data_direction == DMA_TO_DEVICE ? "write" : "read", >- conn->id, sc, sc->cmnd[0], ctask->itt, sc->request_bufflen, >- session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); > spin_unlock(&session->lock); > > scsi_queue_work(host, &conn->xmitwork); >@@ -858,19 +906,16 @@ int iscsi_change_queue_depth(struct scsi > } > EXPORT_SYMBOL_GPL(iscsi_change_queue_depth); > >-static int >-iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr, >- char *data, uint32_t data_size) >+static struct iscsi_mgmt_task * >+__iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, >+ char *data, uint32_t data_size) > { > struct iscsi_session *session = conn->session; >- struct iscsi_nopout *nop = (struct iscsi_nopout *)hdr; > struct iscsi_mgmt_task *mtask; > >- spin_lock_bh(&session->lock); >- if (session->state == ISCSI_STATE_TERMINATE) { >- spin_unlock_bh(&session->lock); >- return -EPERM; >- } >+ if (session->state == ISCSI_STATE_TERMINATE) >+ return NULL; >+ > if (hdr->opcode == (ISCSI_OP_LOGIN | ISCSI_OP_IMMEDIATE) || > hdr->opcode == (ISCSI_OP_TEXT | ISCSI_OP_IMMEDIATE)) > /* >@@ -884,80 +929,48 @@ iscsi_conn_send_generic(struct iscsi_con > BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); > BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); > >- nop->exp_statsn = cpu_to_be32(conn->exp_statsn); > if (!__kfifo_get(session->mgmtpool.queue, >- (void*)&mtask, sizeof(void*))) { >- spin_unlock_bh(&session->lock); >- return -ENOSPC; >- } >+ (void*)&mtask, sizeof(void*))) >+ return NULL; > } > >- /* >- * pre-format CmdSN for outgoing PDU. >- */ >- if (hdr->itt != RESERVED_ITT) { >- hdr->itt = build_itt(mtask->itt, conn->id, session->age); >- nop->cmdsn = cpu_to_be32(session->cmdsn); >- if (conn->c_stage == ISCSI_CONN_STARTED && >- !(hdr->opcode & ISCSI_OP_IMMEDIATE)) >- session->cmdsn++; >- } else >- /* do not advance CmdSN */ >- nop->cmdsn = cpu_to_be32(session->cmdsn); >- > if (data_size) { > memcpy(mtask->data, data, data_size); > mtask->data_count = data_size; > } else > mtask->data_count = 0; > >- INIT_LIST_HEAD(&mtask->running); > memcpy(mtask->hdr, hdr, sizeof(struct iscsi_hdr)); >- if (session->tt->init_mgmt_task) >- session->tt->init_mgmt_task(conn, mtask, data, data_size); >- spin_unlock_bh(&session->lock); >- >- debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n", >- hdr->opcode, hdr->itt, data_size); >- >- /* >- * since send_pdu() could be called at least from two contexts, >- * we need to serialize __kfifo_put, so we don't have to take >- * additional lock on fast data-path >- */ >- if (hdr->opcode & ISCSI_OP_IMMEDIATE) >- __kfifo_put(conn->immqueue, (void*)&mtask, sizeof(void*)); >- else >- __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*)); >- >- scsi_queue_work(session->host, &conn->xmitwork); >- return 0; >+ INIT_LIST_HEAD(&mtask->running); >+ list_add_tail(&mtask->running, &conn->mgmtqueue); >+ return mtask; > } > > int iscsi_conn_send_pdu(struct iscsi_cls_conn *cls_conn, struct iscsi_hdr *hdr, > char *data, uint32_t data_size) > { > struct iscsi_conn *conn = cls_conn->dd_data; >- int rc; >- >- mutex_lock(&conn->xmitmutex); >- rc = iscsi_conn_send_generic(conn, hdr, data, data_size); >- mutex_unlock(&conn->xmitmutex); >+ struct iscsi_session *session = conn->session; >+ int err = 0; > >- return rc; >+ spin_lock_bh(&session->lock); >+ if (!__iscsi_conn_send_pdu(conn, hdr, data, data_size)) >+ err = -EPERM; >+ spin_unlock_bh(&session->lock); >+ scsi_queue_work(session->host, &conn->xmitwork); >+ return err; > } > EXPORT_SYMBOL_GPL(iscsi_conn_send_pdu); > > void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) > { > struct iscsi_session *session = class_to_transport_session(cls_session); >- struct iscsi_conn *conn = session->leadconn; > > spin_lock_bh(&session->lock); > if (session->state != ISCSI_STATE_LOGGED_IN) { > session->state = ISCSI_STATE_RECOVERY_FAILED; >- if (conn) >- wake_up(&conn->ehwait); >+ if (session->leadconn) >+ wake_up(&session->leadconn->ehwait); > } > spin_unlock_bh(&session->lock); > } >@@ -968,7 +981,6 @@ int iscsi_eh_host_reset(struct scsi_cmnd > struct Scsi_Host *host = sc->device->host; > struct iscsi_session *session = iscsi_hostdata(host->hostdata); > struct iscsi_conn *conn = session->leadconn; >- int fail_session = 0; > > spin_lock_bh(&session->lock); > if (session->state == ISCSI_STATE_TERMINATE) { >@@ -979,19 +991,13 @@ failed: > return FAILED; > } > >- if (sc->SCp.phase == session->age) { >- debug_scsi("failing connection CID %d due to SCSI host reset\n", >- conn->id); >- fail_session = 1; >- } > spin_unlock_bh(&session->lock); > > /* > * we drop the lock here but the leadconn cannot be destoyed while > * we are in the scsi eh > */ >- if (fail_session) >- iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); >+ iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); > > debug_scsi("iscsi_eh_host_reset wait for relogin\n"); > wait_event_interruptible(conn->ehwait, >@@ -1012,133 +1018,79 @@ failed: > } > EXPORT_SYMBOL_GPL(iscsi_eh_host_reset); > >-static void iscsi_tmabort_timedout(unsigned long data) >+static void iscsi_tmf_timedout(unsigned long data) > { >- struct iscsi_cmd_task *ctask = (struct iscsi_cmd_task *)data; >- struct iscsi_conn *conn = ctask->conn; >+ struct iscsi_conn *conn = (struct iscsi_conn *)data; > struct iscsi_session *session = conn->session; > > spin_lock(&session->lock); >- if (conn->tmabort_state == TMABORT_INITIAL) { >- conn->tmabort_state = TMABORT_TIMEDOUT; >- debug_scsi("tmabort timedout [sc %p itt 0x%x]\n", >- ctask->sc, ctask->itt); >+ if (conn->tmf_state == TMF_QUEUED) { >+ conn->tmf_state = TMF_TIMEDOUT; >+ debug_scsi("tmf timedout\n"); > /* unblock eh_abort() */ > wake_up(&conn->ehwait); > } > spin_unlock(&session->lock); > } > >-/* must be called with the mutex lock */ >-static int iscsi_exec_abort_task(struct scsi_cmnd *sc, >- struct iscsi_cmd_task *ctask) >+static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, >+ struct iscsi_tm *hdr, int age) > { >- struct iscsi_conn *conn = ctask->conn; > struct iscsi_session *session = conn->session; >- struct iscsi_tm *hdr = &conn->tmhdr; >- int rc; >- >- /* >- * ctask timed out but session is OK requests must be serialized. >- */ >- memset(hdr, 0, sizeof(struct iscsi_tm)); >- hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; >- hdr->flags = ISCSI_TM_FUNC_ABORT_TASK; >- hdr->flags |= ISCSI_FLAG_CMD_FINAL; >- memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); >- hdr->rtt = ctask->hdr->itt; >- hdr->refcmdsn = ctask->hdr->cmdsn; >+ struct iscsi_mgmt_task *mtask; > >- rc = iscsi_conn_send_generic(conn, (struct iscsi_hdr *)hdr, >- NULL, 0); >- if (rc) { >+ mtask = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)hdr, >+ NULL, 0); >+ if (!mtask) { >+ spin_unlock_bh(&session->lock); > iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); >- debug_scsi("abort sent failure [itt 0x%x] %d\n", ctask->itt, >- rc); >- return rc; >+ spin_lock_bh(&session->lock); >+ debug_scsi("tmf exec failure\n"); >+ return -EPERM; > } >+ conn->tmfcmd_pdus_cnt++; >+ conn->tmf_timer.expires = 30 * HZ + jiffies; >+ conn->tmf_timer.function = iscsi_tmf_timedout; >+ conn->tmf_timer.data = (unsigned long)conn; >+ add_timer(&conn->tmf_timer); >+ debug_scsi("tmf set timeout\n"); > >- debug_scsi("abort sent [itt 0x%x]\n", ctask->itt); >- >- spin_lock_bh(&session->lock); >- ctask->mtask = (struct iscsi_mgmt_task *) >- session->mgmt_cmds[get_itt(hdr->itt) - >- ISCSI_MGMT_ITT_OFFSET]; >- >- if (conn->tmabort_state == TMABORT_INITIAL) { >- conn->tmfcmd_pdus_cnt++; >- conn->tmabort_timer.expires = 10*HZ + jiffies; >- conn->tmabort_timer.function = iscsi_tmabort_timedout; >- conn->tmabort_timer.data = (unsigned long)ctask; >- add_timer(&conn->tmabort_timer); >- debug_scsi("abort set timeout [itt 0x%x]\n", ctask->itt); >- } > spin_unlock_bh(&session->lock); >- mutex_unlock(&conn->xmitmutex); >+ mutex_unlock(&session->eh_mutex); >+ scsi_queue_work(session->host, &conn->xmitwork); > > /* > * block eh thread until: > * >- * 1) abort response >- * 2) abort timeout >+ * 1) tmf response >+ * 2) tmf timeout > * 3) session is terminated or restarted or userspace has > * given up on recovery > */ >- wait_event_interruptible(conn->ehwait, >- sc->SCp.phase != session->age || >+ wait_event_interruptible(conn->ehwait, age != session->age || > session->state != ISCSI_STATE_LOGGED_IN || >- conn->tmabort_state != TMABORT_INITIAL); >+ conn->tmf_state != TMF_QUEUED); > if (signal_pending(current)) > flush_signals(current); >- del_timer_sync(&conn->tmabort_timer); >- >- mutex_lock(&conn->xmitmutex); >- return 0; >-} >- >-/* >- * xmit mutex and session lock must be held >- */ >-static struct iscsi_mgmt_task * >-iscsi_remove_mgmt_task(struct kfifo *fifo, uint32_t itt) >-{ >- int i, nr_tasks = __kfifo_len(fifo) / sizeof(void*); >- struct iscsi_mgmt_task *task; >- >- debug_scsi("searching %d tasks\n", nr_tasks); >- >- for (i = 0; i < nr_tasks; i++) { >- __kfifo_get(fifo, (void*)&task, sizeof(void*)); >- debug_scsi("check task %u\n", task->itt); >+ del_timer_sync(&conn->tmf_timer); > >- if (task->itt == itt) { >- debug_scsi("matched task\n"); >- return task; >- } >+ mutex_lock(&session->eh_mutex); >+ spin_lock_bh(&session->lock); >+ /* if the session drops it will clean up the mtask */ >+ if (age != session->age || >+ session->state != ISCSI_STATE_LOGGED_IN) >+ return -ENOTCONN; > >- __kfifo_put(fifo, (void*)&task, sizeof(void*)); >+ if (!list_empty(&mtask->running)) { >+ list_del_init(&mtask->running); >+ __kfifo_put(session->mgmtpool.queue, (void*)&mtask, >+ sizeof(void*)); > } >- return NULL; >-} >- >-static int iscsi_ctask_mtask_cleanup(struct iscsi_cmd_task *ctask) >-{ >- struct iscsi_conn *conn = ctask->conn; >- struct iscsi_session *session = conn->session; >- >- if (!ctask->mtask) >- return -EINVAL; >- >- if (!iscsi_remove_mgmt_task(conn->immqueue, ctask->mtask->itt)) >- list_del(&ctask->mtask->running); >- __kfifo_put(session->mgmtpool.queue, (void*)&ctask->mtask, >- sizeof(void*)); >- ctask->mtask = NULL; > return 0; > } > > /* >- * session lock and xmitmutex must be held >+ * session lock must be held > */ > static void fail_command(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, > int err) >@@ -1149,122 +1101,277 @@ static void fail_command(struct iscsi_co > if (!sc) > return; > >- conn->session->tt->cleanup_cmd_task(conn, ctask); >- iscsi_ctask_mtask_cleanup(ctask); >+ if (ctask->state == ISCSI_TASK_PENDING) >+ /* >+ * cmd never made it to the xmit thread, so we should not count >+ * the cmd in the sequencing >+ */ >+ conn->session->queued_cmdsn--; >+ else >+ conn->session->tt->cleanup_cmd_task(conn, ctask); > > sc->result = err; > sc->resid = sc->request_bufflen; >+ if (conn->ctask == ctask) >+ conn->ctask = NULL; > /* release ref from queuecommand */ > __iscsi_put_ctask(ctask); > } > >+/* >+ * Fail commands. session lock held and recv side suspended and xmit >+ * thread flushed >+ */ >+static void fail_all_commands(struct iscsi_conn *conn, unsigned lun) >+{ >+ struct iscsi_cmd_task *ctask, *tmp; >+ >+ if (conn->ctask && (conn->ctask->sc->device->lun == lun || lun == -1)) >+ conn->ctask = NULL; >+ >+ /* flush pending */ >+ list_for_each_entry_safe(ctask, tmp, &conn->xmitqueue, running) { >+ if (lun == ctask->sc->device->lun || lun == -1) { >+ debug_scsi("failing pending sc %p itt 0x%x\n", >+ ctask->sc, ctask->itt); >+ fail_command(conn, ctask, DID_BUS_BUSY << 16); >+ } >+ } >+ >+ list_for_each_entry_safe(ctask, tmp, &conn->requeue, running) { >+ if (lun == ctask->sc->device->lun || lun == -1) { >+ debug_scsi("failing requeued sc %p itt 0x%x\n", >+ ctask->sc, ctask->itt); >+ fail_command(conn, ctask, DID_BUS_BUSY << 16); >+ } >+ } >+ >+ /* fail all other running */ >+ list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) { >+ if (lun == ctask->sc->device->lun || lun == -1) { >+ debug_scsi("failing in progress sc %p itt 0x%x\n", >+ ctask->sc, ctask->itt); >+ fail_command(conn, ctask, DID_BUS_BUSY << 16); >+ } >+ } >+} >+ >+static void iscsi_suspend_tx(struct iscsi_conn *conn) >+{ >+ set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); >+ scsi_flush_work(conn->session->host); >+} >+ >+static void iscsi_start_tx(struct iscsi_conn *conn) >+{ >+ clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); >+ scsi_queue_work(conn->session->host, &conn->xmitwork); >+} >+ >+static void iscsi_prep_abort_task_pdu(struct iscsi_cmd_task *ctask, >+ struct iscsi_tm *hdr) >+{ >+ memset(hdr, 0, sizeof(*hdr)); >+ hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; >+ hdr->flags = ISCSI_TM_FUNC_ABORT_TASK & ISCSI_FLAG_TM_FUNC_MASK; >+ hdr->flags |= ISCSI_FLAG_CMD_FINAL; >+ memcpy(hdr->lun, ctask->hdr->lun, sizeof(hdr->lun)); >+ hdr->rtt = ctask->hdr->itt; >+ hdr->refcmdsn = ctask->hdr->cmdsn; >+} >+ > int iscsi_eh_abort(struct scsi_cmnd *sc) > { >- struct iscsi_cmd_task *ctask; >+ struct Scsi_Host *host = sc->device->host; >+ struct iscsi_session *session = iscsi_hostdata(host->hostdata); > struct iscsi_conn *conn; >- struct iscsi_session *session; >- int rc; >+ struct iscsi_cmd_task *ctask; >+ struct iscsi_tm *hdr; >+ int rc, age; > >+ mutex_lock(&session->eh_mutex); >+ spin_lock_bh(&session->lock); > /* > * if session was ISCSI_STATE_IN_RECOVERY then we may not have > * got the command. > */ > if (!sc->SCp.ptr) { > debug_scsi("sc never reached iscsi layer or it completed.\n"); >+ spin_unlock_bh(&session->lock); >+ mutex_unlock(&session->eh_mutex); > return SUCCESS; > } > >- ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; >- conn = ctask->conn; >- session = conn->session; >- >- conn->eh_abort_cnt++; >- debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt); >- >- mutex_lock(&conn->xmitmutex); >- spin_lock_bh(&session->lock); >- > /* > * If we are not logged in or we have started a new session > * then let the host reset code handle this > */ >- if (session->state != ISCSI_STATE_LOGGED_IN || >- sc->SCp.phase != session->age) >- goto failed; >+ if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN || >+ sc->SCp.phase != session->age) { >+ spin_unlock_bh(&session->lock); >+ mutex_unlock(&session->eh_mutex); >+ return FAILED; >+ } >+ >+ conn = session->leadconn; >+ conn->eh_abort_cnt++; >+ age = session->age; >+ >+ ctask = (struct iscsi_cmd_task *)sc->SCp.ptr; >+ debug_scsi("aborting [sc %p itt 0x%x]\n", sc, ctask->itt); > > /* ctask completed before time out */ > if (!ctask->sc) { >- spin_unlock_bh(&session->lock); > debug_scsi("sc completed while abort in progress\n"); >- goto success_rel_mutex; >+ goto success; > } > >- /* what should we do here ? */ >- if (conn->ctask == ctask) { >- printk(KERN_INFO "iscsi: sc %p itt 0x%x partially sent. " >- "Failing abort\n", sc, ctask->itt); >- goto failed; >+ if (ctask->state == ISCSI_TASK_PENDING) { >+ fail_command(conn, ctask, DID_ABORT << 16); >+ goto success; > } > >- if (ctask->state == ISCSI_TASK_PENDING) >- goto success_cleanup; >- >- conn->tmabort_state = TMABORT_INITIAL; >+ /* only have one tmf outstanding at a time */ >+ if (conn->tmf_state != TMF_INITIAL) >+ goto failed; >+ conn->tmf_state = TMF_QUEUED; > >- spin_unlock_bh(&session->lock); >- rc = iscsi_exec_abort_task(sc, ctask); >- spin_lock_bh(&session->lock); >+ hdr = &conn->tmhdr; >+ iscsi_prep_abort_task_pdu(ctask, hdr); > >- if (rc || sc->SCp.phase != session->age || >- session->state != ISCSI_STATE_LOGGED_IN) >+ if (iscsi_exec_task_mgmt_fn(conn, hdr, age)) { >+ rc = FAILED; > goto failed; >- iscsi_ctask_mtask_cleanup(ctask); >+ } > >- switch (conn->tmabort_state) { >- case TMABORT_SUCCESS: >- goto success_cleanup; >- case TMABORT_NOT_FOUND: >- if (!ctask->sc) { >+ switch (conn->tmf_state) { >+ case TMF_SUCCESS: >+ spin_unlock_bh(&session->lock); >+ iscsi_suspend_tx(conn); >+ /* >+ * clean up task if aborted. grab the recv lock as a writer >+ */ >+ write_lock_bh(conn->recv_lock); >+ spin_lock(&session->lock); >+ fail_command(conn, ctask, DID_ABORT << 16); >+ conn->tmf_state = TMF_INITIAL; >+ spin_unlock(&session->lock); >+ write_unlock_bh(conn->recv_lock); >+ iscsi_start_tx(conn); >+ goto success_unlocked; >+ case TMF_TIMEDOUT: >+ spin_unlock_bh(&session->lock); >+ iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); >+ goto failed_unlocked; >+ case TMF_NOT_FOUND: >+ if (!sc->SCp.ptr) { >+ conn->tmf_state = TMF_INITIAL; > /* ctask completed before tmf abort response */ >- spin_unlock_bh(&session->lock); > debug_scsi("sc completed while abort in progress\n"); >- goto success_rel_mutex; >+ goto success; > } > /* fall through */ > default: >- /* timedout or failed */ >- spin_unlock_bh(&session->lock); >- iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); >- spin_lock_bh(&session->lock); >+ conn->tmf_state = TMF_INITIAL; > goto failed; > } > >-success_cleanup: >+success: >+ spin_unlock_bh(&session->lock); >+success_unlocked: > debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); >+ mutex_unlock(&session->eh_mutex); >+ return SUCCESS; >+ >+failed: > spin_unlock_bh(&session->lock); >+failed_unlocked: >+ debug_scsi("abort failed [sc %p itt 0x%x]\n", sc, >+ ctask ? ctask->itt : 0); >+ mutex_unlock(&session->eh_mutex); >+ return FAILED; >+} >+EXPORT_SYMBOL_GPL(iscsi_eh_abort); >+ >+static void iscsi_prep_lun_reset_pdu(struct scsi_cmnd *sc, struct iscsi_tm *hdr) >+{ >+ memset(hdr, 0, sizeof(*hdr)); >+ hdr->opcode = ISCSI_OP_SCSI_TMFUNC | ISCSI_OP_IMMEDIATE; >+ hdr->flags = ISCSI_TM_FUNC_LOGICAL_UNIT_RESET & ISCSI_FLAG_TM_FUNC_MASK; >+ hdr->flags |= ISCSI_FLAG_CMD_FINAL; >+ int_to_scsilun(sc->device->lun, (struct scsi_lun *)hdr->lun); >+ hdr->rtt = ISCSI_RESERVED_TAG; >+} >+ >+int iscsi_eh_device_reset(struct scsi_cmnd *sc) >+{ >+ struct Scsi_Host *host = sc->device->host; >+ struct iscsi_session *session = iscsi_hostdata(host->hostdata); >+ struct iscsi_conn *conn; >+ struct iscsi_tm *hdr; >+ int rc = FAILED; >+ >+ debug_scsi("LU Reset [sc %p lun %u]\n", sc, sc->device->lun); > >+ mutex_lock(&session->eh_mutex); >+ spin_lock_bh(&session->lock); > /* >- * clean up task if aborted. we have the xmitmutex so grab >- * the recv lock as a writer >+ * Just check if we are not logged in. We cannot check for >+ * the phase because the reset could come from a ioctl. > */ >+ if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) >+ goto unlock; >+ conn = session->leadconn; >+ >+ /* only have one tmf outstanding at a time */ >+ if (conn->tmf_state != TMF_INITIAL) >+ goto unlock; >+ conn->tmf_state = TMF_QUEUED; >+ >+ hdr = &conn->tmhdr; >+ iscsi_prep_lun_reset_pdu(sc, hdr); >+ >+ if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age)) { >+ rc = FAILED; >+ goto unlock; >+ } >+ >+ switch (conn->tmf_state) { >+ case TMF_SUCCESS: >+ break; >+ case TMF_TIMEDOUT: >+ spin_unlock_bh(&session->lock); >+ iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); >+ goto done; >+ default: >+ conn->tmf_state = TMF_INITIAL; >+ goto unlock; >+ } >+ >+ rc = SUCCESS; >+ spin_unlock_bh(&session->lock); >+ >+ iscsi_suspend_tx(conn); >+ /* need to grab the recv lock then session lock */ > write_lock_bh(conn->recv_lock); > spin_lock(&session->lock); >- fail_command(conn, ctask, DID_ABORT << 16); >+ fail_all_commands(conn, sc->device->lun); >+ conn->tmf_state = TMF_INITIAL; > spin_unlock(&session->lock); > write_unlock_bh(conn->recv_lock); > >-success_rel_mutex: >- mutex_unlock(&conn->xmitmutex); >- return SUCCESS; >+ iscsi_start_tx(conn); >+ goto done; > >-failed: >+unlock: > spin_unlock_bh(&session->lock); >- mutex_unlock(&conn->xmitmutex); >- >- debug_scsi("abort failed [sc %lx itt 0x%x]\n", (long)sc, ctask->itt); >- return FAILED; >+done: >+ debug_scsi("iscsi_eh_device_reset %s\n", >+ rc == SUCCESS ? "SUCCESS" : "FAILED"); >+ mutex_unlock(&session->eh_mutex); >+ return rc; > } >-EXPORT_SYMBOL_GPL(iscsi_eh_abort); >+EXPORT_SYMBOL_GPL(iscsi_eh_device_reset); > > int > iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size) >@@ -1341,6 +1448,10 @@ EXPORT_SYMBOL_GPL(iscsi_pool_free); > * iscsi_session_setup - create iscsi cls session and host and session > * @scsit: scsi transport template > * @iscsit: iscsi transport template >+ * @cmds_max: scsi host can queue >+ * @qdepth: scsi host cmds per lun >+ * @cmd_task_size: LLD ctask private data size >+ * @mgmt_task_size: LLD mtask private data size > * @initial_cmdsn: initial CmdSN > * @hostno: host no allocated > * >@@ -1350,6 +1461,7 @@ EXPORT_SYMBOL_GPL(iscsi_pool_free); > struct iscsi_cls_session * > iscsi_session_setup(struct iscsi_transport *iscsit, > struct scsi_transport_template *scsit, >+ uint16_t cmds_max, uint16_t qdepth, > int cmd_task_size, int mgmt_task_size, > uint32_t initial_cmdsn, uint32_t *hostno) > { >@@ -1358,11 +1470,32 @@ iscsi_session_setup(struct iscsi_transpo > struct iscsi_cls_session *cls_session; > int cmd_i; > >+ if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) { >+ if (qdepth != 0) >+ printk(KERN_ERR "iscsi: invalid queue depth of %d. " >+ "Queue depth must be between 1 and %d.\n", >+ qdepth, ISCSI_MAX_CMD_PER_LUN); >+ qdepth = ISCSI_DEF_CMD_PER_LUN; >+ } >+ >+ if (cmds_max < 2 || (cmds_max & (cmds_max - 1)) || >+ cmds_max >= ISCSI_MGMT_ITT_OFFSET) { >+ if (cmds_max != 0) >+ printk(KERN_ERR "iscsi: invalid can_queue of %d. " >+ "can_queue must be a power of 2 and between " >+ "2 and %d - setting to %d.\n", cmds_max, >+ ISCSI_MGMT_ITT_OFFSET, ISCSI_DEF_XMIT_CMDS_MAX); >+ cmds_max = ISCSI_DEF_XMIT_CMDS_MAX; >+ } >+ > shost = scsi_host_alloc(iscsit->host_template, > hostdata_privsize(sizeof(*session))); > if (!shost) > return NULL; > >+ /* the iscsi layer takes one task for reserve */ >+ shost->can_queue = cmds_max - 1; >+ shost->cmd_per_lun = qdepth; > shost->max_id = 1; > shost->max_channel = 0; > shost->max_lun = iscsit->max_lun; >@@ -1376,12 +1509,14 @@ iscsi_session_setup(struct iscsi_transpo > session->host = shost; > session->state = ISCSI_STATE_FREE; > session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; >- session->cmds_max = ISCSI_XMIT_CMDS_MAX; >- session->cmdsn = initial_cmdsn; >+ session->cmds_max = cmds_max; >+ session->queued_cmdsn = session->cmdsn = initial_cmdsn; > session->exp_cmdsn = initial_cmdsn + 1; > session->max_cmdsn = initial_cmdsn + 1; > session->max_r2t = 1; >+ session->fast_abort = 1; > session->tt = iscsit; >+ mutex_init(&session->eh_mutex); > > /* initialize SCSI PDU commands pool */ > if (iscsi_pool_init(&session->cmdpool, session->cmds_max, >@@ -1458,14 +1593,23 @@ void iscsi_session_teardown(struct iscsi > struct iscsi_session *session = iscsi_hostdata(shost->hostdata); > struct module *owner = cls_session->transport->owner; > >+ iscsi_unblock_session(cls_session); >+ iscsi_remove_session(cls_session); > scsi_remove_host(shost); > > iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); > iscsi_pool_free(&session->cmdpool, (void**)session->cmds); > >+ kfree(session->password); >+ kfree(session->password_in); >+ kfree(session->username); >+ kfree(session->username_in); > kfree(session->targetname); >+ kfree(session->netdev); >+ kfree(session->hwaddress); >+ kfree(session->initiatorname); > >- iscsi_destroy_session(cls_session); >+ iscsi_free_session(cls_session); > scsi_host_put(shost); > module_put(owner); > } >@@ -1495,22 +1639,12 @@ iscsi_conn_setup(struct iscsi_cls_sessio > conn->c_stage = ISCSI_CONN_INITIAL_STAGE; > conn->id = conn_idx; > conn->exp_statsn = 0; >- conn->tmabort_state = TMABORT_INITIAL; >+ conn->tmf_state = TMF_INITIAL; > INIT_LIST_HEAD(&conn->run_list); > INIT_LIST_HEAD(&conn->mgmt_run_list); >+ INIT_LIST_HEAD(&conn->mgmtqueue); > INIT_LIST_HEAD(&conn->xmitqueue); >- >- /* initialize general immediate & non-immediate PDU commands queue */ >- conn->immqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), >- GFP_KERNEL, NULL); >- if (conn->immqueue == ERR_PTR(-ENOMEM)) >- goto immqueue_alloc_fail; >- >- conn->mgmtqueue = kfifo_alloc(session->mgmtpool_max * sizeof(void*), >- GFP_KERNEL, NULL); >- if (conn->mgmtqueue == ERR_PTR(-ENOMEM)) >- goto mgmtqueue_alloc_fail; >- >+ INIT_LIST_HEAD(&conn->requeue); > INIT_WORK(&conn->xmitwork, iscsi_xmitworker); > > /* allocate login_mtask used for the login/text sequences */ >@@ -1523,13 +1657,12 @@ iscsi_conn_setup(struct iscsi_cls_sessio > } > spin_unlock_bh(&session->lock); > >- data = kmalloc(DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH, GFP_KERNEL); >+ data = kmalloc(ISCSI_DEF_MAX_RECV_SEG_LEN, GFP_KERNEL); > if (!data) > goto login_mtask_data_alloc_fail; > conn->login_mtask->data = conn->data = data; > >- init_timer(&conn->tmabort_timer); >- mutex_init(&conn->xmitmutex); >+ init_timer(&conn->tmf_timer); > init_waitqueue_head(&conn->ehwait); > > return cls_conn; >@@ -1538,10 +1671,6 @@ login_mtask_data_alloc_fail: > __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, > sizeof(void*)); > login_mtask_alloc_fail: >- kfifo_free(conn->mgmtqueue); >-mgmtqueue_alloc_fail: >- kfifo_free(conn->immqueue); >-immqueue_alloc_fail: > iscsi_destroy_conn(cls_conn); > return NULL; > } >@@ -1560,9 +1689,6 @@ void iscsi_conn_teardown(struct iscsi_cl > struct iscsi_session *session = conn->session; > unsigned long flags; > >- set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); >- mutex_lock(&conn->xmitmutex); >- > spin_lock_bh(&session->lock); > conn->c_stage = ISCSI_CONN_CLEANUP_WAIT; > if (session->leadconn == conn) { >@@ -1574,8 +1700,6 @@ void iscsi_conn_teardown(struct iscsi_cl > } > spin_unlock_bh(&session->lock); > >- mutex_unlock(&conn->xmitmutex); >- > /* > * Block until all in-progress commands for this connection > * time out or fail. >@@ -1597,21 +1721,18 @@ void iscsi_conn_teardown(struct iscsi_cl > wake_up(&conn->ehwait); > } > >+ /* flush queued up work because we free the connection below */ >+ iscsi_suspend_tx(conn); >+ > spin_lock_bh(&session->lock); > kfree(conn->data); > kfree(conn->persistent_address); > __kfifo_put(session->mgmtpool.queue, (void*)&conn->login_mtask, > sizeof(void*)); >- if (session->leadconn == conn) { >+ if (session->leadconn == conn) > session->leadconn = NULL; >- /* no connections exits.. reset sequencing */ >- session->cmdsn = session->max_cmdsn = session->exp_cmdsn = 1; >- } > spin_unlock_bh(&session->lock); > >- kfifo_free(conn->immqueue); >- kfifo_free(conn->mgmtqueue); >- > iscsi_destroy_conn(cls_conn); > } > EXPORT_SYMBOL_GPL(iscsi_conn_teardown); >@@ -1637,6 +1758,7 @@ int iscsi_conn_start(struct iscsi_cls_co > spin_lock_bh(&session->lock); > conn->c_stage = ISCSI_CONN_STARTED; > session->state = ISCSI_STATE_LOGGED_IN; >+ session->queued_cmdsn = session->cmdsn; > > switch(conn->stop_stage) { > case STOP_CONN_RECOVER: >@@ -1645,7 +1767,7 @@ int iscsi_conn_start(struct iscsi_cls_co > * commands after successful recovery > */ > conn->stop_stage = 0; >- conn->tmabort_state = TMABORT_INITIAL; >+ conn->tmf_state = TMF_INITIAL; > session->age++; > spin_unlock_bh(&session->lock); > >@@ -1670,11 +1792,11 @@ flush_control_queues(struct iscsi_sessio > struct iscsi_mgmt_task *mtask, *tmp; > > /* handle pending */ >- while (__kfifo_get(conn->immqueue, (void*)&mtask, sizeof(void*)) || >- __kfifo_get(conn->mgmtqueue, (void*)&mtask, sizeof(void*))) { >+ list_for_each_entry_safe(mtask, tmp, &conn->mgmtqueue, running) { >+ debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt); >+ list_del_init(&mtask->running); > if (mtask == conn->login_mtask) > continue; >- debug_scsi("flushing pending mgmt task itt 0x%x\n", mtask->itt); > __kfifo_put(session->mgmtpool.queue, (void*)&mtask, > sizeof(void*)); > } >@@ -1682,7 +1804,7 @@ flush_control_queues(struct iscsi_sessio > /* handle running */ > list_for_each_entry_safe(mtask, tmp, &conn->mgmt_run_list, running) { > debug_scsi("flushing running mgmt task itt 0x%x\n", mtask->itt); >- list_del(&mtask->running); >+ list_del_init(&mtask->running); > > if (mtask == conn->login_mtask) > continue; >@@ -1693,36 +1815,27 @@ flush_control_queues(struct iscsi_sessio > conn->mtask = NULL; > } > >-/* Fail commands. Mutex and session lock held and recv side suspended */ >-static void fail_all_commands(struct iscsi_conn *conn) >-{ >- struct iscsi_cmd_task *ctask, *tmp; >- >- /* flush pending */ >- list_for_each_entry_safe(ctask, tmp, &conn->xmitqueue, running) { >- debug_scsi("failing pending sc %p itt 0x%x\n", ctask->sc, >- ctask->itt); >- fail_command(conn, ctask, DID_BUS_BUSY << 16); >- } >- >- /* fail all other running */ >- list_for_each_entry_safe(ctask, tmp, &conn->run_list, running) { >- debug_scsi("failing in progress sc %p itt 0x%x\n", >- ctask->sc, ctask->itt); >- fail_command(conn, ctask, DID_BUS_BUSY << 16); >- } >- >- conn->ctask = NULL; >-} >- > static void iscsi_start_session_recovery(struct iscsi_session *session, > struct iscsi_conn *conn, int flag) > { > int old_stop_stage; > >+ mutex_lock(&session->eh_mutex); > spin_lock_bh(&session->lock); > if (conn->stop_stage == STOP_CONN_TERM) { > spin_unlock_bh(&session->lock); >+ mutex_unlock(&session->eh_mutex); >+ return; >+ } >+ >+ /* >+ * The LLD either freed/unset the lock on us, or userspace called >+ * stop but did not create a proper connection (connection was never >+ * bound or it was unbound then stop was called). >+ */ >+ if (!conn->recv_lock) { >+ spin_unlock_bh(&session->lock); >+ mutex_unlock(&session->eh_mutex); > return; > } > >@@ -1739,14 +1852,14 @@ static void iscsi_start_session_recovery > old_stop_stage = conn->stop_stage; > conn->stop_stage = flag; > conn->c_stage = ISCSI_CONN_STOPPED; >- set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx); > spin_unlock_bh(&session->lock); > >+ iscsi_suspend_tx(conn); >+ > write_lock_bh(conn->recv_lock); > set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); > write_unlock_bh(conn->recv_lock); > >- mutex_lock(&conn->xmitmutex); > /* > * for connection level recovery we should not calculate > * header digest. conn->hdr_size used for optimization >@@ -1767,11 +1880,10 @@ static void iscsi_start_session_recovery > * flush queues. > */ > spin_lock_bh(&session->lock); >- fail_all_commands(conn); >+ fail_all_commands(conn, -1); > flush_control_queues(session, conn); > spin_unlock_bh(&session->lock); >- >- mutex_unlock(&conn->xmitmutex); >+ mutex_unlock(&session->eh_mutex); > } > > void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) >@@ -1819,6 +1931,9 @@ int iscsi_set_param(struct iscsi_cls_con > uint32_t value; > > switch(param) { >+ case ISCSI_PARAM_FAST_ABORT: >+ sscanf(buf, "%d", &session->fast_abort); >+ break; > case ISCSI_PARAM_MAX_RECV_DLENGTH: > sscanf(buf, "%d", &conn->max_recv_dlength); > break; >@@ -1866,6 +1981,30 @@ int iscsi_set_param(struct iscsi_cls_con > case ISCSI_PARAM_EXP_STATSN: > sscanf(buf, "%u", &conn->exp_statsn); > break; >+ case ISCSI_PARAM_USERNAME: >+ kfree(session->username); >+ session->username = kstrdup(buf, GFP_KERNEL); >+ if (!session->username) >+ return -ENOMEM; >+ break; >+ case ISCSI_PARAM_USERNAME_IN: >+ kfree(session->username_in); >+ session->username_in = kstrdup(buf, GFP_KERNEL); >+ if (!session->username_in) >+ return -ENOMEM; >+ break; >+ case ISCSI_PARAM_PASSWORD: >+ kfree(session->password); >+ session->password = kstrdup(buf, GFP_KERNEL); >+ if (!session->password) >+ return -ENOMEM; >+ break; >+ case ISCSI_PARAM_PASSWORD_IN: >+ kfree(session->password_in); >+ session->password_in = kstrdup(buf, GFP_KERNEL); >+ if (!session->password_in) >+ return -ENOMEM; >+ break; > case ISCSI_PARAM_TARGET_NAME: > /* this should not change between logins */ > if (session->targetname) >@@ -1909,6 +2048,9 @@ int iscsi_session_get_param(struct iscsi > int len; > > switch(param) { >+ case ISCSI_PARAM_FAST_ABORT: >+ len = sprintf(buf, "%d\n", session->fast_abort); >+ break; > case ISCSI_PARAM_INITIAL_R2T_EN: > len = sprintf(buf, "%d\n", session->initial_r2t_en); > break; >@@ -1939,6 +2081,18 @@ int iscsi_session_get_param(struct iscsi > case ISCSI_PARAM_TPGT: > len = sprintf(buf, "%d\n", session->tpgt); > break; >+ case ISCSI_PARAM_USERNAME: >+ len = sprintf(buf, "%s\n", session->username); >+ break; >+ case ISCSI_PARAM_USERNAME_IN: >+ len = sprintf(buf, "%s\n", session->username_in); >+ break; >+ case ISCSI_PARAM_PASSWORD: >+ len = sprintf(buf, "%s\n", session->password); >+ break; >+ case ISCSI_PARAM_PASSWORD_IN: >+ len = sprintf(buf, "%s\n", session->password_in); >+ break; > default: > return -ENOSYS; > } >@@ -1989,6 +2143,66 @@ int iscsi_conn_get_param(struct iscsi_cl > } > EXPORT_SYMBOL_GPL(iscsi_conn_get_param); > >+int iscsi_host_get_param(struct Scsi_Host *shost, enum iscsi_host_param param, >+ char *buf) >+{ >+ struct iscsi_session *session = iscsi_hostdata(shost->hostdata); >+ int len; >+ >+ switch (param) { >+ case ISCSI_HOST_PARAM_NETDEV_NAME: >+ if (!session->netdev) >+ len = sprintf(buf, "%s\n", "default"); >+ else >+ len = sprintf(buf, "%s\n", session->netdev); >+ break; >+ case ISCSI_HOST_PARAM_HWADDRESS: >+ if (!session->hwaddress) >+ len = sprintf(buf, "%s\n", "default"); >+ else >+ len = sprintf(buf, "%s\n", session->hwaddress); >+ break; >+ case ISCSI_HOST_PARAM_INITIATOR_NAME: >+ if (!session->initiatorname) >+ len = sprintf(buf, "%s\n", "unknown"); >+ else >+ len = sprintf(buf, "%s\n", session->initiatorname); >+ break; >+ >+ default: >+ return -ENOSYS; >+ } >+ >+ return len; >+} >+EXPORT_SYMBOL_GPL(iscsi_host_get_param); >+ >+int iscsi_host_set_param(struct Scsi_Host *shost, enum iscsi_host_param param, >+ char *buf, int buflen) >+{ >+ struct iscsi_session *session = iscsi_hostdata(shost->hostdata); >+ >+ switch (param) { >+ case ISCSI_HOST_PARAM_NETDEV_NAME: >+ if (!session->netdev) >+ session->netdev = kstrdup(buf, GFP_KERNEL); >+ break; >+ case ISCSI_HOST_PARAM_HWADDRESS: >+ if (!session->hwaddress) >+ session->hwaddress = kstrdup(buf, GFP_KERNEL); >+ break; >+ case ISCSI_HOST_PARAM_INITIATOR_NAME: >+ if (!session->initiatorname) >+ session->initiatorname = kstrdup(buf, GFP_KERNEL); >+ break; >+ default: >+ return -ENOSYS; >+ } >+ >+ return 0; >+} >+EXPORT_SYMBOL_GPL(iscsi_host_set_param); >+ > MODULE_AUTHOR("Mike Christie"); > MODULE_DESCRIPTION("iSCSI library functions"); > MODULE_LICENSE("GPL"); >diff -aurp linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_dbg.c linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_dbg.c >--- linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_dbg.c 2007-10-22 10:47:06.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_dbg.c 2007-10-24 22:26:00.000000000 -0500 >@@ -6,174 +6,9 @@ > */ > > #include "ql4_def.h" >-#include <scsi/scsi_dbg.h> >- >-static void qla4xxx_print_srb_info(struct srb * srb) >-{ >- printk("%s: srb = 0x%p, flags=0x%02x\n", __func__, srb, srb->flags); >- printk("%s: cmd = 0x%p, saved_dma_handle = 0x%lx\n", >- __func__, srb->cmd, (unsigned long) srb->dma_handle); >- printk("%s: fw_ddb_index = %d, lun = %d\n", >- __func__, srb->fw_ddb_index, srb->cmd->device->lun); >- printk("%s: iocb_tov = %d\n", >- __func__, srb->iocb_tov); >- printk("%s: cc_stat = 0x%x, r_start = 0x%lx, u_start = 0x%lx\n\n", >- __func__, srb->cc_stat, srb->r_start, srb->u_start); >-} >- >-void qla4xxx_print_scsi_cmd(struct scsi_cmnd *cmd) >-{ >- printk("SCSI Command = 0x%p, Handle=0x%p\n", cmd, cmd->host_scribble); >- printk(" b=%d, t=%02xh, l=%02xh, cmd_len = %02xh\n", >- cmd->device->channel, cmd->device->id, cmd->device->lun, >- cmd->cmd_len); >- scsi_print_command(cmd); >- printk(" seg_cnt = %d\n", cmd->use_sg); >- printk(" request buffer = 0x%p, request buffer len = 0x%x\n", >- cmd->request_buffer, cmd->request_bufflen); >- if (cmd->use_sg) { >- struct scatterlist *sg; >- sg = (struct scatterlist *)cmd->request_buffer; >- printk(" SG buffer: \n"); >- qla4xxx_dump_buffer((caddr_t) sg, >- (cmd->use_sg * sizeof(*sg))); >- } >- printk(" tag = %d, transfersize = 0x%x \n", cmd->tag, >- cmd->transfersize); >- printk(" Pid = %d, SP = 0x%p\n", (int)cmd->pid, cmd->SCp.ptr); >- printk(" underflow size = 0x%x, direction=0x%x\n", cmd->underflow, >- cmd->sc_data_direction); >- printk(" Current time (jiffies) = 0x%lx, " >- "timeout expires = 0x%lx\n", jiffies, cmd->eh_timeout.expires); >- qla4xxx_print_srb_info((struct srb *) cmd->SCp.ptr); >-} >- >-void __dump_registers(struct scsi_qla_host *ha) >-{ >- uint8_t i; >- for (i = 0; i < MBOX_REG_COUNT; i++) { >- printk(KERN_INFO "0x%02X mailbox[%d] = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, mailbox[i]), i, >- readw(&ha->reg->mailbox[i])); >- } >- printk(KERN_INFO "0x%02X flash_address = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, flash_address), >- readw(&ha->reg->flash_address)); >- printk(KERN_INFO "0x%02X flash_data = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, flash_data), >- readw(&ha->reg->flash_data)); >- printk(KERN_INFO "0x%02X ctrl_status = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, ctrl_status), >- readw(&ha->reg->ctrl_status)); >- if (is_qla4010(ha)) { >- printk(KERN_INFO "0x%02X nvram = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, u1.isp4010.nvram), >- readw(&ha->reg->u1.isp4010.nvram)); >- } >- >- else if (is_qla4022(ha) | is_qla4032(ha)) { >- printk(KERN_INFO "0x%02X intr_mask = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, >- u1.isp4022.intr_mask), >- readw(&ha->reg->u1.isp4022.intr_mask)); >- printk(KERN_INFO "0x%02X nvram = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, u1.isp4022.nvram), >- readw(&ha->reg->u1.isp4022.nvram)); >- printk(KERN_INFO "0x%02X semaphore = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, >- u1.isp4022.semaphore), >- readw(&ha->reg->u1.isp4022.semaphore)); >- } >- printk(KERN_INFO "0x%02X req_q_in = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, req_q_in), >- readw(&ha->reg->req_q_in)); >- printk(KERN_INFO "0x%02X rsp_q_out = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, rsp_q_out), >- readw(&ha->reg->rsp_q_out)); >- if (is_qla4010(ha)) { >- printk(KERN_INFO "0x%02X ext_hw_conf = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, >- u2.isp4010.ext_hw_conf), >- readw(&ha->reg->u2.isp4010.ext_hw_conf)); >- printk(KERN_INFO "0x%02X port_ctrl = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, >- u2.isp4010.port_ctrl), >- readw(&ha->reg->u2.isp4010.port_ctrl)); >- printk(KERN_INFO "0x%02X port_status = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, >- u2.isp4010.port_status), >- readw(&ha->reg->u2.isp4010.port_status)); >- printk(KERN_INFO "0x%02X req_q_out = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, >- u2.isp4010.req_q_out), >- readw(&ha->reg->u2.isp4010.req_q_out)); >- printk(KERN_INFO "0x%02X gp_out = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, u2.isp4010.gp_out), >- readw(&ha->reg->u2.isp4010.gp_out)); >- printk(KERN_INFO "0x%02X gp_in = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, u2.isp4010.gp_in), >- readw(&ha->reg->u2.isp4010.gp_in)); >- printk(KERN_INFO "0x%02X port_err_status = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, >- u2.isp4010.port_err_status), >- readw(&ha->reg->u2.isp4010.port_err_status)); >- } >- >- else if (is_qla4022(ha) | is_qla4032(ha)) { >- printk(KERN_INFO "Page 0 Registers:\n"); >- printk(KERN_INFO "0x%02X ext_hw_conf = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, >- u2.isp4022.p0.ext_hw_conf), >- readw(&ha->reg->u2.isp4022.p0.ext_hw_conf)); >- printk(KERN_INFO "0x%02X port_ctrl = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, >- u2.isp4022.p0.port_ctrl), >- readw(&ha->reg->u2.isp4022.p0.port_ctrl)); >- printk(KERN_INFO "0x%02X port_status = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, >- u2.isp4022.p0.port_status), >- readw(&ha->reg->u2.isp4022.p0.port_status)); >- printk(KERN_INFO "0x%02X gp_out = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, >- u2.isp4022.p0.gp_out), >- readw(&ha->reg->u2.isp4022.p0.gp_out)); >- printk(KERN_INFO "0x%02X gp_in = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, u2.isp4022.p0.gp_in), >- readw(&ha->reg->u2.isp4022.p0.gp_in)); >- printk(KERN_INFO "0x%02X port_err_status = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, >- u2.isp4022.p0.port_err_status), >- readw(&ha->reg->u2.isp4022.p0.port_err_status)); >- printk(KERN_INFO "Page 1 Registers:\n"); >- writel(HOST_MEM_CFG_PAGE & set_rmask(CSR_SCSI_PAGE_SELECT), >- &ha->reg->ctrl_status); >- printk(KERN_INFO "0x%02X req_q_out = 0x%08X\n", >- (uint8_t) offsetof(struct isp_reg, >- u2.isp4022.p1.req_q_out), >- readw(&ha->reg->u2.isp4022.p1.req_q_out)); >- writel(PORT_CTRL_STAT_PAGE & set_rmask(CSR_SCSI_PAGE_SELECT), >- &ha->reg->ctrl_status); >- } >-} >- >-void qla4xxx_dump_mbox_registers(struct scsi_qla_host *ha) >-{ >- unsigned long flags = 0; >- int i = 0; >- spin_lock_irqsave(&ha->hardware_lock, flags); >- for (i = 1; i < MBOX_REG_COUNT; i++) >- printk(KERN_INFO " Mailbox[%d] = %08x\n", i, >- readw(&ha->reg->mailbox[i])); >- spin_unlock_irqrestore(&ha->hardware_lock, flags); >-} >- >-void qla4xxx_dump_registers(struct scsi_qla_host *ha) >-{ >- unsigned long flags = 0; >- spin_lock_irqsave(&ha->hardware_lock, flags); >- __dump_registers(ha); >- spin_unlock_irqrestore(&ha->hardware_lock, flags); >-} >+#include "ql4_glbl.h" >+#include "ql4_dbg.h" >+#include "ql4_inline.h" > > void qla4xxx_dump_buffer(void *b, uint32_t size) > { >@@ -195,3 +30,4 @@ void qla4xxx_dump_buffer(void *b, uint32 > if (cnt % 16) > printk(KERN_DEBUG "\n"); > } >+ >diff -aurp linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_def.h linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_def.h >--- linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_def.h 2007-10-22 10:47:06.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_def.h 2007-10-24 22:26:00.000000000 -0500 >@@ -122,8 +122,7 @@ > > #define ISCSI_IPADDR_SIZE 4 /* IP address size */ > #define ISCSI_ALIAS_SIZE 32 /* ISCSI Alais name size */ >-#define ISCSI_NAME_SIZE 255 /* ISCSI Name size - >- * usually a string */ >+#define ISCSI_NAME_SIZE 0xE0 /* ISCSI Name size */ > > #define LSDW(x) ((u32)((u64)(x))) > #define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16)) >@@ -187,9 +186,21 @@ struct srb { > u_long u_start; /* Time when we handed the cmd to F/W */ > }; > >- /* >- * Device Database (DDB) structure >- */ >+/* >+ * Asynchronous Event Queue structure >+ */ >+struct aen { >+ uint32_t mbox_sts[MBOX_AEN_REG_COUNT]; >+}; >+ >+struct ql4_aen_log { >+ int count; >+ struct aen entry[MAX_AEN_ENTRIES]; >+}; >+ >+/* >+ * Device Database (DDB) structure >+ */ > struct ddb_entry { > struct list_head list; /* ddb list */ > struct scsi_qla_host *ha; >@@ -254,13 +265,6 @@ struct ddb_entry { > #define DF_ISNS_DISCOVERED 2 /* Device was discovered via iSNS */ > #define DF_FO_MASKED 3 > >-/* >- * Asynchronous Event Queue structure >- */ >-struct aen { >- uint32_t mbox_sts[MBOX_AEN_REG_COUNT]; >-}; >- > > #include "ql4_fw.h" > #include "ql4_nvram.h" >@@ -270,31 +274,31 @@ struct aen { > */ > struct scsi_qla_host { > /* Linux adapter configuration data */ >- struct Scsi_Host *host; /* pointer to host data */ >- uint32_t tot_ddbs; > unsigned long flags; > >-#define AF_ONLINE 0 /* 0x00000001 */ >-#define AF_INIT_DONE 1 /* 0x00000002 */ >-#define AF_MBOX_COMMAND 2 /* 0x00000004 */ >-#define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */ >-#define AF_INTERRUPTS_ON 6 /* 0x00000040 Not Used */ >-#define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ >-#define AF_LINK_UP 8 /* 0x00000100 */ >-#define AF_IRQ_ATTACHED 10 /* 0x00000400 */ >-#define AF_ISNS_CMD_IN_PROCESS 12 /* 0x00001000 */ >-#define AF_ISNS_CMD_DONE 13 /* 0x00002000 */ >+#define AF_ONLINE 0 /* 0x00000001 */ >+#define AF_INIT_DONE 1 /* 0x00000002 */ >+#define AF_MBOX_COMMAND 2 /* 0x00000004 */ >+#define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */ >+#define AF_INTERRUPTS_ON 6 /* 0x00000040 */ >+#define AF_GET_CRASH_RECORD 7 /* 0x00000080 */ >+#define AF_LINK_UP 8 /* 0x00000100 */ >+#define AF_IRQ_ATTACHED 10 /* 0x00000400 */ >+#define AF_DISABLE_ACB_COMPLETE 11 /* 0x00000800 */ > > unsigned long dpc_flags; > >-#define DPC_RESET_HA 1 /* 0x00000002 */ >-#define DPC_RETRY_RESET_HA 2 /* 0x00000004 */ >-#define DPC_RELOGIN_DEVICE 3 /* 0x00000008 */ >-#define DPC_RESET_HA_DESTROY_DDB_LIST 4 /* 0x00000010 */ >-#define DPC_RESET_HA_INTR 5 /* 0x00000020 */ >-#define DPC_ISNS_RESTART 7 /* 0x00000080 */ >-#define DPC_AEN 9 /* 0x00000200 */ >-#define DPC_GET_DHCP_IP_ADDR 15 /* 0x00008000 */ >+#define DPC_RESET_HA 1 /* 0x00000002 */ >+#define DPC_RETRY_RESET_HA 2 /* 0x00000004 */ >+#define DPC_RELOGIN_DEVICE 3 /* 0x00000008 */ >+#define DPC_RESET_HA_DESTROY_DDB_LIST 4 /* 0x00000010 */ >+#define DPC_RESET_HA_INTR 5 /* 0x00000020 */ >+#define DPC_ISNS_RESTART 7 /* 0x00000080 */ >+#define DPC_AEN 9 /* 0x00000200 */ >+#define DPC_GET_DHCP_IP_ADDR 15 /* 0x00008000 */ >+ >+ struct Scsi_Host *host; /* pointer to host data */ >+ uint32_t tot_ddbs; > > uint16_t iocb_cnt; > uint16_t iocb_hiwat; >@@ -344,6 +348,7 @@ struct scsi_qla_host { > uint32_t firmware_version[2]; > uint32_t patch_number; > uint32_t build_number; >+ uint32_t board_id; > > /* --- From Init_FW --- */ > /* init_cb_t *init_cb; */ >@@ -363,7 +368,6 @@ struct scsi_qla_host { > > /* --- From GetFwState --- */ > uint32_t firmware_state; >- uint32_t board_id; > uint32_t addl_fw_state; > > /* Linux kernel thread */ >@@ -414,6 +418,8 @@ struct scsi_qla_host { > uint16_t aen_out; > struct aen aen_q[MAX_AEN_ENTRIES]; > >+ struct ql4_aen_log aen_log;/* tracks all aens */ >+ > /* This mutex protects several threads to do mailbox commands > * concurrently. > */ >@@ -585,10 +591,4 @@ static inline void ql4xxx_unlock_drvr(st > #define FLUSH_DDB_CHANGED_AENS 1 > #define RELOGIN_DDB_CHANGED_AENS 2 > >-#include "ql4_version.h" >-#include "ql4_glbl.h" >-#include "ql4_dbg.h" >-#include "ql4_inline.h" >- >- > #endif /*_QLA4XXX_H */ >diff -aurp linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_fw.h linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_fw.h >--- linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_fw.h 2007-10-22 10:47:06.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_fw.h 2007-10-24 22:26:00.000000000 -0500 >@@ -20,143 +20,23 @@ > *************************************************************************/ > > struct port_ctrl_stat_regs { >- __le32 ext_hw_conf; /* 80 x50 R/W */ >- __le32 intChipConfiguration; /* 84 x54 */ >- __le32 port_ctrl; /* 88 x58 */ >- __le32 port_status; /* 92 x5c */ >- __le32 HostPrimMACHi; /* 96 x60 */ >- __le32 HostPrimMACLow; /* 100 x64 */ >- __le32 HostSecMACHi; /* 104 x68 */ >- __le32 HostSecMACLow; /* 108 x6c */ >- __le32 EPPrimMACHi; /* 112 x70 */ >- __le32 EPPrimMACLow; /* 116 x74 */ >- __le32 EPSecMACHi; /* 120 x78 */ >- __le32 EPSecMACLow; /* 124 x7c */ >- __le32 HostPrimIPHi; /* 128 x80 */ >- __le32 HostPrimIPMidHi; /* 132 x84 */ >- __le32 HostPrimIPMidLow; /* 136 x88 */ >- __le32 HostPrimIPLow; /* 140 x8c */ >- __le32 HostSecIPHi; /* 144 x90 */ >- __le32 HostSecIPMidHi; /* 148 x94 */ >- __le32 HostSecIPMidLow; /* 152 x98 */ >- __le32 HostSecIPLow; /* 156 x9c */ >- __le32 EPPrimIPHi; /* 160 xa0 */ >- __le32 EPPrimIPMidHi; /* 164 xa4 */ >- __le32 EPPrimIPMidLow; /* 168 xa8 */ >- __le32 EPPrimIPLow; /* 172 xac */ >- __le32 EPSecIPHi; /* 176 xb0 */ >- __le32 EPSecIPMidHi; /* 180 xb4 */ >- __le32 EPSecIPMidLow; /* 184 xb8 */ >- __le32 EPSecIPLow; /* 188 xbc */ >- __le32 IPReassemblyTimeout; /* 192 xc0 */ >- __le32 EthMaxFramePayload; /* 196 xc4 */ >- __le32 TCPMaxWindowSize; /* 200 xc8 */ >- __le32 TCPCurrentTimestampHi; /* 204 xcc */ >- __le32 TCPCurrentTimestampLow; /* 208 xd0 */ >- __le32 LocalRAMAddress; /* 212 xd4 */ >- __le32 LocalRAMData; /* 216 xd8 */ >- __le32 PCSReserved1; /* 220 xdc */ >- __le32 gp_out; /* 224 xe0 */ >- __le32 gp_in; /* 228 xe4 */ >- __le32 ProbeMuxAddr; /* 232 xe8 */ >- __le32 ProbeMuxData; /* 236 xec */ >- __le32 ERMQueueBaseAddr0; /* 240 xf0 */ >- __le32 ERMQueueBaseAddr1; /* 244 xf4 */ >- __le32 MACConfiguration; /* 248 xf8 */ >- __le32 port_err_status; /* 252 xfc COR */ >+ __le32 ext_hw_conf; /* 0x50 R/W */ >+ __le32 rsrvd0; /* 0x54 */ >+ __le32 port_ctrl; /* 0x58 */ >+ __le32 port_status; /* 0x5c */ >+ __le32 rsrvd1[32]; /* 0x60-0xdf */ >+ __le32 gp_out; /* 0xe0 */ >+ __le32 gp_in; /* 0xe4 */ >+ __le32 rsrvd2[5]; /* 0xe8-0xfb */ >+ __le32 port_err_status; /* 0xfc */ > }; > > struct host_mem_cfg_regs { >- __le32 NetRequestQueueOut; /* 80 x50 */ >- __le32 NetRequestQueueOutAddrHi; /* 84 x54 */ >- __le32 NetRequestQueueOutAddrLow; /* 88 x58 */ >- __le32 NetRequestQueueBaseAddrHi; /* 92 x5c */ >- __le32 NetRequestQueueBaseAddrLow; /* 96 x60 */ >- __le32 NetRequestQueueLength; /* 100 x64 */ >- __le32 NetResponseQueueIn; /* 104 x68 */ >- __le32 NetResponseQueueInAddrHi; /* 108 x6c */ >- __le32 NetResponseQueueInAddrLow; /* 112 x70 */ >- __le32 NetResponseQueueBaseAddrHi; /* 116 x74 */ >- __le32 NetResponseQueueBaseAddrLow; /* 120 x78 */ >- __le32 NetResponseQueueLength; /* 124 x7c */ >- __le32 req_q_out; /* 128 x80 */ >- __le32 RequestQueueOutAddrHi; /* 132 x84 */ >- __le32 RequestQueueOutAddrLow; /* 136 x88 */ >- __le32 RequestQueueBaseAddrHi; /* 140 x8c */ >- __le32 RequestQueueBaseAddrLow; /* 144 x90 */ >- __le32 RequestQueueLength; /* 148 x94 */ >- __le32 ResponseQueueIn; /* 152 x98 */ >- __le32 ResponseQueueInAddrHi; /* 156 x9c */ >- __le32 ResponseQueueInAddrLow; /* 160 xa0 */ >- __le32 ResponseQueueBaseAddrHi; /* 164 xa4 */ >- __le32 ResponseQueueBaseAddrLow; /* 168 xa8 */ >- __le32 ResponseQueueLength; /* 172 xac */ >- __le32 NetRxLargeBufferQueueOut; /* 176 xb0 */ >- __le32 NetRxLargeBufferQueueBaseAddrHi; /* 180 xb4 */ >- __le32 NetRxLargeBufferQueueBaseAddrLow; /* 184 xb8 */ >- __le32 NetRxLargeBufferQueueLength; /* 188 xbc */ >- __le32 NetRxLargeBufferLength; /* 192 xc0 */ >- __le32 NetRxSmallBufferQueueOut; /* 196 xc4 */ >- __le32 NetRxSmallBufferQueueBaseAddrHi; /* 200 xc8 */ >- __le32 NetRxSmallBufferQueueBaseAddrLow; /* 204 xcc */ >- __le32 NetRxSmallBufferQueueLength; /* 208 xd0 */ >- __le32 NetRxSmallBufferLength; /* 212 xd4 */ >- __le32 HMCReserved0[10]; /* 216 xd8 */ >-}; >- >-struct local_ram_cfg_regs { >- __le32 BufletSize; /* 80 x50 */ >- __le32 BufletMaxCount; /* 84 x54 */ >- __le32 BufletCurrCount; /* 88 x58 */ >- __le32 BufletPauseThresholdCount; /* 92 x5c */ >- __le32 BufletTCPWinThresholdHi; /* 96 x60 */ >- __le32 BufletTCPWinThresholdLow; /* 100 x64 */ >- __le32 IPHashTableBaseAddr; /* 104 x68 */ >- __le32 IPHashTableSize; /* 108 x6c */ >- __le32 TCPHashTableBaseAddr; /* 112 x70 */ >- __le32 TCPHashTableSize; /* 116 x74 */ >- __le32 NCBAreaBaseAddr; /* 120 x78 */ >- __le32 NCBMaxCount; /* 124 x7c */ >- __le32 NCBCurrCount; /* 128 x80 */ >- __le32 DRBAreaBaseAddr; /* 132 x84 */ >- __le32 DRBMaxCount; /* 136 x88 */ >- __le32 DRBCurrCount; /* 140 x8c */ >- __le32 LRCReserved[28]; /* 144 x90 */ >-}; >- >-struct prot_stat_regs { >- __le32 MACTxFrameCount; /* 80 x50 R */ >- __le32 MACTxByteCount; /* 84 x54 R */ >- __le32 MACRxFrameCount; /* 88 x58 R */ >- __le32 MACRxByteCount; /* 92 x5c R */ >- __le32 MACCRCErrCount; /* 96 x60 R */ >- __le32 MACEncErrCount; /* 100 x64 R */ >- __le32 MACRxLengthErrCount; /* 104 x68 R */ >- __le32 IPTxPacketCount; /* 108 x6c R */ >- __le32 IPTxByteCount; /* 112 x70 R */ >- __le32 IPTxFragmentCount; /* 116 x74 R */ >- __le32 IPRxPacketCount; /* 120 x78 R */ >- __le32 IPRxByteCount; /* 124 x7c R */ >- __le32 IPRxFragmentCount; /* 128 x80 R */ >- __le32 IPDatagramReassemblyCount; /* 132 x84 R */ >- __le32 IPV6RxPacketCount; /* 136 x88 R */ >- __le32 IPErrPacketCount; /* 140 x8c R */ >- __le32 IPReassemblyErrCount; /* 144 x90 R */ >- __le32 TCPTxSegmentCount; /* 148 x94 R */ >- __le32 TCPTxByteCount; /* 152 x98 R */ >- __le32 TCPRxSegmentCount; /* 156 x9c R */ >- __le32 TCPRxByteCount; /* 160 xa0 R */ >- __le32 TCPTimerExpCount; /* 164 xa4 R */ >- __le32 TCPRxAckCount; /* 168 xa8 R */ >- __le32 TCPTxAckCount; /* 172 xac R */ >- __le32 TCPRxErrOOOCount; /* 176 xb0 R */ >- __le32 PSReserved0; /* 180 xb4 */ >- __le32 TCPRxWindowProbeUpdateCount; /* 184 xb8 R */ >- __le32 ECCErrCorrectionCount; /* 188 xbc R */ >- __le32 PSReserved1[16]; /* 192 xc0 */ >+ __le32 rsrvd0[12]; /* 0x50-0x79 */ >+ __le32 req_q_out; /* 0x80 */ >+ __le32 rsrvd1[31]; /* 0x84-0xFF */ > }; > >- > /* remote register set (access via PCI memory read/write) */ > struct isp_reg { > #define MBOX_REG_COUNT 8 >@@ -207,11 +87,7 @@ struct isp_reg { > union { > struct port_ctrl_stat_regs p0; > struct host_mem_cfg_regs p1; >- struct local_ram_cfg_regs p2; >- struct prot_stat_regs p3; >- __le32 r_union[44]; > }; >- > } __attribute__ ((packed)) isp4022; > } u2; > }; /* 256 x100 */ >@@ -296,6 +172,7 @@ static inline uint32_t clr_rmask(uint32_ > /* ISP Semaphore definitions */ > > /* ISP General Purpose Output definitions */ >+#define GPOR_TOPCAT_RESET 0x00000004 > > /* shadow registers (DMA'd from HA to system memory. read only) */ > struct shadow_regs { >@@ -337,6 +214,7 @@ union external_hw_config_reg { > > /* Mailbox command definitions */ > #define MBOX_CMD_ABOUT_FW 0x0009 >+#define MBOX_CMD_PING 0x000B > #define MBOX_CMD_LUN_RESET 0x0016 > #define MBOX_CMD_GET_MANAGEMENT_DATA 0x001E > #define MBOX_CMD_GET_FW_STATUS 0x001F >@@ -364,6 +242,17 @@ union external_hw_config_reg { > #define MBOX_CMD_GET_FW_STATE 0x0069 > #define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A > #define MBOX_CMD_RESTORE_FACTORY_DEFAULTS 0x0087 >+#define MBOX_CMD_SET_ACB 0x0088 >+#define MBOX_CMD_GET_ACB 0x0089 >+#define MBOX_CMD_DISABLE_ACB 0x008A >+#define MBOX_CMD_GET_IPV6_NEIGHBOR_CACHE 0x008B >+#define MBOX_CMD_GET_IPV6_DEST_CACHE 0x008C >+#define MBOX_CMD_GET_IPV6_DEF_ROUTER_LIST 0x008D >+#define MBOX_CMD_GET_IPV6_LCL_PREFIX_LIST 0x008E >+#define MBOX_CMD_SET_IPV6_NEIGHBOR_CACHE 0x0090 >+#define MBOX_CMD_GET_IP_ADDR_STATE 0x0091 >+#define MBOX_CMD_SEND_IPV6_ROUTER_SOL 0x0092 >+#define MBOX_CMD_GET_DB_ENTRY_CURRENT_IP_ADDR 0x0093 > > /* Mailbox 1 */ > #define FW_STATE_READY 0x0000 >@@ -409,6 +298,16 @@ union external_hw_config_reg { > #define MBOX_ASTS_DHCP_LEASE_EXPIRED 0x801D > #define MBOX_ASTS_DHCP_LEASE_ACQUIRED 0x801F > #define MBOX_ASTS_ISNS_UNSOLICITED_PDU_RECEIVED 0x8021 >+#define MBOX_ASTS_DUPLICATE_IP 0x8025 >+#define MBOX_ASTS_ARP_COMPLETE 0x8026 >+#define MBOX_ASTS_SUBNET_STATE_CHANGE 0x8027 >+#define MBOX_ASTS_RESPONSE_QUEUE_FULL 0x8028 >+#define MBOX_ASTS_IP_ADDR_STATE_CHANGED 0x8029 >+#define MBOX_ASTS_IPV6_PREFIX_EXPIRED 0x802B >+#define MBOX_ASTS_IPV6_ND_PREFIX_IGNORED 0x802C >+#define MBOX_ASTS_IPV6_LCL_PREFIX_IGNORED 0x802D >+#define MBOX_ASTS_ICMPV6_ERROR_MSG_RCVD 0x802E >+ > #define ISNS_EVENT_DATA_RECEIVED 0x0000 > #define ISNS_EVENT_CONNECTION_OPENED 0x0001 > #define ISNS_EVENT_CONNECTION_FAILED 0x0002 >@@ -418,137 +317,166 @@ union external_hw_config_reg { > /*************************************************************************/ > > /* Host Adapter Initialization Control Block (from host) */ >-struct init_fw_ctrl_blk { >- uint8_t Version; /* 00 */ >- uint8_t Control; /* 01 */ >+struct addr_ctrl_blk { >+ uint8_t version; /* 00 */ >+ uint8_t control; /* 01 */ > >- uint16_t FwOptions; /* 02-03 */ >+ uint16_t fw_options; /* 02-03 */ > #define FWOPT_HEARTBEAT_ENABLE 0x1000 > #define FWOPT_SESSION_MODE 0x0040 > #define FWOPT_INITIATOR_MODE 0x0020 > #define FWOPT_TARGET_MODE 0x0010 > >- uint16_t ExecThrottle; /* 04-05 */ >- uint8_t RetryCount; /* 06 */ >- uint8_t RetryDelay; /* 07 */ >- uint16_t MaxEthFrPayloadSize; /* 08-09 */ >- uint16_t AddFwOptions; /* 0A-0B */ >- >- uint8_t HeartbeatInterval; /* 0C */ >- uint8_t InstanceNumber; /* 0D */ >- uint16_t RES2; /* 0E-0F */ >- uint16_t ReqQConsumerIndex; /* 10-11 */ >- uint16_t ComplQProducerIndex; /* 12-13 */ >- uint16_t ReqQLen; /* 14-15 */ >- uint16_t ComplQLen; /* 16-17 */ >- uint32_t ReqQAddrLo; /* 18-1B */ >- uint32_t ReqQAddrHi; /* 1C-1F */ >- uint32_t ComplQAddrLo; /* 20-23 */ >- uint32_t ComplQAddrHi; /* 24-27 */ >- uint32_t ShadowRegBufAddrLo; /* 28-2B */ >- uint32_t ShadowRegBufAddrHi; /* 2C-2F */ >- >- uint16_t iSCSIOptions; /* 30-31 */ >- >- uint16_t TCPOptions; /* 32-33 */ >- >- uint16_t IPOptions; /* 34-35 */ >- >- uint16_t MaxPDUSize; /* 36-37 */ >- uint16_t RcvMarkerInt; /* 38-39 */ >- uint16_t SndMarkerInt; /* 3A-3B */ >- uint16_t InitMarkerlessInt; /* 3C-3D */ >- uint16_t FirstBurstSize; /* 3E-3F */ >- uint16_t DefaultTime2Wait; /* 40-41 */ >- uint16_t DefaultTime2Retain; /* 42-43 */ >- uint16_t MaxOutStndngR2T; /* 44-45 */ >- uint16_t KeepAliveTimeout; /* 46-47 */ >- uint16_t PortNumber; /* 48-49 */ >- uint16_t MaxBurstSize; /* 4A-4B */ >- uint32_t RES4; /* 4C-4F */ >- uint8_t IPAddr[4]; /* 50-53 */ >- uint8_t RES5[12]; /* 54-5F */ >- uint8_t SubnetMask[4]; /* 60-63 */ >- uint8_t RES6[12]; /* 64-6F */ >- uint8_t GatewayIPAddr[4]; /* 70-73 */ >- uint8_t RES7[12]; /* 74-7F */ >- uint8_t PriDNSIPAddr[4]; /* 80-83 */ >- uint8_t SecDNSIPAddr[4]; /* 84-87 */ >- uint8_t RES8[8]; /* 88-8F */ >- uint8_t Alias[32]; /* 90-AF */ >- uint8_t TargAddr[8]; /* B0-B7 *//* /FIXME: Remove?? */ >- uint8_t CHAPNameSecretsTable[8]; /* B8-BF */ >- uint8_t EthernetMACAddr[6]; /* C0-C5 */ >- uint16_t TargetPortalGroup; /* C6-C7 */ >- uint8_t SendScale; /* C8 */ >- uint8_t RecvScale; /* C9 */ >- uint8_t TypeOfService; /* CA */ >- uint8_t Time2Live; /* CB */ >- uint16_t VLANPriority; /* CC-CD */ >- uint16_t Reserved8; /* CE-CF */ >- uint8_t SecIPAddr[4]; /* D0-D3 */ >- uint8_t Reserved9[12]; /* D4-DF */ >- uint8_t iSNSIPAddr[4]; /* E0-E3 */ >- uint16_t iSNSServerPortNumber; /* E4-E5 */ >- uint8_t Reserved10[10]; /* E6-EF */ >- uint8_t SLPDAIPAddr[4]; /* F0-F3 */ >- uint8_t Reserved11[12]; /* F4-FF */ >- uint8_t iSCSINameString[256]; /* 100-1FF */ >+ uint16_t exec_throttle; /* 04-05 */ >+ uint8_t zio_count; /* 06 */ >+ uint8_t res0; /* 07 */ >+ uint16_t eth_mtu_size; /* 08-09 */ >+ uint16_t add_fw_options; /* 0A-0B */ >+ >+ uint8_t hb_interval; /* 0C */ >+ uint8_t inst_num; /* 0D */ >+ uint16_t res1; /* 0E-0F */ >+ uint16_t rqq_consumer_idx; /* 10-11 */ >+ uint16_t compq_producer_idx; /* 12-13 */ >+ uint16_t rqq_len; /* 14-15 */ >+ uint16_t compq_len; /* 16-17 */ >+ uint32_t rqq_addr_lo; /* 18-1B */ >+ uint32_t rqq_addr_hi; /* 1C-1F */ >+ uint32_t compq_addr_lo; /* 20-23 */ >+ uint32_t compq_addr_hi; /* 24-27 */ >+ uint32_t shdwreg_addr_lo; /* 28-2B */ >+ uint32_t shdwreg_addr_hi; /* 2C-2F */ >+ >+ uint16_t iscsi_opts; /* 30-31 */ >+ uint16_t ipv4_tcp_opts; /* 32-33 */ >+ uint16_t ipv4_ip_opts; /* 34-35 */ >+ >+ uint16_t iscsi_max_pdu_size; /* 36-37 */ >+ uint8_t ipv4_tos; /* 38 */ >+ uint8_t ipv4_ttl; /* 39 */ >+ uint8_t acb_version; /* 3A */ >+ uint8_t res2; /* 3B */ >+ uint16_t def_timeout; /* 3C-3D */ >+ uint16_t iscsi_fburst_len; /* 3E-3F */ >+ uint16_t iscsi_def_time2wait; /* 40-41 */ >+ uint16_t iscsi_def_time2retain; /* 42-43 */ >+ uint16_t iscsi_max_outstnd_r2t; /* 44-45 */ >+ uint16_t conn_ka_timeout; /* 46-47 */ >+ uint16_t ipv4_port; /* 48-49 */ >+ uint16_t iscsi_max_burst_len; /* 4A-4B */ >+ uint32_t res5; /* 4C-4F */ >+ uint8_t ipv4_addr[4]; /* 50-53 */ >+ uint16_t ipv4_vlan_tag; /* 54-55 */ >+ uint8_t ipv4_addr_state; /* 56 */ >+ uint8_t ipv4_cacheid; /* 57 */ >+ uint8_t res6[8]; /* 58-5F */ >+ uint8_t ipv4_subnet[4]; /* 60-63 */ >+ uint8_t res7[12]; /* 64-6F */ >+ uint8_t ipv4_gw_addr[4]; /* 70-73 */ >+ uint8_t res8[0xc]; /* 74-7F */ >+ uint8_t pri_dns_srvr_ip[4];/* 80-83 */ >+ uint8_t sec_dns_srvr_ip[4];/* 84-87 */ >+ uint16_t min_eph_port; /* 88-89 */ >+ uint16_t max_eph_port; /* 8A-8B */ >+ uint8_t res9[4]; /* 8C-8F */ >+ uint8_t iscsi_alias[32];/* 90-AF */ >+ uint8_t res9_1[0x16]; /* B0-C5 */ >+ uint16_t tgt_portal_grp;/* C6-C7 */ >+ uint8_t abort_timer; /* C8 */ >+ uint8_t ipv4_tcp_wsf; /* C9 */ >+ uint8_t res10[6]; /* CA-CF */ >+ uint8_t ipv4_sec_ip_addr[4]; /* D0-D3 */ >+ uint8_t ipv4_dhcp_vid_len; /* D4 */ >+ uint8_t ipv4_dhcp_vid[11]; /* D5-DF */ >+ uint8_t res11[20]; /* E0-F3 */ >+ uint8_t ipv4_dhcp_alt_cid_len; /* F4 */ >+ uint8_t ipv4_dhcp_alt_cid[11]; /* F5-FF */ >+ uint8_t iscsi_name[224]; /* 100-1DF */ >+ uint8_t res12[32]; /* 1E0-1FF */ >+ uint32_t cookie; /* 200-203 */ >+ uint16_t ipv6_port; /* 204-205 */ >+ uint16_t ipv6_opts; /* 206-207 */ >+ uint16_t ipv6_addtl_opts; /* 208-209 */ >+ uint16_t ipv6_tcp_opts; /* 20A-20B */ >+ uint8_t ipv6_tcp_wsf; /* 20C */ >+ uint16_t ipv6_flow_lbl; /* 20D-20F */ >+ uint8_t ipv6_gw_addr[16]; /* 210-21F */ >+ uint16_t ipv6_vlan_tag; /* 220-221 */ >+ uint8_t ipv6_lnk_lcl_addr_state;/* 222 */ >+ uint8_t ipv6_addr0_state; /* 223 */ >+ uint8_t ipv6_addr1_state; /* 224 */ >+ uint8_t ipv6_gw_state; /* 225 */ >+ uint8_t ipv6_traffic_class; /* 226 */ >+ uint8_t ipv6_hop_limit; /* 227 */ >+ uint8_t ipv6_if_id[8]; /* 228-22F */ >+ uint8_t ipv6_addr0[16]; /* 230-23F */ >+ uint8_t ipv6_addr1[16]; /* 240-24F */ >+ uint32_t ipv6_nd_reach_time; /* 250-253 */ >+ uint32_t ipv6_nd_rexmit_timer; /* 254-257 */ >+ uint32_t ipv6_nd_stale_timeout; /* 258-25B */ >+ uint8_t ipv6_dup_addr_detect_count; /* 25C */ >+ uint8_t ipv6_cache_id; /* 25D */ >+ uint8_t res13[18]; /* 25E-26F */ >+ uint32_t ipv6_gw_advrt_mtu; /* 270-273 */ >+ uint8_t res14[140]; /* 274-2FF */ >+}; >+ >+struct init_fw_ctrl_blk { >+ struct addr_ctrl_blk pri; >+ struct addr_ctrl_blk sec; > }; > > /*************************************************************************/ > > struct dev_db_entry { >- uint8_t options; /* 00 */ >+ uint16_t options; /* 00-01 */ > #define DDB_OPT_DISC_SESSION 0x10 > #define DDB_OPT_TARGET 0x02 /* device is a target */ > >- uint8_t control; /* 01 */ >- >- uint16_t exeThrottle; /* 02-03 */ >- uint16_t exeCount; /* 04-05 */ >- uint8_t retryCount; /* 06 */ >- uint8_t retryDelay; /* 07 */ >- uint16_t iSCSIOptions; /* 08-09 */ >- >- uint16_t TCPOptions; /* 0A-0B */ >- >- uint16_t IPOptions; /* 0C-0D */ >- >- uint16_t maxPDUSize; /* 0E-0F */ >- uint16_t rcvMarkerInt; /* 10-11 */ >- uint16_t sndMarkerInt; /* 12-13 */ >- uint16_t iSCSIMaxSndDataSegLen; /* 14-15 */ >- uint16_t firstBurstSize; /* 16-17 */ >- uint16_t minTime2Wait; /* 18-19 : RA :default_time2wait */ >- uint16_t maxTime2Retain; /* 1A-1B */ >- uint16_t maxOutstndngR2T; /* 1C-1D */ >- uint16_t keepAliveTimeout; /* 1E-1F */ >- uint8_t ISID[6]; /* 20-25 big-endian, must be converted >+ uint16_t exec_throttle; /* 02-03 */ >+ uint16_t exec_count; /* 04-05 */ >+ uint16_t res0; /* 06-07 */ >+ uint16_t iscsi_options; /* 08-09 */ >+ uint16_t tcp_options; /* 0A-0B */ >+ uint16_t ip_options; /* 0C-0D */ >+ uint16_t iscsi_max_rcv_data_seg_len; /* 0E-0F */ >+ uint32_t res1; /* 10-13 */ >+ uint16_t iscsi_max_snd_data_seg_len; /* 14-15 */ >+ uint16_t iscsi_first_burst_len; /* 16-17 */ >+ uint16_t iscsi_def_time2wait; /* 18-19 */ >+ uint16_t iscsi_def_time2retain; /* 1A-1B */ >+ uint16_t iscsi_max_outsnd_r2t; /* 1C-1D */ >+ uint16_t ka_timeout; /* 1E-1F */ >+ uint8_t isid[6]; /* 20-25 big-endian, must be converted > * to little-endian */ >- uint16_t TSID; /* 26-27 */ >- uint16_t portNumber; /* 28-29 */ >- uint16_t maxBurstSize; /* 2A-2B */ >- uint16_t taskMngmntTimeout; /* 2C-2D */ >- uint16_t reserved1; /* 2E-2F */ >- uint8_t ipAddr[0x10]; /* 30-3F */ >- uint8_t iSCSIAlias[0x20]; /* 40-5F */ >- uint8_t targetAddr[0x20]; /* 60-7F */ >- uint8_t userID[0x20]; /* 80-9F */ >- uint8_t password[0x20]; /* A0-BF */ >- uint8_t iscsiName[0x100]; /* C0-1BF : xxzzy Make this a >+ uint16_t tsid; /* 26-27 */ >+ uint16_t port; /* 28-29 */ >+ uint16_t iscsi_max_burst_len; /* 2A-2B */ >+ uint16_t def_timeout; /* 2C-2D */ >+ uint16_t res2; /* 2E-2F */ >+ uint8_t ip_addr[0x10]; /* 30-3F */ >+ uint8_t iscsi_alias[0x20]; /* 40-5F */ >+ uint8_t tgt_addr[0x20]; /* 60-7F */ >+ uint16_t mss; /* 80-81 */ >+ uint16_t res3; /* 82-83 */ >+ uint16_t lcl_port; /* 84-85 */ >+ uint8_t ipv4_tos; /* 86 */ >+ uint16_t ipv6_flow_lbl; /* 87-89 */ >+ uint8_t res4[0x36]; /* 8A-BF */ >+ uint8_t iscsi_name[0xE0]; /* C0-19F : xxzzy Make this a > * pointer to a string so we > * don't have to reserve soooo > * much RAM */ >- uint16_t ddbLink; /* 1C0-1C1 */ >- uint16_t CHAPTableIndex; /* 1C2-1C3 */ >- uint16_t TargetPortalGroup; /* 1C4-1C5 */ >- uint16_t reserved2[2]; /* 1C6-1C7 */ >- uint32_t statSN; /* 1C8-1CB */ >- uint32_t expStatSN; /* 1CC-1CF */ >- uint16_t reserved3[0x2C]; /* 1D0-1FB */ >- uint16_t ddbValidCookie; /* 1FC-1FD */ >- uint16_t ddbValidSize; /* 1FE-1FF */ >+ uint8_t ipv6_addr[0x10];/* 1A0-1AF */ >+ uint8_t res5[0x10]; /* 1B0-1BF */ >+ uint16_t ddb_link; /* 1C0-1C1 */ >+ uint16_t chap_tbl_idx; /* 1C2-1C3 */ >+ uint16_t tgt_portal_grp; /* 1C4-1C5 */ >+ uint8_t tcp_xmt_wsf; /* 1C6 */ >+ uint8_t tcp_rcv_wsf; /* 1C7 */ >+ uint32_t stat_sn; /* 1C8-1CB */ >+ uint32_t exp_stat_sn; /* 1CC-1CF */ >+ uint8_t res6[0x30]; /* 1D0-1FF */ > }; > > /*************************************************************************/ >diff -aurp linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_glbl.h linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_glbl.h >--- linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_glbl.h 2007-10-22 10:47:06.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_glbl.h 2007-10-25 01:07:47.000000000 -0500 >@@ -8,6 +8,9 @@ > #ifndef __QLA4x_GBL_H > #define __QLA4x_GBL_H > >+struct iscsi_cls_conn; >+ >+void qla4xxx_hw_reset(struct scsi_qla_host *ha); > int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a); > int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port); > int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb); >@@ -43,8 +46,6 @@ int qla4xxx_get_fwddb_entry(struct scsi_ > uint16_t *tcp_source_port_num, > uint16_t *connection_id); > >-struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host * ha, >- uint32_t fw_ddb_index); > int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index, > dma_addr_t fw_ddb_entry_dma); > >@@ -53,25 +54,20 @@ void qla4xxx_mark_device_missing(struct > u16 rd_nvram_word(struct scsi_qla_host * ha, int offset); > void qla4xxx_get_crash_record(struct scsi_qla_host * ha); > struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha); >-int qla4xxx_add_sess(struct ddb_entry *); >+int qla4xxx_add_sess(struct ddb_entry *, int); > void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry); >-int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha, >- uint16_t fw_ddb_index, >- uint16_t connection_id, >- uint16_t option); >-int qla4xxx_clear_database_entry(struct scsi_qla_host * ha, >- uint16_t fw_ddb_index); > int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host * ha); > int qla4xxx_get_fw_version(struct scsi_qla_host * ha); > void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha, > uint32_t intr_status); > int qla4xxx_init_rings(struct scsi_qla_host * ha); >-void qla4xxx_dump_buffer(void *b, uint32_t size); >-struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t index); >+struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, >+ uint32_t index); > void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb); > int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha); > int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha, > uint32_t fw_ddb_index, uint32_t state); >+void qla4xxx_dump_buffer(void *b, uint32_t size); > > extern int ql4xextended_error_logging; > extern int ql4xdiscoverywait; >diff -aurp linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_init.c linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_init.c >--- linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_init.c 2007-10-22 10:47:06.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_init.c 2007-10-25 01:07:32.000000000 -0500 >@@ -5,11 +5,14 @@ > * See LICENSE.qla4xxx for copyright and licensing details. > */ > >+#include <scsi/iscsi_if.h> > #include "ql4_def.h" >+#include "ql4_glbl.h" >+#include "ql4_dbg.h" >+#include "ql4_inline.h" > >-/* >- * QLogic ISP4xxx Hardware Support Function Prototypes. >- */ >+static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, >+ uint32_t fw_ddb_index); > > static void ql4xxx_set_mac_number(struct scsi_qla_host *ha) > { >@@ -48,7 +51,8 @@ static void ql4xxx_set_mac_number(struct > * This routine deallocates and unlinks the specified ddb_entry from the > * adapter's > **/ >-void qla4xxx_free_ddb(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry) >+static void qla4xxx_free_ddb(struct scsi_qla_host *ha, >+ struct ddb_entry *ddb_entry) > { > /* Remove device entry from list */ > list_del_init(&ddb_entry->list); >@@ -300,12 +304,12 @@ static int qla4xxx_init_firmware(struct > if (!qla4xxx_fw_ready(ha)) > return status; > >- set_bit(AF_ONLINE, &ha->flags); > return qla4xxx_get_firmware_status(ha); > } > > static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha, >- uint32_t fw_ddb_index) >+ uint32_t fw_ddb_index, >+ uint32_t *new_tgt) > { > struct dev_db_entry *fw_ddb_entry = NULL; > dma_addr_t fw_ddb_entry_dma; >@@ -313,6 +317,7 @@ static struct ddb_entry* qla4xxx_get_ddb > int found = 0; > uint32_t device_state; > >+ *new_tgt = 0; > /* Make sure the dma buffer is valid */ > fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, > sizeof(*fw_ddb_entry), >@@ -337,7 +342,7 @@ static struct ddb_entry* qla4xxx_get_ddb > DEBUG2(printk("scsi%ld: %s: Looking for ddb[%d]\n", ha->host_no, > __func__, fw_ddb_index)); > list_for_each_entry(ddb_entry, &ha->ddb_list, list) { >- if (memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsiName, >+ if (memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsi_name, > ISCSI_NAME_SIZE) == 0) { > found++; > break; >@@ -348,6 +353,7 @@ static struct ddb_entry* qla4xxx_get_ddb > DEBUG2(printk("scsi%ld: %s: ddb[%d] not found - allocating " > "new ddb\n", ha->host_no, __func__, > fw_ddb_index)); >+ *new_tgt = 1; > ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index); > } > >@@ -370,9 +376,9 @@ static struct ddb_entry* qla4xxx_get_ddb > * must be initialized prior to calling this routine > * > **/ >-int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, >- struct ddb_entry *ddb_entry, >- uint32_t fw_ddb_index) >+static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha, >+ struct ddb_entry *ddb_entry, >+ uint32_t fw_ddb_index) > { > struct dev_db_entry *fw_ddb_entry = NULL; > dma_addr_t fw_ddb_entry_dma; >@@ -409,26 +415,26 @@ int qla4xxx_update_ddb_entry(struct scsi > } > > status = QLA_SUCCESS; >- ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->TSID); >+ ddb_entry->target_session_id = le16_to_cpu(fw_ddb_entry->tsid); > ddb_entry->task_mgmt_timeout = >- le16_to_cpu(fw_ddb_entry->taskMngmntTimeout); >+ le16_to_cpu(fw_ddb_entry->def_timeout); > ddb_entry->CmdSn = 0; >- ddb_entry->exe_throttle = le16_to_cpu(fw_ddb_entry->exeThrottle); >+ ddb_entry->exe_throttle = le16_to_cpu(fw_ddb_entry->exec_throttle); > ddb_entry->default_relogin_timeout = >- le16_to_cpu(fw_ddb_entry->taskMngmntTimeout); >- ddb_entry->default_time2wait = le16_to_cpu(fw_ddb_entry->minTime2Wait); >+ le16_to_cpu(fw_ddb_entry->def_timeout); >+ ddb_entry->default_time2wait = le16_to_cpu(fw_ddb_entry->iscsi_def_time2wait); > > /* Update index in case it changed */ > ddb_entry->fw_ddb_index = fw_ddb_index; > ha->fw_ddb_index_map[fw_ddb_index] = ddb_entry; > >- ddb_entry->port = le16_to_cpu(fw_ddb_entry->portNumber); >- ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->TargetPortalGroup); >- memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsiName[0], >+ ddb_entry->port = le16_to_cpu(fw_ddb_entry->port); >+ ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp); >+ memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsi_name[0], > min(sizeof(ddb_entry->iscsi_name), >- sizeof(fw_ddb_entry->iscsiName))); >- memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ipAddr[0], >- min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ipAddr))); >+ sizeof(fw_ddb_entry->iscsi_name))); >+ memcpy(&ddb_entry->ip_addr[0], &fw_ddb_entry->ip_addr[0], >+ min(sizeof(ddb_entry->ip_addr), sizeof(fw_ddb_entry->ip_addr))); > > DEBUG2(printk("scsi%ld: %s: ddb[%d] - State= %x status= %d.\n", > ha->host_no, __func__, fw_ddb_index, >@@ -450,8 +456,8 @@ int qla4xxx_update_ddb_entry(struct scsi > * This routine allocates a ddb_entry, ititializes some values, and > * inserts it into the ddb list. > **/ >-struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, >- uint32_t fw_ddb_index) >+static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, >+ uint32_t fw_ddb_index) > { > struct ddb_entry *ddb_entry; > >@@ -495,6 +501,7 @@ static int qla4xxx_build_ddb_list(struct > uint32_t ddb_state; > uint32_t conn_err, err_code; > struct ddb_entry *ddb_entry; >+ uint32_t new_tgt; > > dev_info(&ha->pdev->dev, "Initializing DDBs ...\n"); > for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES; >@@ -526,8 +533,19 @@ static int qla4xxx_build_ddb_list(struct > "completed " > "or access denied failure\n", > ha->host_no, __func__)); >- } else >+ } else { > qla4xxx_set_ddb_entry(ha, fw_ddb_index, 0); >+ if (qla4xxx_get_fwddb_entry(ha, fw_ddb_index, >+ NULL, 0, NULL, &next_fw_ddb_index, >+ &ddb_state, &conn_err, NULL, NULL) >+ == QLA_ERROR) { >+ DEBUG2(printk("scsi%ld: %s:" >+ "get_ddb_entry %d failed\n", >+ ha->host_no, >+ __func__, fw_ddb_index)); >+ return QLA_ERROR; >+ } >+ } > } > > if (ddb_state != DDB_DS_SESSION_ACTIVE) >@@ -540,7 +558,7 @@ static int qla4xxx_build_ddb_list(struct > ha->host_no, __func__, fw_ddb_index)); > > /* Add DDB to internal our ddb list. */ >- ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index); >+ ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index, &new_tgt); > if (ddb_entry == NULL) { > DEBUG2(printk("scsi%ld: %s: Unable to allocate memory " > "for device at fw_ddb_index %d\n", >@@ -865,21 +883,20 @@ static int qla4xxx_config_nvram(struct s > > static void qla4x00_pci_config(struct scsi_qla_host *ha) > { >- uint16_t w, mwi; >+ uint16_t w; >+ int status; > > dev_info(&ha->pdev->dev, "Configuring PCI space...\n"); > > pci_set_master(ha->pdev); >- mwi = 0; >- if (pci_set_mwi(ha->pdev)) >- mwi = PCI_COMMAND_INVALIDATE; >+ status = pci_set_mwi(ha->pdev); > /* > * We want to respect framework's setting of PCI configuration space > * command register and also want to make sure that all bits of > * interest to us are properly set in command register. > */ > pci_read_config_word(ha->pdev, PCI_COMMAND, &w); >- w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR); >+ w |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR; > w &= ~PCI_COMMAND_INTX_DISABLE; > pci_write_config_word(ha->pdev, PCI_COMMAND, w); > } >@@ -911,6 +928,9 @@ static int qla4xxx_start_firmware_from_f > writel(set_rmask(NVR_WRITE_ENABLE), > &ha->reg->u1.isp4022.nvram); > >+ writel(2, &ha->reg->mailbox[6]); >+ readl(&ha->reg->mailbox[6]); >+ > writel(set_rmask(CSR_BOOT_ENABLE), &ha->reg->ctrl_status); > readl(&ha->reg->ctrl_status); > spin_unlock_irqrestore(&ha->hardware_lock, flags); >@@ -958,25 +978,25 @@ static int qla4xxx_start_firmware_from_f > return status; > } > >-int ql4xxx_lock_drvr_wait(struct scsi_qla_host *ha) >+int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a) > { >-#define QL4_LOCK_DRVR_WAIT 30 >+#define QL4_LOCK_DRVR_WAIT 60 > #define QL4_LOCK_DRVR_SLEEP 1 > > int drvr_wait = QL4_LOCK_DRVR_WAIT; > while (drvr_wait) { >- if (ql4xxx_lock_drvr(ha) == 0) { >+ if (ql4xxx_lock_drvr(a) == 0) { > ssleep(QL4_LOCK_DRVR_SLEEP); > if (drvr_wait) { > DEBUG2(printk("scsi%ld: %s: Waiting for " >- "Global Init Semaphore(%d)...n", >- ha->host_no, >+ "Global Init Semaphore(%d)...\n", >+ a->host_no, > __func__, drvr_wait)); > } > drvr_wait -= QL4_LOCK_DRVR_SLEEP; > } else { > DEBUG2(printk("scsi%ld: %s: Global Init Semaphore " >- "acquired.n", ha->host_no, __func__)); >+ "acquired\n", a->host_no, __func__)); > return QLA_SUCCESS; > } > } >@@ -1125,17 +1145,17 @@ int qla4xxx_initialize_adapter(struct sc > > /* Initialize the Host adapter request/response queues and firmware */ > if (qla4xxx_start_firmware(ha) == QLA_ERROR) >- return status; >+ goto exit_init_hba; > > if (qla4xxx_validate_mac_address(ha) == QLA_ERROR) >- return status; >+ goto exit_init_hba; > > if (qla4xxx_init_local_data(ha) == QLA_ERROR) >- return status; >+ goto exit_init_hba; > > status = qla4xxx_init_firmware(ha); > if (status == QLA_ERROR) >- return status; >+ goto exit_init_hba; > > /* > * FW is waiting to get an IP address from DHCP server: Skip building >@@ -1143,12 +1163,12 @@ int qla4xxx_initialize_adapter(struct sc > * followed by 0x8014 aen" to trigger the tgt discovery process. > */ > if (ha->firmware_state & FW_STATE_DHCP_IN_PROGRESS) >- return status; >+ goto exit_init_online; > > /* Skip device discovery if ip and subnet is zero */ > if (memcmp(ha->ip_address, ip_address, IP_ADDR_LEN) == 0 || > memcmp(ha->subnet_mask, ip_address, IP_ADDR_LEN) == 0) >- return status; >+ goto exit_init_online; > > if (renew_ddb_list == PRESERVE_DDB_LIST) { > /* >@@ -1177,9 +1197,10 @@ int qla4xxx_initialize_adapter(struct sc > ha->host_no)); > } > >- exit_init_hba: >+exit_init_online: >+ set_bit(AF_ONLINE, &ha->flags); >+exit_init_hba: > return status; >- > } > > /** >@@ -1193,9 +1214,10 @@ static void qla4xxx_add_device_dynamical > uint32_t fw_ddb_index) > { > struct ddb_entry * ddb_entry; >+ uint32_t new_tgt; > > /* First allocate a device structure */ >- ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index); >+ ddb_entry = qla4xxx_get_ddb_entry(ha, fw_ddb_index, &new_tgt); > if (ddb_entry == NULL) { > DEBUG2(printk(KERN_WARNING > "scsi%ld: Unable to allocate memory to add " >@@ -1203,6 +1225,18 @@ static void qla4xxx_add_device_dynamical > return; > } > >+ if (!new_tgt && (ddb_entry->fw_ddb_index != fw_ddb_index)) { >+ /* Target has been bound to a new fw_ddb_index */ >+ qla4xxx_free_ddb(ha, ddb_entry); >+ ddb_entry = qla4xxx_alloc_ddb(ha, fw_ddb_index); >+ if (ddb_entry == NULL) { >+ DEBUG2(printk(KERN_WARNING >+ "scsi%ld: Unable to allocate memory" >+ " to add fw_ddb_index %d\n", >+ ha->host_no, fw_ddb_index)); >+ return; >+ } >+ } > if (qla4xxx_update_ddb_entry(ha, ddb_entry, fw_ddb_index) == > QLA_ERROR) { > ha->fw_ddb_index_map[fw_ddb_index] = >@@ -1215,7 +1249,7 @@ static void qla4xxx_add_device_dynamical > return; > } > >- if (qla4xxx_add_sess(ddb_entry)) { >+ if (qla4xxx_add_sess(ddb_entry, 0)) { > DEBUG2(printk(KERN_WARNING > "scsi%ld: failed to add new device at index " > "[%d]\n Unable to add connection and session\n", >diff -aurp linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_iocb.c linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_iocb.c >--- linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_iocb.c 2007-10-22 10:47:06.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_iocb.c 2007-10-24 22:26:00.000000000 -0500 >@@ -6,6 +6,10 @@ > */ > > #include "ql4_def.h" >+#include "ql4_glbl.h" >+#include "ql4_dbg.h" >+#include "ql4_inline.h" >+ > > #include <scsi/scsi_tcq.h> > >@@ -19,8 +23,8 @@ > * - advances the request_in pointer > * - checks for queue full > **/ >-int qla4xxx_get_req_pkt(struct scsi_qla_host *ha, >- struct queue_entry **queue_entry) >+static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha, >+ struct queue_entry **queue_entry) > { > uint16_t request_in; > uint8_t status = QLA_SUCCESS; >@@ -62,8 +66,8 @@ int qla4xxx_get_req_pkt(struct scsi_qla_ > * > * This routine issues a marker IOCB. > **/ >-int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, >- struct ddb_entry *ddb_entry, int lun) >+static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, >+ struct ddb_entry *ddb_entry, int lun) > { > struct marker_entry *marker_entry; > unsigned long flags = 0; >@@ -96,7 +100,7 @@ exit_send_marker: > return status; > } > >-struct continuation_t1_entry* qla4xxx_alloc_cont_entry( >+static struct continuation_t1_entry* qla4xxx_alloc_cont_entry( > struct scsi_qla_host *ha) > { > struct continuation_t1_entry *cont_entry; >@@ -120,7 +124,7 @@ struct continuation_t1_entry* qla4xxx_al > return cont_entry; > } > >-uint16_t qla4xxx_calc_request_entries(uint16_t dsds) >+static uint16_t qla4xxx_calc_request_entries(uint16_t dsds) > { > uint16_t iocbs; > >diff -aurp linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_isr.c linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_isr.c >--- linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_isr.c 2007-10-22 10:47:06.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_isr.c 2007-10-24 22:26:00.000000000 -0500 >@@ -6,6 +6,9 @@ > */ > > #include "ql4_def.h" >+#include "ql4_glbl.h" >+#include "ql4_dbg.h" >+#include "ql4_inline.h" > > /** > * qla2x00_process_completed_request() - Process a Fast Post response. >@@ -90,9 +93,29 @@ static void qla4xxx_status_entry(struct > break; > } > >- if (sts_entry->iscsiFlags & >- (ISCSI_FLAG_RESIDUAL_OVER|ISCSI_FLAG_RESIDUAL_UNDER)) >+ if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) { >+ cmd->result = DID_ERROR << 16; >+ break; >+ } >+ >+ if (sts_entry->iscsiFlags &ISCSI_FLAG_RESIDUAL_UNDER) { > cmd->resid = residual; >+ if (!scsi_status && ((cmd->request_bufflen - residual) < >+ cmd->underflow)) { >+ >+ cmd->result = DID_ERROR << 16; >+ >+ DEBUG2(printk("scsi%ld:%d:%d:%d: %s: " >+ "Mid-layer Data underrun0, " >+ "xferlen = 0x%x, " >+ "residual = 0x%x\n", ha->host_no, >+ cmd->device->channel, >+ cmd->device->id, >+ cmd->device->lun, __func__, >+ cmd->request_bufflen, residual)); >+ break; >+ } >+ } > > cmd->result = DID_OK << 16 | scsi_status; > >@@ -161,7 +184,8 @@ static void qla4xxx_status_entry(struct > > case SCS_DATA_UNDERRUN: > case SCS_DATA_OVERRUN: >- if (sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) { >+ if ((sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) || >+ (sts_entry->completionStatus == SCS_DATA_OVERRUN)) { > DEBUG2(printk("scsi%ld:%d:%d:%d: %s: " "Data overrun, " > "residual = 0x%x\n", ha->host_no, > cmd->device->channel, cmd->device->id, >@@ -171,21 +195,7 @@ static void qla4xxx_status_entry(struct > break; > } > >- if ((sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_UNDER) == 0) { >- /* >- * Firmware detected a SCSI transport underrun >- * condition >- */ >- cmd->resid = residual; >- DEBUG2(printk("scsi%ld:%d:%d:%d: %s: UNDERRUN status " >- "detected, xferlen = 0x%x, residual = " >- "0x%x\n", >- ha->host_no, cmd->device->channel, >- cmd->device->id, >- cmd->device->lun, __func__, >- cmd->request_bufflen, >- residual)); >- } >+ cmd->resid = residual; > > /* > * If there is scsi_status, it takes precedense over >@@ -417,6 +427,7 @@ static void qla4xxx_isr_decode_mailbox(s > uint32_t mbox_status) > { > int i; >+ uint32_t mbox_stat2, mbox_stat3; > > if ((mbox_status == MBOX_STS_BUSY) || > (mbox_status == MBOX_STS_INTERMEDIATE_COMPLETION) || >@@ -437,6 +448,12 @@ static void qla4xxx_isr_decode_mailbox(s > } else if (mbox_status >> 12 == MBOX_ASYNC_EVENT_STATUS) { > /* Immediately process the AENs that don't require much work. > * Only queue the database_changed AENs */ >+ if (ha->aen_log.count < MAX_AEN_ENTRIES) { >+ for (i = 0; i < MBOX_AEN_REG_COUNT; i++) >+ ha->aen_log.entry[ha->aen_log.count].mbox_sts[i] = >+ readl(&ha->reg->mailbox[i]); >+ ha->aen_log.count++; >+ } > switch (mbox_status) { > case MBOX_ASTS_SYSTEM_ERROR: > /* Log Mailbox registers */ >@@ -493,6 +510,16 @@ static void qla4xxx_isr_decode_mailbox(s > mbox_status)); > break; > >+ case MBOX_ASTS_IP_ADDR_STATE_CHANGED: >+ mbox_stat2 = readl(&ha->reg->mailbox[2]); >+ mbox_stat3 = readl(&ha->reg->mailbox[3]); >+ >+ if ((mbox_stat3 == 5) && (mbox_stat2 == 3)) >+ set_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags); >+ else if ((mbox_stat3 == 2) && (mbox_stat2 == 5)) >+ set_bit(DPC_RESET_HA, &ha->dpc_flags); >+ break; >+ > case MBOX_ASTS_MAC_ADDRESS_CHANGED: > case MBOX_ASTS_DNS: > /* No action */ >@@ -518,11 +545,6 @@ static void qla4xxx_isr_decode_mailbox(s > /* Queue AEN information and process it in the DPC > * routine */ > if (ha->aen_q_count > 0) { >- /* advance pointer */ >- if (ha->aen_in == (MAX_AEN_ENTRIES - 1)) >- ha->aen_in = 0; >- else >- ha->aen_in++; > > /* decrement available counter */ > ha->aen_q_count--; >@@ -542,6 +564,10 @@ static void qla4xxx_isr_decode_mailbox(s > ha->aen_q[ha->aen_in].mbox_sts[2], > ha->aen_q[ha->aen_in].mbox_sts[3], > ha->aen_q[ha->aen_in]. mbox_sts[4])); >+ /* advance pointer */ >+ ha->aen_in++; >+ if (ha->aen_in == MAX_AEN_ENTRIES) >+ ha->aen_in = 0; > > /* The DPC routine will process the aen */ > set_bit(DPC_AEN, &ha->dpc_flags); >@@ -724,25 +750,24 @@ void qla4xxx_process_aen(struct scsi_qla > > spin_lock_irqsave(&ha->hardware_lock, flags); > while (ha->aen_out != ha->aen_in) { >- /* Advance pointers for next entry */ >- if (ha->aen_out == (MAX_AEN_ENTRIES - 1)) >- ha->aen_out = 0; >- else >- ha->aen_out++; >- >- ha->aen_q_count++; > aen = &ha->aen_q[ha->aen_out]; >- > /* copy aen information to local structure */ > for (i = 0; i < MBOX_AEN_REG_COUNT; i++) > mbox_sts[i] = aen->mbox_sts[i]; > >+ ha->aen_q_count++; >+ ha->aen_out++; >+ >+ if (ha->aen_out == MAX_AEN_ENTRIES) >+ ha->aen_out = 0; >+ > spin_unlock_irqrestore(&ha->hardware_lock, flags); > >- DEBUG(printk("scsi%ld: AEN[%d] %04x, index [%d] state=%04x " >- "mod=%x conerr=%08x \n", ha->host_no, ha->aen_out, >- mbox_sts[0], mbox_sts[2], mbox_sts[3], >- mbox_sts[1], mbox_sts[4])); >+ DEBUG2(printk("qla4xxx(%ld): AEN[%d]=0x%08x, mbx1=0x%08x mbx2=0x%08x" >+ " mbx3=0x%08x mbx4=0x%08x\n", ha->host_no, >+ (ha->aen_out ? (ha->aen_out-1): (MAX_AEN_ENTRIES-1)), >+ mbox_sts[0], mbox_sts[1], mbox_sts[2], >+ mbox_sts[3], mbox_sts[4])); > > switch (mbox_sts[0]) { > case MBOX_ASTS_DATABASE_CHANGED: >@@ -792,6 +817,5 @@ void qla4xxx_process_aen(struct scsi_qla > spin_lock_irqsave(&ha->hardware_lock, flags); > } > spin_unlock_irqrestore(&ha->hardware_lock, flags); >- > } > >diff -aurp linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_mbx.c linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_mbx.c >--- linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_mbx.c 2007-10-22 10:47:06.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_mbx.c 2007-10-24 22:26:00.000000000 -0500 >@@ -6,6 +6,9 @@ > */ > > #include "ql4_def.h" >+#include "ql4_glbl.h" >+#include "ql4_dbg.h" >+#include "ql4_inline.h" > > > /** >@@ -20,9 +23,9 @@ > * If outCount is 0, this routine completes successfully WITHOUT waiting > * for the mailbox command to complete. > **/ >-int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, >- uint8_t outCount, uint32_t *mbx_cmd, >- uint32_t *mbx_sts) >+static int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, >+ uint8_t outCount, uint32_t *mbx_cmd, >+ uint32_t *mbx_sts) > { > int status = QLA_ERROR; > uint8_t i; >@@ -169,80 +172,6 @@ mbox_exit: > return status; > } > >- >-/** >- * qla4xxx_issue_iocb - issue mailbox iocb command >- * @ha: adapter state pointer. >- * @buffer: buffer pointer. >- * @phys_addr: physical address of buffer. >- * @size: size of buffer. >- * >- * Issues iocbs via mailbox commands. >- * TARGET_QUEUE_LOCK must be released. >- * ADAPTER_STATE_LOCK must be released. >- **/ >-int >-qla4xxx_issue_iocb(struct scsi_qla_host * ha, void *buffer, >- dma_addr_t phys_addr, size_t size) >-{ >- uint32_t mbox_cmd[MBOX_REG_COUNT]; >- uint32_t mbox_sts[MBOX_REG_COUNT]; >- int status; >- >- memset(&mbox_cmd, 0, sizeof(mbox_cmd)); >- memset(&mbox_sts, 0, sizeof(mbox_sts)); >- mbox_cmd[0] = MBOX_CMD_EXECUTE_IOCB_A64; >- mbox_cmd[1] = 0; >- mbox_cmd[2] = LSDW(phys_addr); >- mbox_cmd[3] = MSDW(phys_addr); >- status = qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]); >- return status; >-} >- >-int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha, >- uint16_t fw_ddb_index, >- uint16_t connection_id, >- uint16_t option) >-{ >- uint32_t mbox_cmd[MBOX_REG_COUNT]; >- uint32_t mbox_sts[MBOX_REG_COUNT]; >- >- memset(&mbox_cmd, 0, sizeof(mbox_cmd)); >- memset(&mbox_sts, 0, sizeof(mbox_sts)); >- mbox_cmd[0] = MBOX_CMD_CONN_CLOSE_SESS_LOGOUT; >- mbox_cmd[1] = fw_ddb_index; >- mbox_cmd[2] = connection_id; >- mbox_cmd[3] = LOGOUT_OPTION_RELOGIN; >- if (qla4xxx_mailbox_command(ha, 4, 2, &mbox_cmd[0], &mbox_sts[0]) != >- QLA_SUCCESS) { >- DEBUG2(printk("scsi%ld: %s: MBOX_CMD_CONN_CLOSE_SESS_LOGOUT " >- "option %04x failed sts %04X %04X", >- ha->host_no, __func__, >- option, mbox_sts[0], mbox_sts[1])); >- if (mbox_sts[0] == 0x4005) >- DEBUG2(printk("%s reason %04X\n", __func__, >- mbox_sts[1])); >- } >- return QLA_SUCCESS; >-} >- >-int qla4xxx_clear_database_entry(struct scsi_qla_host * ha, >- uint16_t fw_ddb_index) >-{ >- uint32_t mbox_cmd[MBOX_REG_COUNT]; >- uint32_t mbox_sts[MBOX_REG_COUNT]; >- >- memset(&mbox_cmd, 0, sizeof(mbox_cmd)); >- memset(&mbox_sts, 0, sizeof(mbox_sts)); >- mbox_cmd[0] = MBOX_CMD_CLEAR_DATABASE_ENTRY; >- mbox_cmd[1] = fw_ddb_index; >- if (qla4xxx_mailbox_command(ha, 2, 5, &mbox_cmd[0], &mbox_sts[0]) != >- QLA_SUCCESS) >- return QLA_ERROR; >- >- return QLA_SUCCESS; >-} >- > /** > * qla4xxx_initialize_fw_cb - initializes firmware control block. > * @ha: Pointer to host adapter structure. >@@ -268,10 +197,13 @@ int qla4xxx_initialize_fw_cb(struct scsi > /* Get Initialize Firmware Control Block. */ > memset(&mbox_cmd, 0, sizeof(mbox_cmd)); > memset(&mbox_sts, 0, sizeof(mbox_sts)); >+ > mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK; > mbox_cmd[2] = LSDW(init_fw_cb_dma); > mbox_cmd[3] = MSDW(init_fw_cb_dma); >- if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) != >+ mbox_cmd[4] = sizeof(struct init_fw_ctrl_blk); >+ >+ if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) != > QLA_SUCCESS) { > dma_free_coherent(&ha->pdev->dev, > sizeof(struct init_fw_ctrl_blk), >@@ -283,51 +215,56 @@ int qla4xxx_initialize_fw_cb(struct scsi > qla4xxx_init_rings(ha); > > /* Fill in the request and response queue information. */ >- init_fw_cb->ReqQConsumerIndex = cpu_to_le16(ha->request_out); >- init_fw_cb->ComplQProducerIndex = cpu_to_le16(ha->response_in); >- init_fw_cb->ReqQLen = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH); >- init_fw_cb->ComplQLen = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH); >- init_fw_cb->ReqQAddrLo = cpu_to_le32(LSDW(ha->request_dma)); >- init_fw_cb->ReqQAddrHi = cpu_to_le32(MSDW(ha->request_dma)); >- init_fw_cb->ComplQAddrLo = cpu_to_le32(LSDW(ha->response_dma)); >- init_fw_cb->ComplQAddrHi = cpu_to_le32(MSDW(ha->response_dma)); >- init_fw_cb->ShadowRegBufAddrLo = >+ init_fw_cb->pri.rqq_consumer_idx = cpu_to_le16(ha->request_out); >+ init_fw_cb->pri.compq_producer_idx = cpu_to_le16(ha->response_in); >+ init_fw_cb->pri.rqq_len = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH); >+ init_fw_cb->pri.compq_len = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH); >+ init_fw_cb->pri.rqq_addr_lo = cpu_to_le32(LSDW(ha->request_dma)); >+ init_fw_cb->pri.rqq_addr_hi = cpu_to_le32(MSDW(ha->request_dma)); >+ init_fw_cb->pri.compq_addr_lo = cpu_to_le32(LSDW(ha->response_dma)); >+ init_fw_cb->pri.compq_addr_hi = cpu_to_le32(MSDW(ha->response_dma)); >+ init_fw_cb->pri.shdwreg_addr_lo = > cpu_to_le32(LSDW(ha->shadow_regs_dma)); >- init_fw_cb->ShadowRegBufAddrHi = >+ init_fw_cb->pri.shdwreg_addr_hi = > cpu_to_le32(MSDW(ha->shadow_regs_dma)); > > /* Set up required options. */ >- init_fw_cb->FwOptions |= >+ init_fw_cb->pri.fw_options |= > __constant_cpu_to_le16(FWOPT_SESSION_MODE | > FWOPT_INITIATOR_MODE); >- init_fw_cb->FwOptions &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE); >+ init_fw_cb->pri.fw_options &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE); > > /* Save some info in adapter structure. */ >- ha->firmware_options = le16_to_cpu(init_fw_cb->FwOptions); >- ha->tcp_options = le16_to_cpu(init_fw_cb->TCPOptions); >- ha->heartbeat_interval = init_fw_cb->HeartbeatInterval; >- memcpy(ha->ip_address, init_fw_cb->IPAddr, >- min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr))); >- memcpy(ha->subnet_mask, init_fw_cb->SubnetMask, >- min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask))); >- memcpy(ha->gateway, init_fw_cb->GatewayIPAddr, >- min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr))); >- memcpy(ha->name_string, init_fw_cb->iSCSINameString, >+ ha->firmware_options = le16_to_cpu(init_fw_cb->pri.fw_options); >+ ha->tcp_options = le16_to_cpu(init_fw_cb->pri.ipv4_tcp_opts); >+ ha->heartbeat_interval = init_fw_cb->pri.hb_interval; >+ memcpy(ha->ip_address, init_fw_cb->pri.ipv4_addr, >+ min(sizeof(ha->ip_address), sizeof(init_fw_cb->pri.ipv4_addr))); >+ memcpy(ha->subnet_mask, init_fw_cb->pri.ipv4_subnet, >+ min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->pri.ipv4_subnet))); >+ memcpy(ha->gateway, init_fw_cb->pri.ipv4_gw_addr, >+ min(sizeof(ha->gateway), sizeof(init_fw_cb->pri.ipv4_gw_addr))); >+ memcpy(ha->name_string, init_fw_cb->pri.iscsi_name, > min(sizeof(ha->name_string), >- sizeof(init_fw_cb->iSCSINameString))); >- memcpy(ha->alias, init_fw_cb->Alias, >- min(sizeof(ha->alias), sizeof(init_fw_cb->Alias))); >+ sizeof(init_fw_cb->pri.iscsi_name))); >+ /*memcpy(ha->alias, init_fw_cb->Alias, >+ min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/ > > /* Save Command Line Paramater info */ >- ha->port_down_retry_count = le16_to_cpu(init_fw_cb->KeepAliveTimeout); >+ ha->port_down_retry_count = le16_to_cpu(init_fw_cb->pri.conn_ka_timeout); > ha->discovery_wait = ql4xdiscoverywait; > > /* Send Initialize Firmware Control Block. */ >+ memset(&mbox_cmd, 0, sizeof(mbox_cmd)); >+ memset(&mbox_sts, 0, sizeof(mbox_sts)); >+ > mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE; > mbox_cmd[1] = 0; > mbox_cmd[2] = LSDW(init_fw_cb_dma); > mbox_cmd[3] = MSDW(init_fw_cb_dma); >- if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) == >+ mbox_cmd[4] = sizeof(struct init_fw_ctrl_blk); >+ >+ if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) == > QLA_SUCCESS) > status = QLA_SUCCESS; > else { >@@ -364,12 +301,14 @@ int qla4xxx_get_dhcp_ip_address(struct s > /* Get Initialize Firmware Control Block. */ > memset(&mbox_cmd, 0, sizeof(mbox_cmd)); > memset(&mbox_sts, 0, sizeof(mbox_sts)); >+ > memset(init_fw_cb, 0, sizeof(struct init_fw_ctrl_blk)); > mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK; > mbox_cmd[2] = LSDW(init_fw_cb_dma); > mbox_cmd[3] = MSDW(init_fw_cb_dma); >+ mbox_cmd[4] = sizeof(struct init_fw_ctrl_blk); > >- if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) != >+ if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) != > QLA_SUCCESS) { > DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n", > ha->host_no, __func__)); >@@ -380,12 +319,12 @@ int qla4xxx_get_dhcp_ip_address(struct s > } > > /* Save IP Address. */ >- memcpy(ha->ip_address, init_fw_cb->IPAddr, >- min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr))); >- memcpy(ha->subnet_mask, init_fw_cb->SubnetMask, >- min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask))); >- memcpy(ha->gateway, init_fw_cb->GatewayIPAddr, >- min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr))); >+ memcpy(ha->ip_address, init_fw_cb->pri.ipv4_addr, >+ min(sizeof(ha->ip_address), sizeof(init_fw_cb->pri.ipv4_addr))); >+ memcpy(ha->subnet_mask, init_fw_cb->pri.ipv4_subnet, >+ min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->pri.ipv4_subnet))); >+ memcpy(ha->gateway, init_fw_cb->pri.ipv4_gw_addr, >+ min(sizeof(ha->gateway), sizeof(init_fw_cb->pri.ipv4_gw_addr))); > > dma_free_coherent(&ha->pdev->dev, sizeof(struct init_fw_ctrl_blk), > init_fw_cb, init_fw_cb_dma); >@@ -405,8 +344,10 @@ int qla4xxx_get_firmware_state(struct sc > /* Get firmware version */ > memset(&mbox_cmd, 0, sizeof(mbox_cmd)); > memset(&mbox_sts, 0, sizeof(mbox_sts)); >+ > mbox_cmd[0] = MBOX_CMD_GET_FW_STATE; >- if (qla4xxx_mailbox_command(ha, 1, 4, &mbox_cmd[0], &mbox_sts[0]) != >+ >+ if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 4, &mbox_cmd[0], &mbox_sts[0]) != > QLA_SUCCESS) { > DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ " > "status %04X\n", ha->host_no, __func__, >@@ -434,8 +375,10 @@ int qla4xxx_get_firmware_status(struct s > /* Get firmware version */ > memset(&mbox_cmd, 0, sizeof(mbox_cmd)); > memset(&mbox_sts, 0, sizeof(mbox_sts)); >+ > mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS; >- if (qla4xxx_mailbox_command(ha, 1, 3, &mbox_cmd[0], &mbox_sts[0]) != >+ >+ if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) != > QLA_SUCCESS) { > DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ " > "status %04X\n", ha->host_no, __func__, >@@ -487,11 +430,14 @@ int qla4xxx_get_fwddb_entry(struct scsi_ > } > memset(&mbox_cmd, 0, sizeof(mbox_cmd)); > memset(&mbox_sts, 0, sizeof(mbox_sts)); >+ > mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY; > mbox_cmd[1] = (uint32_t) fw_ddb_index; > mbox_cmd[2] = LSDW(fw_ddb_entry_dma); > mbox_cmd[3] = MSDW(fw_ddb_entry_dma); >- if (qla4xxx_mailbox_command(ha, 4, 7, &mbox_cmd[0], &mbox_sts[0]) == >+ mbox_cmd[4] = sizeof(struct dev_db_entry); >+ >+ if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 7, &mbox_cmd[0], &mbox_sts[0]) == > QLA_ERROR) { > DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed" > " with status 0x%04X\n", ha->host_no, __func__, >@@ -508,11 +454,11 @@ int qla4xxx_get_fwddb_entry(struct scsi_ > dev_info(&ha->pdev->dev, "DDB[%d] MB0 %04x Tot %d Next %d " > "State %04x ConnErr %08x %d.%d.%d.%d:%04d \"%s\"\n", > fw_ddb_index, mbox_sts[0], mbox_sts[2], mbox_sts[3], >- mbox_sts[4], mbox_sts[5], fw_ddb_entry->ipAddr[0], >- fw_ddb_entry->ipAddr[1], fw_ddb_entry->ipAddr[2], >- fw_ddb_entry->ipAddr[3], >- le16_to_cpu(fw_ddb_entry->portNumber), >- fw_ddb_entry->iscsiName); >+ mbox_sts[4], mbox_sts[5], fw_ddb_entry->ip_addr[0], >+ fw_ddb_entry->ip_addr[1], fw_ddb_entry->ip_addr[2], >+ fw_ddb_entry->ip_addr[3], >+ le16_to_cpu(fw_ddb_entry->port), >+ fw_ddb_entry->iscsi_name); > } > if (num_valid_ddb_entries) > *num_valid_ddb_entries = mbox_sts[2]; >@@ -567,32 +513,9 @@ int qla4xxx_set_ddb_entry(struct scsi_ql > mbox_cmd[1] = (uint32_t) fw_ddb_index; > mbox_cmd[2] = LSDW(fw_ddb_entry_dma); > mbox_cmd[3] = MSDW(fw_ddb_entry_dma); >- return qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]); >-} >- >-int qla4xxx_conn_open_session_login(struct scsi_qla_host * ha, >- uint16_t fw_ddb_index) >-{ >- int status = QLA_ERROR; >- uint32_t mbox_cmd[MBOX_REG_COUNT]; >- uint32_t mbox_sts[MBOX_REG_COUNT]; >- >- /* Do not wait for completion. The firmware will send us an >- * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status. >- */ >- memset(&mbox_cmd, 0, sizeof(mbox_cmd)); >- memset(&mbox_sts, 0, sizeof(mbox_sts)); >- mbox_cmd[0] = MBOX_CMD_CONN_OPEN_SESS_LOGIN; >- mbox_cmd[1] = (uint32_t) fw_ddb_index; >- mbox_cmd[2] = 0; >- mbox_cmd[3] = 0; >- mbox_cmd[4] = 0; >- status = qla4xxx_mailbox_command(ha, 4, 0, &mbox_cmd[0], &mbox_sts[0]); >- DEBUG2(printk("%s fw_ddb_index=%d status=%d mbx0_1=0x%x :0x%x\n", >- __func__, fw_ddb_index, status, mbox_sts[0], >- mbox_sts[1]);) >+ mbox_cmd[4] = sizeof(struct dev_db_entry); > >- return status; >+ return qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]); > } > > /** >@@ -608,12 +531,14 @@ void qla4xxx_get_crash_record(struct scs > struct crash_record *crash_record = NULL; > dma_addr_t crash_record_dma = 0; > uint32_t crash_record_size = 0; >+ > memset(&mbox_cmd, 0, sizeof(mbox_cmd)); > memset(&mbox_sts, 0, sizeof(mbox_cmd)); > > /* Get size of crash record. */ > mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD; >- if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) != >+ >+ if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != > QLA_SUCCESS) { > DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n", > ha->host_no, __func__)); >@@ -633,11 +558,15 @@ void qla4xxx_get_crash_record(struct scs > goto exit_get_crash_record; > > /* Get Crash Record. */ >+ memset(&mbox_cmd, 0, sizeof(mbox_cmd)); >+ memset(&mbox_sts, 0, sizeof(mbox_cmd)); >+ > mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD; > mbox_cmd[2] = LSDW(crash_record_dma); > mbox_cmd[3] = MSDW(crash_record_dma); > mbox_cmd[4] = crash_record_size; >- if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) != >+ >+ if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != > QLA_SUCCESS) > goto exit_get_crash_record; > >@@ -671,7 +600,8 @@ void qla4xxx_get_conn_event_log(struct s > > /* Get size of crash record. */ > mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG; >- if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) != >+ >+ if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != > QLA_SUCCESS) > goto exit_get_event_log; > >@@ -686,10 +616,14 @@ void qla4xxx_get_conn_event_log(struct s > goto exit_get_event_log; > > /* Get Crash Record. */ >+ memset(&mbox_cmd, 0, sizeof(mbox_cmd)); >+ memset(&mbox_sts, 0, sizeof(mbox_cmd)); >+ > mbox_cmd[0] = MBOX_CMD_GET_CONN_EVENT_LOG; > mbox_cmd[2] = LSDW(event_log_dma); > mbox_cmd[3] = MSDW(event_log_dma); >- if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) != >+ >+ if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != > QLA_SUCCESS) { > DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve event " > "log!\n", ha->host_no, __func__)); >@@ -765,11 +699,13 @@ int qla4xxx_reset_lun(struct scsi_qla_ho > */ > memset(&mbox_cmd, 0, sizeof(mbox_cmd)); > memset(&mbox_sts, 0, sizeof(mbox_sts)); >+ > mbox_cmd[0] = MBOX_CMD_LUN_RESET; > mbox_cmd[1] = ddb_entry->fw_ddb_index; > mbox_cmd[2] = lun << 8; > mbox_cmd[5] = 0x01; /* Immediate Command Enable */ >- qla4xxx_mailbox_command(ha, 6, 1, &mbox_cmd[0], &mbox_sts[0]); >+ >+ qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]); > if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE && > mbox_sts[0] != MBOX_STS_COMMAND_ERROR) > status = QLA_ERROR; >@@ -786,12 +722,14 @@ int qla4xxx_get_flash(struct scsi_qla_ho > > memset(&mbox_cmd, 0, sizeof(mbox_cmd)); > memset(&mbox_sts, 0, sizeof(mbox_sts)); >+ > mbox_cmd[0] = MBOX_CMD_READ_FLASH; > mbox_cmd[1] = LSDW(dma_addr); > mbox_cmd[2] = MSDW(dma_addr); > mbox_cmd[3] = offset; > mbox_cmd[4] = len; >- if (qla4xxx_mailbox_command(ha, 5, 2, &mbox_cmd[0], &mbox_sts[0]) != >+ >+ if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 2, &mbox_cmd[0], &mbox_sts[0]) != > QLA_SUCCESS) { > DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ " > "status %04X %04X, offset %08x, len %08x\n", ha->host_no, >@@ -817,8 +755,10 @@ int qla4xxx_get_fw_version(struct scsi_q > /* Get firmware version. */ > memset(&mbox_cmd, 0, sizeof(mbox_cmd)); > memset(&mbox_sts, 0, sizeof(mbox_sts)); >+ > mbox_cmd[0] = MBOX_CMD_ABOUT_FW; >- if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) != >+ >+ if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 5, &mbox_cmd[0], &mbox_sts[0]) != > QLA_SUCCESS) { > DEBUG2(printk("scsi%ld: %s: MBOX_CMD_ABOUT_FW failed w/ " > "status %04X\n", ha->host_no, __func__, mbox_sts[0])); >@@ -834,7 +774,8 @@ int qla4xxx_get_fw_version(struct scsi_q > return QLA_SUCCESS; > } > >-int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, dma_addr_t dma_addr) >+static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, >+ dma_addr_t dma_addr) > { > uint32_t mbox_cmd[MBOX_REG_COUNT]; > uint32_t mbox_sts[MBOX_REG_COUNT]; >@@ -846,7 +787,7 @@ int qla4xxx_get_default_ddb(struct scsi_ > mbox_cmd[2] = LSDW(dma_addr); > mbox_cmd[3] = MSDW(dma_addr); > >- if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) != >+ if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 1, &mbox_cmd[0], &mbox_sts[0]) != > QLA_SUCCESS) { > DEBUG2(printk("scsi%ld: %s: failed status %04X\n", > ha->host_no, __func__, mbox_sts[0])); >@@ -855,7 +796,7 @@ int qla4xxx_get_default_ddb(struct scsi_ > return QLA_SUCCESS; > } > >-int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t *ddb_index) >+static int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t *ddb_index) > { > uint32_t mbox_cmd[MBOX_REG_COUNT]; > uint32_t mbox_sts[MBOX_REG_COUNT]; >@@ -866,7 +807,7 @@ int qla4xxx_req_ddb_entry(struct scsi_ql > mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY; > mbox_cmd[1] = MAX_PRST_DEV_DB_ENTRIES; > >- if (qla4xxx_mailbox_command(ha, 2, 3, &mbox_cmd[0], &mbox_sts[0]) != >+ if (qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, 3, &mbox_cmd[0], &mbox_sts[0]) != > QLA_SUCCESS) { > if (mbox_sts[0] == MBOX_STS_COMMAND_ERROR) { > *ddb_index = mbox_sts[2]; >@@ -909,23 +850,23 @@ int qla4xxx_send_tgts(struct scsi_qla_ho > if (ret_val != QLA_SUCCESS) > goto qla4xxx_send_tgts_exit; > >- memset((void *)fw_ddb_entry->iSCSIAlias, 0, >- sizeof(fw_ddb_entry->iSCSIAlias)); >+ memset(fw_ddb_entry->iscsi_alias, 0, >+ sizeof(fw_ddb_entry->iscsi_alias)); > >- memset((void *)fw_ddb_entry->iscsiName, 0, >- sizeof(fw_ddb_entry->iscsiName)); >+ memset(fw_ddb_entry->iscsi_name, 0, >+ sizeof(fw_ddb_entry->iscsi_name)); > >- memset((void *)fw_ddb_entry->ipAddr, 0, sizeof(fw_ddb_entry->ipAddr)); >- memset((void *)fw_ddb_entry->targetAddr, 0, >- sizeof(fw_ddb_entry->targetAddr)); >+ memset(fw_ddb_entry->ip_addr, 0, sizeof(fw_ddb_entry->ip_addr)); >+ memset(fw_ddb_entry->tgt_addr, 0, >+ sizeof(fw_ddb_entry->tgt_addr)); > > fw_ddb_entry->options = (DDB_OPT_DISC_SESSION | DDB_OPT_TARGET); >- fw_ddb_entry->portNumber = cpu_to_le16(ntohs(port)); >+ fw_ddb_entry->port = cpu_to_le16(ntohs(port)); > >- fw_ddb_entry->ipAddr[0] = *ip; >- fw_ddb_entry->ipAddr[1] = *(ip + 1); >- fw_ddb_entry->ipAddr[2] = *(ip + 2); >- fw_ddb_entry->ipAddr[3] = *(ip + 3); >+ fw_ddb_entry->ip_addr[0] = *ip; >+ fw_ddb_entry->ip_addr[1] = *(ip + 1); >+ fw_ddb_entry->ip_addr[2] = *(ip + 2); >+ fw_ddb_entry->ip_addr[3] = *(ip + 3); > > ret_val = qla4xxx_set_ddb_entry(ha, ddb_index, fw_ddb_entry_dma); > >diff -aurp linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_nvram.c linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_nvram.c >--- linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_nvram.c 2007-10-22 10:47:06.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_nvram.c 2007-10-24 22:26:00.000000000 -0500 >@@ -6,6 +6,9 @@ > */ > > #include "ql4_def.h" >+#include "ql4_glbl.h" >+#include "ql4_dbg.h" >+#include "ql4_inline.h" > > static inline void eeprom_cmd(uint32_t cmd, struct scsi_qla_host *ha) > { >diff -aurp linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_os.c linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_os.c >--- linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_os.c 2007-10-22 10:47:06.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_os.c 2007-10-25 01:07:08.000000000 -0500 >@@ -10,11 +10,15 @@ > #include <scsi/scsicam.h> > > #include "ql4_def.h" >+#include "ql4_version.h" >+#include "ql4_glbl.h" >+#include "ql4_dbg.h" >+#include "ql4_inline.h" > > /* > * Driver version > */ >-char qla4xxx_version_str[40]; >+static char qla4xxx_version_str[40]; > > /* > * SRB allocation cache >@@ -45,18 +49,20 @@ int ql4_mod_unload = 0; > /* > * SCSI host template entry points > */ >- >-void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha); >+static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha); > > /* > * iSCSI template entry points > */ >-static int qla4xxx_tgt_dscvr(enum iscsi_tgt_dscvr type, uint32_t host_no, >- uint32_t enable, struct sockaddr *dst_addr); >+static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost, >+ enum iscsi_tgt_dscvr type, uint32_t enable, >+ struct sockaddr *dst_addr); > static int qla4xxx_conn_get_param(struct iscsi_cls_conn *conn, > enum iscsi_param param, char *buf); > static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess, > enum iscsi_param param, char *buf); >+static int qla4xxx_host_get_param(struct Scsi_Host *shost, >+ enum iscsi_host_param param, char *buf); > static void qla4xxx_conn_stop(struct iscsi_cls_conn *conn, int flag); > static int qla4xxx_conn_start(struct iscsi_cls_conn *conn); > static void qla4xxx_recovery_timedout(struct iscsi_cls_session *session); >@@ -96,16 +102,20 @@ static struct scsi_host_template qla4xxx > static struct iscsi_transport qla4xxx_iscsi_transport = { > .owner = THIS_MODULE, > .name = DRIVER_NAME, >- .param_mask = ISCSI_CONN_PORT | >- ISCSI_CONN_ADDRESS | >- ISCSI_TARGET_NAME | >- ISCSI_TPGT, >+ .caps = CAP_FW_DB | CAP_SENDTARGETS_OFFLOAD | >+ CAP_DATA_PATH_OFFLOAD, >+ .param_mask = ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS | >+ ISCSI_TARGET_NAME | ISCSI_TPGT, >+ .host_param_mask = ISCSI_HOST_HWADDRESS | >+ ISCSI_HOST_IPADDRESS | >+ ISCSI_HOST_INITIATOR_NAME, > .sessiondata_size = sizeof(struct ddb_entry), > .host_template = &qla4xxx_driver_template, > > .tgt_dscvr = qla4xxx_tgt_dscvr, > .get_conn_param = qla4xxx_conn_get_param, > .get_session_param = qla4xxx_sess_get_param, >+ .get_host_param = qla4xxx_host_get_param, > .start_conn = qla4xxx_conn_start, > .stop_conn = qla4xxx_conn_stop, > .session_recovery_timedout = qla4xxx_recovery_timedout, >@@ -162,6 +172,43 @@ static void qla4xxx_conn_stop(struct isc > printk(KERN_ERR "iscsi: invalid stop flag %d\n", flag); > } > >+static ssize_t format_addr(char *buf, const unsigned char *addr, int len) >+{ >+ int i; >+ char *cp = buf; >+ >+ for (i = 0; i < len; i++) >+ cp += sprintf(cp, "%02x%c", addr[i], >+ i == (len - 1) ? '\n' : ':'); >+ return cp - buf; >+} >+ >+ >+static int qla4xxx_host_get_param(struct Scsi_Host *shost, >+ enum iscsi_host_param param, char *buf) >+{ >+ struct scsi_qla_host *ha = to_qla_host(shost); >+ int len; >+ >+ switch (param) { >+ case ISCSI_HOST_PARAM_HWADDRESS: >+ len = format_addr(buf, ha->my_mac, MAC_ADDR_LEN); >+ break; >+ case ISCSI_HOST_PARAM_IPADDRESS: >+ len = sprintf(buf, "%d.%d.%d.%d\n", ha->ip_address[0], >+ ha->ip_address[1], ha->ip_address[2], >+ ha->ip_address[3]); >+ break; >+ case ISCSI_HOST_PARAM_INITIATOR_NAME: >+ len = sprintf(buf, "%s\n", ha->name_string); >+ break; >+ default: >+ return -ENOSYS; >+ } >+ >+ return len; >+} >+ > static int qla4xxx_sess_get_param(struct iscsi_cls_session *sess, > enum iscsi_param param, char *buf) > { >@@ -209,21 +256,15 @@ static int qla4xxx_conn_get_param(struct > return len; > } > >-static int qla4xxx_tgt_dscvr(enum iscsi_tgt_dscvr type, uint32_t host_no, >- uint32_t enable, struct sockaddr *dst_addr) >+static int qla4xxx_tgt_dscvr(struct Scsi_Host *shost, >+ enum iscsi_tgt_dscvr type, uint32_t enable, >+ struct sockaddr *dst_addr) > { > struct scsi_qla_host *ha; >- struct Scsi_Host *shost; > struct sockaddr_in *addr; > struct sockaddr_in6 *addr6; > int ret = 0; > >- shost = scsi_host_lookup(host_no); >- if (IS_ERR(shost)) { >- printk(KERN_ERR "Could not find host no %u\n", host_no); >- return -ENODEV; >- } >- > ha = (struct scsi_qla_host *) shost->hostdata; > > switch (type) { >@@ -247,8 +288,6 @@ static int qla4xxx_tgt_dscvr(enum iscsi_ > default: > ret = -ENOSYS; > } >- >- scsi_host_put(shost); > return ret; > } > >@@ -258,6 +297,7 @@ void qla4xxx_destroy_sess(struct ddb_ent > return; > > if (ddb_entry->conn) { >+ atomic_set(&ddb_entry->state, DDB_STATE_DEAD); > iscsi_if_destroy_session_done(ddb_entry->conn); > iscsi_destroy_conn(ddb_entry->conn); > iscsi_remove_session(ddb_entry->sess); >@@ -265,7 +305,7 @@ void qla4xxx_destroy_sess(struct ddb_ent > iscsi_free_session(ddb_entry->sess); > } > >-int qla4xxx_add_sess(struct ddb_entry *ddb_entry) >+int qla4xxx_add_sess(struct ddb_entry *ddb_entry, int scan) > { > int err; > >@@ -283,6 +323,10 @@ int qla4xxx_add_sess(struct ddb_entry *d > } > > ddb_entry->sess->recovery_tmo = ddb_entry->ha->port_down_retry_count; >+ if (scan) >+ scsi_scan_target(&ddb_entry->sess->dev, 0, >+ ddb_entry->sess->target_id, >+ SCAN_WILD_CARD, 0); > iscsi_if_create_session_done(ddb_entry->conn); > return 0; > } >@@ -712,7 +756,7 @@ static int qla4xxx_cmd_wait(struct scsi_ > return stat; > } > >-static void qla4xxx_hw_reset(struct scsi_qla_host *ha) >+void qla4xxx_hw_reset(struct scsi_qla_host *ha) > { > uint32_t ctrl_status; > unsigned long flags = 0; >@@ -1082,13 +1126,13 @@ static void qla4xxx_free_adapter(struct > if (ha->timer_active) > qla4xxx_stop_timer(ha); > >- /* free extra memory */ >- qla4xxx_mem_free(ha); >- > /* Detach interrupts */ > if (test_and_clear_bit(AF_IRQ_ATTACHED, &ha->flags)) > free_irq(ha->pdev->irq, ha); > >+ /* free extra memory */ >+ qla4xxx_mem_free(ha); >+ > pci_disable_device(ha->pdev); > > } >@@ -1296,7 +1340,7 @@ static int __devinit qla4xxx_probe_adapt > /* Update transport device information for all devices. */ > list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) { > if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) >- if (qla4xxx_add_sess(ddb_entry)) >+ if (qla4xxx_add_sess(ddb_entry, 1)) > goto remove_host; > } > >@@ -1306,7 +1350,6 @@ static int __devinit qla4xxx_probe_adapt > qla4xxx_version_str, ha->pdev->device, pci_name(ha->pdev), > ha->host_no, ha->firmware_version[0], ha->firmware_version[1], > ha->patch_number, ha->build_number); >- > return 0; > > remove_host: >@@ -1333,6 +1376,11 @@ static void __devexit qla4xxx_remove_ada > > ha = pci_get_drvdata(pdev); > >+ qla4xxx_disable_intrs(ha); >+ >+ while (test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags)) >+ ssleep(1); >+ > /* remove devs from iscsi_sessions to scsi_devices */ > qla4xxx_free_ddb_list(ha); > >@@ -1352,7 +1400,7 @@ static void __devexit qla4xxx_remove_ada > * At exit, the @ha's flags.enable_64bit_addressing set to indicated > * supported addressing method. > */ >-void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha) >+static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha) > { > int retval; > >@@ -1627,7 +1675,7 @@ static struct pci_device_id qla4xxx_pci_ > }; > MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl); > >-struct pci_driver qla4xxx_pci_driver = { >+static struct pci_driver qla4xxx_pci_driver = { > .name = DRIVER_NAME, > .id_table = qla4xxx_pci_tbl, > .probe = qla4xxx_probe_adapter, >diff -aurp linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_version.h linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_version.h >--- linux-2.6.21.noarch/drivers/scsi/qla4xxx/ql4_version.h 2007-10-22 10:47:06.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/scsi/qla4xxx/ql4_version.h 2007-10-24 22:26:00.000000000 -0500 >@@ -5,4 +5,5 @@ > * See LICENSE.qla4xxx for copyright and licensing details. > */ > >-#define QLA4XXX_DRIVER_VERSION "5.00.07-k1" >+#define QLA4XXX_DRIVER_VERSION "5.01.00-k8" >+ >diff -aurp linux-2.6.21.noarch/drivers/scsi/scsi_transport_iscsi.c linux-2.6.21.noarch.iscsi2/drivers/scsi/scsi_transport_iscsi.c >--- linux-2.6.21.noarch/drivers/scsi/scsi_transport_iscsi.c 2007-10-22 10:47:07.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/drivers/scsi/scsi_transport_iscsi.c 2007-10-24 22:26:00.000000000 -0500 >@@ -30,10 +30,10 @@ > #include <scsi/scsi_transport_iscsi.h> > #include <scsi/iscsi_if.h> > >-#define ISCSI_SESSION_ATTRS 11 >+#define ISCSI_SESSION_ATTRS 16 > #define ISCSI_CONN_ATTRS 11 >-#define ISCSI_HOST_ATTRS 0 >-#define ISCSI_TRANSPORT_VERSION "2.0-724" >+#define ISCSI_HOST_ATTRS 4 >+#define ISCSI_TRANSPORT_VERSION "2.0-865" > > struct iscsi_internal { > int daemon_pid; >@@ -49,7 +49,7 @@ struct iscsi_internal { > struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1]; > }; > >-static int iscsi_session_nr; /* sysfs session id for next new session */ >+static atomic_t iscsi_session_nr; /* sysfs session id for next new session */ > > /* > * list of registered transports and lock that must >@@ -300,7 +300,7 @@ int iscsi_add_session(struct iscsi_cls_s > int err; > > ihost = shost->shost_data; >- session->sid = iscsi_session_nr++; >+ session->sid = atomic_add_return(1, &iscsi_session_nr); > session->target_id = target_id; > > snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u", >@@ -609,12 +609,10 @@ iscsi_if_send_reply(int pid, int seq, in > int t = done ? NLMSG_DONE : type; > > skb = alloc_skb(len, GFP_ATOMIC); >- /* >- * FIXME: >- * user is supposed to react on iferror == -ENOMEM; >- * see iscsi_if_rx(). >- */ >- BUG_ON(!skb); >+ if (!skb) { >+ printk(KERN_ERR "Could not allocate skb to send reply.\n"); >+ return -ENOMEM; >+ } > > nlh = __nlmsg_put(skb, pid, seq, t, (len - sizeof(*nlh)), 0); > nlh->nlmsg_flags = flags; >@@ -816,6 +814,8 @@ iscsi_if_create_session(struct iscsi_int > uint32_t hostno; > > session = transport->create_session(transport, &priv->t, >+ ev->u.c_session.cmds_max, >+ ev->u.c_session.queue_depth, > ev->u.c_session.initial_cmdsn, > &hostno); > if (!session) >@@ -947,15 +947,50 @@ static int > iscsi_tgt_dscvr(struct iscsi_transport *transport, > struct iscsi_uevent *ev) > { >+ struct Scsi_Host *shost; > struct sockaddr *dst_addr; >+ int err; > > if (!transport->tgt_dscvr) > return -EINVAL; > >+ shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no); >+ if (IS_ERR(shost)) { >+ printk(KERN_ERR "target discovery could not find host no %u\n", >+ ev->u.tgt_dscvr.host_no); >+ return -ENODEV; >+ } >+ >+ > dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev)); >- return transport->tgt_dscvr(ev->u.tgt_dscvr.type, >- ev->u.tgt_dscvr.host_no, >- ev->u.tgt_dscvr.enable, dst_addr); >+ err = transport->tgt_dscvr(shost, ev->u.tgt_dscvr.type, >+ ev->u.tgt_dscvr.enable, dst_addr); >+ scsi_host_put(shost); >+ return err; >+} >+ >+static int >+iscsi_set_host_param(struct iscsi_transport *transport, >+ struct iscsi_uevent *ev) >+{ >+ char *data = (char*)ev + sizeof(*ev); >+ struct Scsi_Host *shost; >+ int err; >+ >+ if (!transport->set_host_param) >+ return -ENOSYS; >+ >+ shost = scsi_host_lookup(ev->u.set_host_param.host_no); >+ if (IS_ERR(shost)) { >+ printk(KERN_ERR "set_host_param could not find host no %u\n", >+ ev->u.set_host_param.host_no); >+ return -ENODEV; >+ } >+ >+ err = transport->set_host_param(shost, ev->u.set_host_param.param, >+ data, ev->u.set_host_param.len); >+ scsi_host_put(shost); >+ return err; > } > > static int >@@ -1049,8 +1084,11 @@ iscsi_if_recv_msg(struct sk_buff *skb, s > case ISCSI_UEVENT_TGT_DSCVR: > err = iscsi_tgt_dscvr(transport, ev); > break; >+ case ISCSI_UEVENT_SET_HOST_PARAM: >+ err = iscsi_set_host_param(transport, ev); >+ break; > default: >- err = -EINVAL; >+ err = -ENOSYS; > break; > } > >@@ -1160,30 +1198,38 @@ iscsi_conn_attr(address, ISCSI_PARAM_CON > /* > * iSCSI session attrs > */ >-#define iscsi_session_attr_show(param) \ >+#define iscsi_session_attr_show(param, perm) \ > static ssize_t \ > show_session_param_##param(struct class_device *cdev, char *buf) \ > { \ > struct iscsi_cls_session *session = iscsi_cdev_to_session(cdev); \ > struct iscsi_transport *t = session->transport; \ >+ \ >+ if (perm && !capable(CAP_SYS_ADMIN)) \ >+ return -EACCES; \ > return t->get_session_param(session, param, buf); \ > } > >-#define iscsi_session_attr(field, param) \ >- iscsi_session_attr_show(param) \ >+#define iscsi_session_attr(field, param, perm) \ >+ iscsi_session_attr_show(param, perm) \ > static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_param_##param, \ > NULL); > >-iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME); >-iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN); >-iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T); >-iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN); >-iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST); >-iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST); >-iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN); >-iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN); >-iscsi_session_attr(erl, ISCSI_PARAM_ERL); >-iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT); >+iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME, 0); >+iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, 0); >+iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, 0); >+iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN, 0); >+iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST, 0); >+iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, 0); >+iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, 0); >+iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, 0); >+iscsi_session_attr(erl, ISCSI_PARAM_ERL, 0); >+iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT, 0); >+iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1); >+iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1); >+iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1); >+iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1); >+iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 1); > > #define iscsi_priv_session_attr_show(field, format) \ > static ssize_t \ >@@ -1199,6 +1245,28 @@ static ISCSI_CLASS_ATTR(priv_sess, field > NULL) > iscsi_priv_session_attr(recovery_tmo, "%d"); > >+/* >+ * iSCSI host attrs >+ */ >+#define iscsi_host_attr_show(param) \ >+static ssize_t \ >+show_host_param_##param(struct class_device *cdev, char *buf) \ >+{ \ >+ struct Scsi_Host *shost = transport_class_to_shost(cdev); \ >+ struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \ >+ return priv->iscsi_transport->get_host_param(shost, param, buf); \ >+} >+ >+#define iscsi_host_attr(field, param) \ >+ iscsi_host_attr_show(param) \ >+static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param, \ >+ NULL); >+ >+iscsi_host_attr(netdev, ISCSI_HOST_PARAM_NETDEV_NAME); >+iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS); >+iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS); >+iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME); >+ > #define SETUP_PRIV_SESSION_RD_ATTR(field) \ > do { \ > priv->session_attrs[count] = &class_device_attr_priv_sess_##field; \ >@@ -1222,6 +1290,14 @@ do { \ > } \ > } while (0) > >+#define SETUP_HOST_RD_ATTR(field, param_flag) \ >+do { \ >+ if (tt->host_param_mask & param_flag) { \ >+ priv->host_attrs[count] = &class_device_attr_host_##field; \ >+ count++; \ >+ } \ >+} while (0) >+ > static int iscsi_session_match(struct attribute_container *cont, > struct device *dev) > { >@@ -1323,9 +1399,16 @@ iscsi_register_transport(struct iscsi_tr > priv->t.host_attrs.ac.class = &iscsi_host_class.class; > priv->t.host_attrs.ac.match = iscsi_host_match; > priv->t.host_size = sizeof(struct iscsi_host); >- priv->host_attrs[0] = NULL; > transport_container_register(&priv->t.host_attrs); > >+ SETUP_HOST_RD_ATTR(netdev, ISCSI_HOST_NETDEV_NAME); >+ SETUP_HOST_RD_ATTR(ipaddress, ISCSI_HOST_IPADDRESS); >+ SETUP_HOST_RD_ATTR(hwaddress, ISCSI_HOST_HWADDRESS); >+ SETUP_HOST_RD_ATTR(initiatorname, ISCSI_HOST_INITIATOR_NAME); >+ BUG_ON(count > ISCSI_HOST_ATTRS); >+ priv->host_attrs[count] = NULL; >+ count = 0; >+ > /* connection parameters */ > priv->conn_cont.ac.attrs = &priv->conn_attrs[0]; > priv->conn_cont.ac.class = &iscsi_connection_class.class; >@@ -1364,6 +1447,11 @@ iscsi_register_transport(struct iscsi_tr > SETUP_SESSION_RD_ATTR(erl, ISCSI_ERL); > SETUP_SESSION_RD_ATTR(targetname, ISCSI_TARGET_NAME); > SETUP_SESSION_RD_ATTR(tpgt, ISCSI_TPGT); >+ SETUP_SESSION_RD_ATTR(password, ISCSI_USERNAME); >+ SETUP_SESSION_RD_ATTR(password_in, ISCSI_USERNAME_IN); >+ SETUP_SESSION_RD_ATTR(username, ISCSI_PASSWORD); >+ SETUP_SESSION_RD_ATTR(username_in, ISCSI_PASSWORD_IN); >+ SETUP_SESSION_RD_ATTR(fast_abort, ISCSI_FAST_ABORT); > SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo); > > BUG_ON(count > ISCSI_SESSION_ATTRS); >@@ -1419,6 +1507,8 @@ static __init int iscsi_transport_init(v > printk(KERN_INFO "Loading iSCSI transport class v%s.\n", > ISCSI_TRANSPORT_VERSION); > >+ atomic_set(&iscsi_session_nr, 0); >+ > err = class_register(&iscsi_transport_class); > if (err) > return err; >Only in linux-2.6.21.noarch/include: config >diff -aurp linux-2.6.21.noarch/include/scsi/iscsi_if.h linux-2.6.21.noarch.iscsi2/include/scsi/iscsi_if.h >--- linux-2.6.21.noarch/include/scsi/iscsi_if.h 2007-10-22 10:47:02.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/include/scsi/iscsi_if.h 2007-10-24 22:26:00.000000000 -0500 >@@ -48,6 +48,7 @@ enum iscsi_uevent_e { > ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT = UEVENT_BASE + 14, > > ISCSI_UEVENT_TGT_DSCVR = UEVENT_BASE + 15, >+ ISCSI_UEVENT_SET_HOST_PARAM = UEVENT_BASE + 16, > > /* up events */ > ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1, >@@ -71,6 +72,8 @@ struct iscsi_uevent { > /* messages u -> k */ > struct msg_create_session { > uint32_t initial_cmdsn; >+ uint16_t cmds_max; >+ uint16_t queue_depth; > } c_session; > struct msg_destroy_session { > uint32_t sid; >@@ -136,6 +139,11 @@ struct iscsi_uevent { > */ > uint32_t enable; > } tgt_dscvr; >+ struct msg_set_host_param { >+ uint32_t host_no; >+ uint32_t param; /* enum iscsi_host_param */ >+ uint32_t len; >+ } set_host_param; > } u; > union { > /* messages k -> u */ >@@ -223,6 +231,12 @@ enum iscsi_param { > ISCSI_PARAM_CONN_PORT, > ISCSI_PARAM_CONN_ADDRESS, > >+ ISCSI_PARAM_USERNAME, >+ ISCSI_PARAM_USERNAME_IN, >+ ISCSI_PARAM_PASSWORD, >+ ISCSI_PARAM_PASSWORD_IN, >+ >+ ISCSI_PARAM_FAST_ABORT, > /* must always be last */ > ISCSI_PARAM_MAX, > }; >@@ -249,6 +263,25 @@ enum iscsi_param { > #define ISCSI_SESS_RECOVERY_TMO (1 << ISCSI_PARAM_SESS_RECOVERY_TMO) > #define ISCSI_CONN_PORT (1 << ISCSI_PARAM_CONN_PORT) > #define ISCSI_CONN_ADDRESS (1 << ISCSI_PARAM_CONN_ADDRESS) >+#define ISCSI_USERNAME (1 << ISCSI_PARAM_USERNAME) >+#define ISCSI_USERNAME_IN (1 << ISCSI_PARAM_USERNAME_IN) >+#define ISCSI_PASSWORD (1 << ISCSI_PARAM_PASSWORD) >+#define ISCSI_PASSWORD_IN (1 << ISCSI_PARAM_PASSWORD_IN) >+#define ISCSI_FAST_ABORT (1 << ISCSI_PARAM_FAST_ABORT) >+ >+/* iSCSI HBA params */ >+enum iscsi_host_param { >+ ISCSI_HOST_PARAM_HWADDRESS, >+ ISCSI_HOST_PARAM_INITIATOR_NAME, >+ ISCSI_HOST_PARAM_NETDEV_NAME, >+ ISCSI_HOST_PARAM_IPADDRESS, >+ ISCSI_HOST_PARAM_MAX, >+}; >+ >+#define ISCSI_HOST_HWADDRESS (1 << ISCSI_HOST_PARAM_HWADDRESS) >+#define ISCSI_HOST_INITIATOR_NAME (1 << ISCSI_HOST_PARAM_INITIATOR_NAME) >+#define ISCSI_HOST_NETDEV_NAME (1 << ISCSI_HOST_PARAM_NETDEV_NAME) >+#define ISCSI_HOST_IPADDRESS (1 << ISCSI_HOST_PARAM_IPADDRESS) > > #define iscsi_ptr(_handle) ((void*)(unsigned long)_handle) > #define iscsi_handle(_ptr) ((uint64_t)(unsigned long)_ptr) >@@ -272,12 +305,14 @@ enum iscsi_param { > #define CAP_MULTI_CONN 0x40 > #define CAP_TEXT_NEGO 0x80 > #define CAP_MARKERS 0x100 >+#define CAP_FW_DB 0x200 >+#define CAP_SENDTARGETS_OFFLOAD 0x400 >+#define CAP_DATA_PATH_OFFLOAD 0x800 > > /* > * These flags describes reason of stop_conn() call > */ > #define STOP_CONN_TERM 0x1 >-#define STOP_CONN_SUSPEND 0x2 > #define STOP_CONN_RECOVER 0x3 > > #define ISCSI_STATS_CUSTOM_MAX 32 >diff -aurp linux-2.6.21.noarch/include/scsi/iscsi_proto.h linux-2.6.21.noarch.iscsi2/include/scsi/iscsi_proto.h >--- linux-2.6.21.noarch/include/scsi/iscsi_proto.h 2007-10-22 10:47:02.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/include/scsi/iscsi_proto.h 2007-10-24 22:26:00.000000000 -0500 >@@ -21,6 +21,8 @@ > #ifndef ISCSI_PROTO_H > #define ISCSI_PROTO_H > >+#include <linux/types.h> >+ > #define ISCSI_DRAFT20_VERSION 0x00 > > /* default iSCSI listen port for incoming connections */ >@@ -588,7 +590,20 @@ struct iscsi_reject { > #define VALUE_MAXLEN 255 > #define TARGET_NAME_MAXLEN VALUE_MAXLEN > >-#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH 8192 >+#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH 8192 /* compat for old tools */ >+#define ISCSI_DEF_MAX_RECV_SEG_LEN 8192 >+#define ISCSI_MIN_MAX_RECV_SEG_LEN 512 >+#define ISCSI_MAX_MAX_RECV_SEG_LEN 16777215 >+ >+#define ISCSI_DEF_FIRST_BURST_LEN 65536 >+#define ISCSI_MIN_FIRST_BURST_LEN 512 >+#define ISCSI_MAX_FIRST_BURST_LEN 16777215 >+ >+#define ISCSI_DEF_MAX_BURST_LEN 262144 >+#define ISCSI_MIN_MAX_BURST_LEN 512 >+#define ISCSI_MAX_MAX_BURST_LEN 16777215 >+ >+#define ISCSI_DEF_TIME2WAIT 2 > > /************************* RFC 3720 End *****************************/ > >diff -aurp linux-2.6.21.noarch/include/scsi/libiscsi.h linux-2.6.21.noarch.iscsi2/include/scsi/libiscsi.h >--- linux-2.6.21.noarch/include/scsi/libiscsi.h 2007-10-22 10:47:02.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/include/scsi/libiscsi.h 2007-10-24 22:26:00.000000000 -0500 >@@ -48,9 +48,8 @@ struct iscsi_nopin; > #define debug_scsi(fmt...) > #endif > >-#define ISCSI_XMIT_CMDS_MAX 128 /* must be power of 2 */ >-#define ISCSI_MGMT_CMDS_MAX 32 /* must be power of 2 */ >-#define ISCSI_CONN_MAX 1 >+#define ISCSI_DEF_XMIT_CMDS_MAX 128 /* must be power of 2 */ >+#define ISCSI_MGMT_CMDS_MAX 16 /* must be power of 2 */ > > #define ISCSI_MGMT_ITT_OFFSET 0xa00 > >@@ -58,11 +57,14 @@ struct iscsi_nopin; > #define ISCSI_MAX_CMD_PER_LUN 128 > > /* Task Mgmt states */ >-#define TMABORT_INITIAL 0x0 >-#define TMABORT_SUCCESS 0x1 >-#define TMABORT_FAILED 0x2 >-#define TMABORT_TIMEDOUT 0x3 >-#define TMABORT_NOT_FOUND 0x4 >+enum { >+ TMF_INITIAL, >+ TMF_QUEUED, >+ TMF_SUCCESS, >+ TMF_FAILED, >+ TMF_TIMEDOUT, >+ TMF_NOT_FOUND, >+}; > > /* Connection suspend "bit" */ > #define ISCSI_SUSPEND_BIT 1 >@@ -73,6 +75,8 @@ struct iscsi_nopin; > #define ISCSI_AGE_SHIFT 28 > #define ISCSI_AGE_MASK (0xf << ISCSI_AGE_SHIFT) > >+#define ISCSI_ADDRESS_BUF_LEN 64 >+ > struct iscsi_mgmt_task { > /* > * Becuae LLDs allocate their hdr differently, this is a pointer to >@@ -80,7 +84,7 @@ struct iscsi_mgmt_task { > */ > struct iscsi_hdr *hdr; > char *data; /* mgmt payload */ >- int data_count; /* counts data to be sent */ >+ unsigned data_count; /* counts data to be sent */ > uint32_t itt; /* this ITT */ > void *dd_data; /* driver/transport data */ > struct list_head running; >@@ -99,18 +103,15 @@ struct iscsi_cmd_task { > */ > struct iscsi_cmd *hdr; > int itt; /* this ITT */ >- int datasn; /* DataSN */ > > uint32_t unsol_datasn; >- int imm_count; /* imm-data (bytes) */ >- int unsol_count; /* unsolicited (bytes)*/ >+ unsigned imm_count; /* imm-data (bytes) */ >+ unsigned unsol_count; /* unsolicited (bytes)*/ > /* offset in unsolicited stream (bytes); */ >- int unsol_offset; >- int data_count; /* remaining Data-Out */ >+ unsigned unsol_offset; >+ unsigned data_count; /* remaining Data-Out */ > struct scsi_cmnd *sc; /* associated SCSI cmd*/ >- int total_length; > struct iscsi_conn *conn; /* used connection */ >- struct iscsi_mgmt_task *mtask; /* tmf mtask in progr */ > > /* state set/tested under session->lock */ > int state; >@@ -152,30 +153,24 @@ struct iscsi_conn { > struct iscsi_cmd_task *ctask; /* xmit ctask in progress */ > > /* xmit */ >- struct kfifo *immqueue; /* immediate xmit queue */ >- struct kfifo *mgmtqueue; /* mgmt (control) xmit queue */ >+ struct list_head mgmtqueue; /* mgmt (control) xmit queue */ > struct list_head mgmt_run_list; /* list of control tasks */ > struct list_head xmitqueue; /* data-path cmd queue */ > struct list_head run_list; /* list of cmds in progress */ >+ struct list_head requeue; /* tasks needing another run */ > struct work_struct xmitwork; /* per-conn. xmit workqueue */ >- /* >- * serializes connection xmit, access to kfifos: >- * xmitqueue, immqueue, mgmtqueue >- */ >- struct mutex xmitmutex; >- > unsigned long suspend_tx; /* suspend Tx */ > unsigned long suspend_rx; /* suspend Rx */ > > /* abort */ > wait_queue_head_t ehwait; /* used in eh_abort() */ > struct iscsi_tm tmhdr; >- struct timer_list tmabort_timer; >- int tmabort_state; /* see TMABORT_INITIAL, etc.*/ >+ struct timer_list tmf_timer; >+ int tmf_state; /* see TMF_INITIAL, etc.*/ > > /* negotiated params */ >- int max_recv_dlength; /* initiator_max_recv_dsl*/ >- int max_xmit_dlength; /* target_max_recv_dsl */ >+ unsigned max_recv_dlength; /* initiator_max_recv_dsl*/ >+ unsigned max_xmit_dlength; /* target_max_recv_dsl */ > int hdrdgst_en; > int datadgst_en; > int ifmarker_en; >@@ -183,6 +178,12 @@ struct iscsi_conn { > /* values userspace uses to id a conn */ > int persistent_port; > char *persistent_address; >+ /* remote portal currently connected to */ >+ int portal_port; >+ char portal_address[ISCSI_ADDRESS_BUF_LEN]; >+ /* local address */ >+ int local_port; >+ char local_address[ISCSI_ADDRESS_BUF_LEN]; > > /* MIB-statistics */ > uint64_t txdata_octets; >@@ -206,25 +207,43 @@ struct iscsi_queue { > }; > > struct iscsi_session { >+ /* >+ * Syncs up the scsi eh thread with the iscsi eh thread when sending >+ * task management functions. This must be taken before the session >+ * and recv lock. >+ */ >+ struct mutex eh_mutex; >+ > /* iSCSI session-wide sequencing */ > uint32_t cmdsn; > uint32_t exp_cmdsn; > uint32_t max_cmdsn; > >+ /* This tracks the reqs queued into the initiator */ >+ uint32_t queued_cmdsn; >+ > /* configuration */ > int initial_r2t_en; >- int max_r2t; >+ unsigned max_r2t; > int imm_data_en; >- int first_burst; >- int max_burst; >+ unsigned first_burst; >+ unsigned max_burst; > int time2wait; > int time2retain; > int pdu_inorder_en; > int dataseq_inorder_en; > int erl; >+ int fast_abort; > int tpgt; >+ char *username; >+ char *username_in; >+ char *password; >+ char *password_in; > char *targetname; >- >+ char *initiatorname; >+ /* hw address or netdev iscsi connection is bound to */ >+ char *hwaddress; >+ char *netdev; > /* control data */ > struct iscsi_transport *tt; > struct Scsi_Host *host; >@@ -252,15 +271,26 @@ struct iscsi_session { > extern int iscsi_change_queue_depth(struct scsi_device *sdev, int depth); > extern int iscsi_eh_abort(struct scsi_cmnd *sc); > extern int iscsi_eh_host_reset(struct scsi_cmnd *sc); >+extern int iscsi_eh_device_reset(struct scsi_cmnd *sc); > extern int iscsi_queuecommand(struct scsi_cmnd *sc, > void (*done)(struct scsi_cmnd *)); > >+ >+/* >+ * iSCSI host helpers. >+ */ >+extern int iscsi_host_set_param(struct Scsi_Host *shost, >+ enum iscsi_host_param param, char *buf, >+ int buflen); >+extern int iscsi_host_get_param(struct Scsi_Host *shost, >+ enum iscsi_host_param param, char *buf); >+ > /* > * session management > */ > extern struct iscsi_cls_session * > iscsi_session_setup(struct iscsi_transport *, struct scsi_transport_template *, >- int, int, uint32_t, uint32_t *); >+ uint16_t, uint16_t, int, int, uint32_t, uint32_t *); > extern void iscsi_session_teardown(struct iscsi_cls_session *); > extern struct iscsi_session *class_to_transport_session(struct iscsi_cls_session *); > extern void iscsi_session_recovery_timedout(struct iscsi_cls_session *); >@@ -289,8 +319,7 @@ extern int iscsi_conn_get_param(struct i > /* > * pdu and task processing > */ >-extern int iscsi_check_assign_cmdsn(struct iscsi_session *, >- struct iscsi_nopin *); >+extern void iscsi_update_cmdsn(struct iscsi_session *, struct iscsi_nopin *); > extern void iscsi_prep_unsolicit_data_pdu(struct iscsi_cmd_task *, > struct iscsi_data *hdr); > extern int iscsi_conn_send_pdu(struct iscsi_cls_conn *, struct iscsi_hdr *, >@@ -301,6 +330,7 @@ extern int __iscsi_complete_pdu(struct i > char *, int); > extern int iscsi_verify_itt(struct iscsi_conn *, struct iscsi_hdr *, > uint32_t *); >+extern void iscsi_requeue_ctask(struct iscsi_cmd_task *ctask); > > /* > * generic helpers >diff -aurp linux-2.6.21.noarch/include/scsi/scsi_transport_iscsi.h linux-2.6.21.noarch.iscsi2/include/scsi/scsi_transport_iscsi.h >--- linux-2.6.21.noarch/include/scsi/scsi_transport_iscsi.h 2007-10-22 10:47:02.000000000 -0500 >+++ linux-2.6.21.noarch.iscsi2/include/scsi/scsi_transport_iscsi.h 2007-10-24 22:26:00.000000000 -0500 >@@ -79,7 +79,8 @@ struct iscsi_transport { > char *name; > unsigned int caps; > /* LLD sets this to indicate what values it can export to sysfs */ >- unsigned int param_mask; >+ uint64_t param_mask; >+ uint64_t host_param_mask; > struct scsi_host_template *host_template; > /* LLD connection data size */ > int conndata_size; >@@ -89,7 +90,8 @@ struct iscsi_transport { > unsigned int max_conn; > unsigned int max_cmd_len; > struct iscsi_cls_session *(*create_session) (struct iscsi_transport *it, >- struct scsi_transport_template *t, uint32_t sn, uint32_t *hn); >+ struct scsi_transport_template *t, uint16_t, uint16_t, >+ uint32_t sn, uint32_t *hn); > void (*destroy_session) (struct iscsi_cls_session *session); > struct iscsi_cls_conn *(*create_conn) (struct iscsi_cls_session *sess, > uint32_t cid); >@@ -105,14 +107,18 @@ struct iscsi_transport { > enum iscsi_param param, char *buf); > int (*get_session_param) (struct iscsi_cls_session *session, > enum iscsi_param param, char *buf); >+ int (*get_host_param) (struct Scsi_Host *shost, >+ enum iscsi_host_param param, char *buf); >+ int (*set_host_param) (struct Scsi_Host *shost, >+ enum iscsi_host_param param, char *buf, >+ int buflen); > int (*send_pdu) (struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr, > char *data, uint32_t data_size); > void (*get_stats) (struct iscsi_cls_conn *conn, > struct iscsi_stats *stats); > void (*init_cmd_task) (struct iscsi_cmd_task *ctask); > void (*init_mgmt_task) (struct iscsi_conn *conn, >- struct iscsi_mgmt_task *mtask, >- char *data, uint32_t data_size); >+ struct iscsi_mgmt_task *mtask); > int (*xmit_cmd_task) (struct iscsi_conn *conn, > struct iscsi_cmd_task *ctask); > void (*cleanup_cmd_task) (struct iscsi_conn *conn, >@@ -124,7 +130,7 @@ struct iscsi_transport { > uint64_t *ep_handle); > int (*ep_poll) (uint64_t ep_handle, int timeout_ms); > void (*ep_disconnect) (uint64_t ep_handle); >- int (*tgt_dscvr) (enum iscsi_tgt_dscvr type, uint32_t host_no, >+ int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type, > uint32_t enable, struct sockaddr *dst_addr); > }; > > >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 318521
: 253021