[PATCH 3/3 2.6.28] cxgb3i - add host_set_param() and fixed ddp tag generation.
From: Karen Xie <[EMAIL PROTECTED]> - added host_set_param() to set private ipv4 address for iscsi traffic. - fixed ddp tag generation when upper 16 bits are used. This patch is based on the cxgb3 branch of the git tree. Signed-off-by: Karen Xie <[EMAIL PROTECTED]> --- drivers/scsi/cxgb3i/cxgb3i.h | 4 - drivers/scsi/cxgb3i/cxgb3i_iscsi.c | 62 +++++++++ drivers/scsi/cxgb3i/cxgb3i_offload.c | 222 ++++++++++++++++++++++------------ drivers/scsi/cxgb3i/cxgb3i_offload.h | 21 ++- drivers/scsi/cxgb3i/cxgb3i_ulp2.c | 61 ++++++--- 5 files changed, 261 insertions(+), 109 deletions(-) diff --git a/drivers/scsi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgb3i/cxgb3i.h index a65995d..e8eca78 100644 --- a/drivers/scsi/cxgb3i/cxgb3i.h +++ b/drivers/scsi/cxgb3i/cxgb3i.h @@ -47,6 +47,7 @@ struct cxgb3i_endpoint; * @rsvd_bits: # of bits used by h/w * @rsvd_shift: shift left * @rsvd_mask: bit mask + * @rsvd_tag_mask: h/w tag bit mask * */ struct cxgb3i_tag_format { @@ -55,6 +56,7 @@ struct cxgb3i_tag_format { unsigned char rsvd_bits; unsigned char rsvd_shift; u32 rsvd_mask; + u32 rsvd_tag_mask; }; /** @@ -172,6 +174,4 @@ u32 cxgb3i_ddp_tag_reserve(struct cxgb3i_adapter *, unsigned int, u32, unsigned int, struct scatterlist *, unsigned int); int cxgb3i_conn_ulp2_xmit(struct iscsi_conn *); - -void cxgb3i_display_byte_string(char *, unsigned char *, int, int); #endif diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c index e3a7443..c2324fe 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c +++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c @@ -9,6 +9,7 @@ * Written by: Karen Xie ([EMAIL PROTECTED]) */ +#include <linux/inet.h> #include <net/tcp.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.h> @@ -253,9 +254,6 @@ static int cxgb3i_ep_poll(struct iscsi_endpoint *ep, int timeout_ms) struct cxgb3i_endpoint *cep = ep->dd_data; struct s3_conn *c3cn = cep->c3cn; - cxgb3i_log_debug("ep 0x%p, timeout %d, c3cn 0x%p, state 0x%x.\n", - ep, timeout_ms, c3cn, c3cn->state); - if (!c3cn_in_state(c3cn, C3CN_STATE_ESTABLISHED)) { cxgb3i_log_info("not in established state.\n"); return 0; @@ -409,12 +407,11 @@ static int cxgb3i_conn_xmit_segment(struct iscsi_conn *conn) struct iscsi_segment *segment = &tcp_conn->out.segment; if (segment->total_copied < segment->total_size) - return cxgb3i_conn_ulp2_xmit(conn); + return cxgb3i_conn_ulp2_xmit(conn); return 0; } - /** * cxgb3i_conn_bind - binds iscsi sess, conn and endpoint together * @cls_session: pointer to iscsi cls session @@ -559,6 +556,48 @@ static int cxgb3i_conn_set_param(struct iscsi_cls_conn *cls_conn, } /** + * cxgb3i_host_set_param - configure host (adapter) related parameters + * @shost: scsi host pointer + * @param: parameter type identifier + * @buf: buffer pointer + */ +static int cxgb3i_host_set_param(struct Scsi_Host *shost, + enum iscsi_host_param param, + char *buf, int buflen) +{ + static struct cxgb3i_hba *hba; + int rc = -EINVAL; + + cxgb3i_log_debug("param %d, buf %s.\n", param, buf); + + switch (param) { + case ISCSI_HOST_PARAM_NETDEV_NAME: + { + struct net_device *ndev = dev_get_by_name(&init_net, buf); + + if (ndev) { + hba = cxgb3i_hba_find_by_netdev(ndev); + if (hba) + rc = 0; + else + cxgb3i_log_info("%s not a cxgb3i device.\n", + buf); + } + break; + } + case ISCSI_HOST_PARAM_IPADDRESS: + if (hba) { + __be32 addr = in_aton(buf); + rc = cxgb3i_set_private_ipv4addr(hba->ndev, addr); + } + break; + default: + return iscsi_host_get_param(shost, param, buf); + } + return rc; +} + +/** * cxgb3i_host_get_param - returns host (adapter) related parameters * @shost: scsi host pointer * @param: parameter type identifier @@ -571,6 +610,8 @@ static int cxgb3i_host_get_param(struct Scsi_Host *shost, int i; int len = 0; + cxgb3i_log_debug("hba %s, param %d.\n", hba->ndev->name, param); + switch (param) { case ISCSI_HOST_PARAM_HWADDRESS: for (i = 0; i < 6; i++) @@ -583,6 +624,16 @@ static int cxgb3i_host_get_param(struct Scsi_Host *shost, case ISCSI_HOST_PARAM_NETDEV_NAME: len = sprintf(buf, "%s\n", hba->ndev->name); break; + case ISCSI_HOST_PARAM_IPADDRESS: + { + int rc; + __be32 addr; + + rc = cxgb3i_get_private_ipv4addr(hba->ndev, &addr); + if (!rc) + len = sprintf(buf, "%u.%u.%u.%u", NIPQUAD(addr)); + break; + } default: return iscsi_host_get_param(shost, param, buf); } @@ -746,6 +797,7 @@ static struct iscsi_transport cxgb3i_iscsi_transport = { .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | ISCSI_HOST_INITIATOR_NAME | ISCSI_HOST_NETDEV_NAME, .get_host_param = cxgb3i_host_get_param, + .set_host_param = cxgb3i_host_set_param, /* session management */ .create_session = cxgb3i_session_create, .destroy_session = cxgb3i_session_destroy, diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c index bb968ae..fbc0e8a 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_offload.c +++ b/drivers/scsi/cxgb3i/cxgb3i_offload.c @@ -39,12 +39,6 @@ static unsigned int sport_base = 20000; module_param(sport_base, uint, 0644); MODULE_PARM_DESC(sport_start, "starting port number (default=20000)"); -#ifdef __DEBUG_C3CN_CONN__ -#define c3cn_conn_debug cxgb3i_log_debug -#else -#define c3cn_conn_debug(fmt...) -#endif - #ifdef __DEBUG_C3CN_TX__ #define c3cn_tx_debug cxgb3i_log_debug #else @@ -197,7 +191,7 @@ static void s3_init_wr_tab(unsigned int wr_len) } /* - * Initialization/cleanup cxgb3 API operations. + * cxgb3i API operations. */ /* * large memory chunk allocation/release @@ -306,6 +300,36 @@ void cxgb3i_sdev_remove(struct t3cdev *cdev) } /* + * set/get iscsi private address + */ +int cxgb3i_set_private_ipv4addr(struct net_device *ndev, __be32 addr) +{ + struct t3cdev *tdev = dev2t3cdev(ndev); + struct iscsi_ipv4addr ii; + int rc; + + ii.dev = ndev; + ii.ipv4addr = addr; + rc = tdev->ctl(tdev, SET_ISCSI_IPV4ADDR, &ii); + if (!rc) + cxgb3i_log_info("%s -> iscsi IPV4 %u.%u.%u.%u.\n", + ndev->name, NIPQUAD(addr)); + return rc; +} + +int cxgb3i_get_private_ipv4addr(struct net_device *ndev, __be32 *addrp) +{ + struct t3cdev *tdev = dev2t3cdev(ndev); + struct iscsi_ipv4addr ii; + int rc; + + ii.dev = ndev; + rc = tdev->ctl(tdev, GET_ISCSI_IPV4ADDR, &ii); + *addrp = rc ? 0 : ii.ipv4addr; + return rc; +} + +/* * Return TRUE if the specified net device is for a port on one of our * registered adapters. */ @@ -410,11 +434,15 @@ void c3cn_close(struct s3_conn *c3cn) /* Nothing if we are already closed */ ; else if (data_lost || c3cn->state == C3CN_STATE_SYN_SENT) { + c3cn_conn_debug("c3cn 0x%p, 0x%x -> closing, send reset.\n", + c3cn, c3cn->state); /* Unread data was tossed, zap the connection. */ s3_send_reset(c3cn, CPL_ABORT_SEND_RST, NULL); release_port(c3cn); goto unlock; } else if (c3cn->state == C3CN_STATE_ESTABLISHED) { + c3cn_conn_debug("c3cn 0x%p, est. -> closing, send close_req.\n", + c3cn); c3cn_set_state(c3cn, C3CN_STATE_CLOSING); mk_close_req(c3cn); } @@ -454,8 +482,8 @@ out: * ====================================================================== */ -static int s3_connect(struct s3_conn *); static u32 s3_send_rx_credits(struct s3_conn *, u32, u32, int); +static int act_open(struct s3_conn *, struct net_device *); static void mk_act_open_req(struct s3_conn *, struct sk_buff *, unsigned int, const struct l2t_entry *); static void skb_entail(struct s3_conn *, struct sk_buff *, int); @@ -545,6 +573,36 @@ static inline void make_tx_data_wr(struct s3_conn *c3cn, } } +/** + * cxgb3_egress_dev - return the cxgb3 egress device or NULL if the egress + * device isn't one of our ports. + * + * @root_dev: the root device anchoring the search + * @c3cn: the connection used to determine egress port in bonding mode + * @context: in bonding mode, indicates a connection set up or failover + * + * Given a root network device it returns the physical egress device that is a + * descendant of the root device. The root device may be either a physical + * device, in which case it is the device returned, or a virtual device, such + * as a VLAN or bonding device. In case of a bonding device the search + * considers the decisions of the bonding device given its mode to locate the + * correct egress device. + */ +static struct net_device *cxgb3_egress_dev(struct net_device *root_dev, + struct s3_conn *c3cn, + int context) +{ + while (root_dev) { + if (root_dev->priv_flags & IFF_802_1Q_VLAN) + root_dev = vlan_dev_real_dev(root_dev); + else if (is_cxgb3_dev(root_dev)) + return root_dev; + else + return NULL; + } + return NULL; +} + static struct rtable *find_route(__be32 saddr, __be32 daddr, __be16 sport, __be16 dport) { @@ -570,6 +628,10 @@ static struct rtable *find_route(__be32 saddr, __be32 daddr, int cxgb3i_c3cn_connect(struct s3_conn *c3cn, struct sockaddr_in *usin) { struct rtable *rt; + struct net_device *dev; + struct cxgb3i_sdev_data *cdata; + struct t3cdev *cdev; + __be32 sipv4; int err; if (usin->sin_family != AF_INET) @@ -608,14 +670,42 @@ int cxgb3i_c3cn_connect(struct s3_conn *c3cn, struct sockaddr_in *usin) if (!c3cn->saddr.sin_addr.s_addr) c3cn->saddr.sin_addr.s_addr = rt->rt_src; - c3cn_conn_debug("c3cn 0x%p -> SYN_SENT.\n", c3cn); - c3cn_set_state(c3cn, C3CN_STATE_SYN_SENT); - /* now commit destination to connection */ c3cn->dst_cache = &rt->u.dst; - if (s3_connect(c3cn)) + /* try to establish an offloaded connection */ + dev = cxgb3_egress_dev(c3cn->dst_cache->dev, c3cn, 0); + if (dev == NULL) { + c3cn_conn_debug("c3cn 0x%p, egress dev NULL.\n", c3cn); + return -ENETUNREACH; + } + cdata = NDEV2CDATA(dev); + cdev = cdata->cdev; + + err = cxgb3i_get_private_ipv4addr(dev, &sipv4); + if (err) + return err; + + if (!sipv4) { + c3cn_conn_debug("c3cn 0x%p, iscsi ip not configured.\n", c3cn); + sipv4 = c3cn->saddr.sin_addr.s_addr + 0x1000000; + err = cxgb3i_set_private_ipv4addr(dev, sipv4); + if (err) + return err; + } + c3cn->saddr.sin_addr.s_addr = sipv4; + + c3cn_conn_debug("c3cn 0x%p, %u.%u.%u.%u,%u-%u.%u.%u.%u,%u SYN_SENT.\n", + c3cn, NIPQUAD(c3cn->saddr.sin_addr.s_addr), + ntohs(c3cn->saddr.sin_port), + NIPQUAD(c3cn->daddr.sin_addr.s_addr), + ntohs(c3cn->daddr.sin_port)); + + c3cn_set_state(c3cn, C3CN_STATE_SYN_SENT); + + if (!act_open(c3cn, dev)) return 0; + /* * If we get here, we don't have an offload connection so simply * return a failure. @@ -763,6 +853,8 @@ static void abort_arp_failure(struct t3cdev *cdev, struct sk_buff *skb) { struct cpl_abort_req *req = cplhdr(skb); + c3cn_conn_debug("tdev 0x%p.\n", cdev); + req->cmd = CPL_ABORT_NO_RST; cxgb3_ofld_send(cdev, skb); } @@ -785,7 +877,8 @@ static int s3_send_reset(struct s3_conn *c3cn, int mode, return 1; } - c3cn_conn_debug("c3cn 0x%p, mode %d.\n", c3cn, mode); + c3cn_conn_debug("c3cn 0x%p, mode %d, flag ABORT_RPL + ABORT_SHUT.\n", + c3cn, mode); c3cn_set_flag(c3cn, C3CN_ABORT_RPL_PENDING); c3cn_set_flag(c3cn, C3CN_ABORT_SHUTDOWN); @@ -873,7 +966,6 @@ static void process_rx_iscsi_hdr(struct s3_conn *, struct sk_buff *); static struct sk_buff *__get_cpl_reply_skb(struct sk_buff *, size_t, gfp_t); -static int act_open(struct s3_conn *, struct net_device *); static void fail_act_open(struct s3_conn *, int); static void init_offload_conn(struct s3_conn *, struct t3cdev *, struct dst_entry *); @@ -919,51 +1011,6 @@ static struct sk_buff *alloc_ctrl_skb(const struct s3_conn *c3cn, return skb; } -/** - * cxgb3_egress_dev - return the cxgb3 egress device or NULL if the egress - * device isn't one of our ports. - * - * @root_dev: the root device anchoring the search - * @c3cn: the connection used to determine egress port in bonding mode - * @context: in bonding mode, indicates a connection set up or failover - * - * Given a root network device it returns the physical egress device that is a - * descendant of the root device. The root device may be either a physical - * device, in which case it is the device returned, or a virtual device, such - * as a VLAN or bonding device. In case of a bonding device the search - * considers the decisions of the bonding device given its mode to locate the - * correct egress device. - */ -static struct net_device *cxgb3_egress_dev(struct net_device *root_dev, - struct s3_conn *c3cn, - int context) -{ - while (root_dev) { - if (root_dev->priv_flags & IFF_802_1Q_VLAN) - root_dev = vlan_dev_real_dev(root_dev); - else if (is_cxgb3_dev(root_dev)) - return root_dev; - else - return NULL; - } - return NULL; -} - -/* - * Return TRUE if we're able to establish an offload connection; otherwise - * return FALSE. - */ -static int s3_connect(struct s3_conn *c3cn) -{ - struct net_device *dev = cxgb3_egress_dev(c3cn->dst_cache->dev, - c3cn, 0); - if (dev == NULL) { - c3cn_conn_debug("c3cn 0x%p, egress dev NULL.\n", c3cn); - return 0; - } - return act_open(c3cn, dev) == 0; -} - /* * Handle an ARP failure for an active open. */ @@ -971,6 +1018,8 @@ static void act_open_req_arp_failure(struct t3cdev *dev, struct sk_buff *skb) { struct s3_conn *c3cn = (struct s3_conn *)skb->sk; + c3cn_conn_debug("c3cn 0x%p, state 0x%x.\n", c3cn, c3cn->state); + c3cn_hold(c3cn); spin_lock(&c3cn->lock); if (c3cn->state == C3CN_STATE_SYN_SENT) { @@ -1097,10 +1146,6 @@ static void mk_act_open_req(struct s3_conn *c3cn, struct sk_buff *skb, unsigned int atid, const struct l2t_entry *e) { struct cpl_act_open_req *req; - struct iscsi_ipv4addr ii; - - ii.dev = c3cn->dev; - c3cn->cdev->ctl(c3cn->cdev, GET_ISCSI_IPV4ADDR, &ii); c3cn_conn_debug("c3cn 0x%p, atid 0x%x.\n", c3cn, atid); @@ -1110,7 +1155,7 @@ static void mk_act_open_req(struct s3_conn *c3cn, struct sk_buff *skb, OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, atid)); req->local_port = c3cn->saddr.sin_port; req->peer_port = c3cn->daddr.sin_port; - req->local_ip = ii.ipv4addr; + req->local_ip = c3cn->saddr.sin_addr.s_addr; req->peer_ip = c3cn->daddr.sin_addr.s_addr; req->opt0h = htonl(calc_opt0h(c3cn) | V_L2T_IDX(e->idx) | V_TX_CHANNEL(e->smt_idx)); @@ -1165,6 +1210,8 @@ static inline void abort_conn(struct s3_conn *c3cn, { struct sk_buff *abort_skb; + c3cn_conn_debug("c3cn 0x%p, state 0x%x.\n", c3cn, c3cn->state); + abort_skb = __get_cpl_reply_skb(skb, sizeof(struct cpl_abort_req), GFP_ATOMIC); if (abort_skb) @@ -1197,7 +1244,8 @@ static int do_act_establish(struct t3cdev *cdev, struct sk_buff *skb, struct s3_conn *c3cn = ctx; struct cxgb3i_sdev_data *cdata = CXGB3_SDEV_DATA(cdev); - c3cn_conn_debug("c3cn 0x%p, tid 0x%x.\n", c3cn, tid); + c3cn_conn_debug("rcv, tid 0x%x, c3cn 0x%p, 0x%x, 0x%lx.\n", + tid, c3cn, c3cn->state, c3cn->flags); /* * It's OK if the TID is currently in use, the owning connection may * have backlogged its last CPL message(s). Just take it away. @@ -1220,7 +1268,8 @@ static int do_act_open_rpl(struct t3cdev *cdev, struct sk_buff *skb, void *ctx) struct s3_conn *c3cn = ctx; struct cpl_act_open_rpl *rpl = cplhdr(skb); - c3cn_conn_debug("c3cn 0x%p, status 0x%x.\n", c3cn, rpl->status); + c3cn_conn_debug("rcv, status 0x%x, c3cn 0x%p, 0x%x, 0x%lx.\n", + rpl->status, c3cn, c3cn->state, c3cn->flags); if (act_open_has_tid(rpl->status)) cxgb3_queue_tid_release(cdev, GET_TID(rpl)); @@ -1257,8 +1306,8 @@ static int do_peer_close(struct t3cdev *cdev, struct sk_buff *skb, void *ctx) { struct s3_conn *c3cn = ctx; - c3cn_conn_debug("c3cn 0x%p, state 0x%x, flag 0x%lx.\n", - c3cn, c3cn->state, c3cn->flags); + c3cn_conn_debug("rcv, c3cn 0x%p, 0x%x, 0x%lx.\n", + c3cn, c3cn->state, c3cn->flags); process_cpl_msg_ref(do_peer_fin, c3cn, skb); return 0; } @@ -1271,14 +1320,14 @@ static int do_abort_req(struct t3cdev *cdev, struct sk_buff *skb, void *ctx) const struct cpl_abort_req_rss *req = cplhdr(skb); struct s3_conn *c3cn = ctx; + c3cn_conn_debug("rcv, c3cn 0x%p, 0x%x, 0x%lx.\n", + c3cn, c3cn->state, c3cn->flags); + if (is_neg_adv_abort(req->status)) { __kfree_skb(skb); return 0; } - c3cn_conn_debug("c3cn 0x%p, state 0x%x, flag 0x%lx.\n", - c3cn, c3cn->state, c3cn->flags); - process_cpl_msg_ref(process_abort_req, c3cn, skb); return 0; } @@ -1289,7 +1338,11 @@ static int do_abort_req(struct t3cdev *cdev, struct sk_buff *skb, void *ctx) static int do_abort_rpl(struct t3cdev *cdev, struct sk_buff *skb, void *ctx) { struct cpl_abort_rpl_rss *rpl = cplhdr(skb); - struct s3_conn *c3cn; + struct s3_conn *c3cn = ctx; + + c3cn_conn_debug("rcv, status 0x%x, c3cn 0x%p, 0x%x, 0x%lx.\n", + rpl->status, c3cn, c3cn ? c3cn->state : 0, + c3cn ? c3cn->flags : 0UL); /* * Ignore replies to post-close aborts indicating that the abort was @@ -1300,10 +1353,6 @@ static int do_abort_rpl(struct t3cdev *cdev, struct sk_buff *skb, void *ctx) if (rpl->status == CPL_ERR_ABORT_FAILED) goto discard; - c3cn = ctx; - c3cn_conn_debug("c3cn 0x%p, state 0x%x, flag 0x%lx.\n", - c3cn, c3cn->state, c3cn->flags); - /* * Sometimes we've already closed the connection, e.g., a post-close * abort races with ABORT_REQ_RSS, the latter frees the connection @@ -1330,7 +1379,7 @@ static int do_close_con_rpl(struct t3cdev *cdev, struct sk_buff *skb, { struct s3_conn *c3cn = ctx; - c3cn_conn_debug("c3cn 0x%p, state 0x%x, flag 0x%lx.\n", + c3cn_conn_debug("rcv, c3cn 0x%p, 0x%x, 0x%lx.\n", c3cn, c3cn->state, c3cn->flags); process_cpl_msg_ref(process_close_con_rpl, c3cn, skb); @@ -1415,6 +1464,8 @@ static void c3cn_act_establish(struct s3_conn *c3cn, struct cpl_act_establish *req = cplhdr(skb); u32 rcv_isn = ntohl(req->rcv_isn); /* real RCV_ISN + 1 */ + c3cn_conn_debug("c3cn 0x%p, state 0x%x.\n", c3cn, c3cn->state); + if (unlikely(c3cn->state != C3CN_STATE_SYN_SENT)) printk(KERN_ERR "TID %u expected SYN_SENT, found %d\n", c3cn->tid, c3cn->state); @@ -1436,6 +1487,8 @@ static void active_open_failed(struct s3_conn *c3cn, { struct cpl_act_open_rpl *rpl = cplhdr(skb); + c3cn_conn_debug("c3cn 0x%p, state 0x%x.\n", c3cn, c3cn->state); + if (rpl->status == CPL_ERR_CONN_EXIST && c3cn->retry_timer.function != act_open_retry_timer) { c3cn->retry_timer.function = act_open_retry_timer; @@ -1572,6 +1625,9 @@ static void do_peer_fin(struct s3_conn *c3cn, struct sk_buff *skb) { int keep = 0; + c3cn_conn_debug("rcv, c3cn 0x%p, 0x%x, 0x%lx.\n", + c3cn, c3cn->state, c3cn->flags); + if (c3cn_flag(c3cn, C3CN_ABORT_RPL_PENDING)) goto out; @@ -1607,6 +1663,8 @@ static void process_abort_req(struct s3_conn *c3cn, int rst_status = CPL_ABORT_NO_RST; const struct cpl_abort_req_rss *req = cplhdr(skb); + c3cn_conn_debug("c3cn 0x%p, state 0x%x.\n", c3cn, c3cn->state); + if (!c3cn_flag(c3cn, C3CN_ABORT_REQ_RCVD)) { c3cn_set_flag(c3cn, C3CN_ABORT_REQ_RCVD); c3cn_set_flag(c3cn, C3CN_ABORT_SHUTDOWN); @@ -1644,6 +1702,8 @@ static void process_abort_req(struct s3_conn *c3cn, static void process_abort_rpl(struct s3_conn *c3cn, struct sk_buff *skb) { + c3cn_conn_debug("c3cn 0x%p, state 0x%x.\n", c3cn, c3cn->state); + if (c3cn_flag(c3cn, C3CN_ABORT_RPL_PENDING)) { if (!c3cn_flag(c3cn, C3CN_ABORT_RPL_RCVD)) c3cn_set_flag(c3cn, C3CN_ABORT_RPL_RCVD); @@ -1666,6 +1726,8 @@ static void process_close_con_rpl(struct s3_conn *c3cn, { struct cpl_close_con_rpl *rpl = cplhdr(skb); + c3cn_conn_debug("c3cn 0x%p, state 0x%x.\n", c3cn, c3cn->state); + c3cn->snd_una = ntohl(rpl->snd_nxt) - 1; /* exclude FIN */ if (c3cn_flag(c3cn, C3CN_ABORT_RPL_PENDING)) @@ -1722,6 +1784,8 @@ static unsigned int select_mss(struct s3_conn *c3cn, unsigned int pmtu) static void fail_act_open(struct s3_conn *c3cn, int errno) { + c3cn_conn_debug("c3cn 0x%p, state 0x%x.\n", c3cn, c3cn->state); + c3cn->err = errno; t3_release_offload_resources(c3cn); c3cn_done(c3cn); @@ -1748,6 +1812,8 @@ static void act_open_retry_timer(unsigned long data) struct sk_buff *skb; struct s3_conn *c3cn = (struct s3_conn *)data; + c3cn_conn_debug("c3cn 0x%p, state 0x%x.\n", c3cn, c3cn->state); + spin_lock(&c3cn->lock); skb = alloc_skb(sizeof(struct cpl_act_open_req), GFP_ATOMIC); if (!skb) @@ -1913,6 +1979,8 @@ static struct sk_buff *__get_cpl_reply_skb(struct sk_buff *skb, size_t len, static void make_established(struct s3_conn *c3cn, u32 snd_isn, unsigned int opt) { + c3cn_conn_debug("c3cn 0x%p, state 0x%x.\n", c3cn, c3cn->state); + c3cn->write_seq = c3cn->snd_nxt = c3cn->snd_una = snd_isn; /* diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.h b/drivers/scsi/cxgb3i/cxgb3i_offload.h index 0c17abd..42ed6c3 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_offload.h +++ b/drivers/scsi/cxgb3i/cxgb3i_offload.h @@ -29,6 +29,12 @@ #define cxgb3i_log_debug(fmt...) #endif +#ifdef __DEBUG_C3CN_CONN__ +#define c3cn_conn_debug cxgb3i_log_debug +#else +#define c3cn_conn_debug(fmt...) +#endif + /* * Data structure to keep track of cxgb3 connection. */ @@ -95,7 +101,6 @@ static inline unsigned int c3cn_in_state(const struct s3_conn *c3cn, return states & c3cn->state; } - /* * Connection flags -- many to track some close related events. */ @@ -115,12 +120,16 @@ static inline void c3cn_set_flag(struct s3_conn *c3cn, enum c3cn_flags flag) { __set_bit(flag, &c3cn->flags); + c3cn_conn_debug("c3cn 0x%p, %d, 0x%x, 0x%lx.\n", + c3cn, flag, c3cn->state, c3cn->flags); } static inline void c3cn_reset_flag(struct s3_conn *c3cn, enum c3cn_flags flag) { __clear_bit(flag, &c3cn->flags); + c3cn_conn_debug("c3cn 0x%p, %d, 0x%x, 0x%lx.\n", + c3cn, flag, c3cn->state, c3cn->flags); } static inline int c3cn_flag(struct s3_conn *c3cn, enum c3cn_flags flag) @@ -155,8 +164,11 @@ static inline void c3cn_hold(struct s3_conn *c3cn) static inline void c3cn_put(struct s3_conn *c3cn) { - if (atomic_dec_and_test(&c3cn->refcnt)) + if (atomic_dec_and_test(&c3cn->refcnt)) { + c3cn_conn_debug("c3cn 0x%p, 0x%x, 0x%lx.\n", + c3cn, c3cn->state, c3cn->flags); kfree(c3cn); + } } void c3cn_close(struct s3_conn *); @@ -169,6 +181,8 @@ static inline void c3cn_release(struct s3_conn *c3cn) /* * Primary API routines. */ +int cxgb3i_set_private_ipv4addr(struct net_device *, __be32); +int cxgb3i_get_private_ipv4addr(struct net_device *, __be32 *); void cxgb3i_sdev_cleanup(void); int cxgb3i_sdev_init(cxgb3_cpl_handler_func *); @@ -216,11 +230,8 @@ static inline void process_cpl_msg(void (*fn)(struct s3_conn *, struct s3_conn *c3cn, struct sk_buff *skb) { -cxgb3i_log_debug("c3cn 0x%p, locking ....\n", c3cn); spin_lock(&c3cn->lock); -cxgb3i_log_debug("c3cn 0x%p, locked.\n", c3cn); fn(c3cn, skb); -cxgb3i_log_debug("c3cn 0x%p, unlock.\n", c3cn); spin_unlock(&c3cn->lock); } diff --git a/drivers/scsi/cxgb3i/cxgb3i_ulp2.c b/drivers/scsi/cxgb3i/cxgb3i_ulp2.c index ef85401..f11ec43 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ulp2.c +++ b/drivers/scsi/cxgb3i/cxgb3i_ulp2.c @@ -1,5 +1,5 @@ /* - * cxgb3i_ddp.c: Chelsio S3xx iSCSI driver. + * cxgb3i_ulp2.c: Chelsio S3xx iSCSI driver. * * Copyright (c) 2008 Chelsio Communications, Inc. * @@ -59,7 +59,7 @@ static void cxgb3i_ddp_page_init(void) unsigned long n = PAGE_SIZE >> ULP2_4K_PAGE_SHIFT; if (PAGE_SIZE & (~ULP2_4K_PAGE_MASK)) { - cxgb3i_log_warn("PAGE_SIZE 0x%lx is not multiple of 4K, " + cxgb3i_log_debug("PAGE_SIZE 0x%lx is not multiple of 4K, " "ddp disabled.\n", PAGE_SIZE); return; } @@ -105,8 +105,10 @@ static int set_ddp_map(struct cxgb3i_adapter *snic, struct pagepod_hdr *hdr, skb = alloc_skb(sizeof(struct ulp_mem_io) + PPOD_SIZE, GFP_ATOMIC); - if (!skb) + if (!skb) { + cxgb3i_log_debug("skb OMM.\n"); return -ENOMEM; + } skb_put(skb, sizeof(struct ulp_mem_io) + PPOD_SIZE); ulp_mem_io_set_hdr(skb, pm_addr); @@ -164,8 +166,11 @@ static int cxgb3i_ddp_sgl_check(struct scatterlist *sgl, unsigned int sgcnt) for_each_sg(sgl, sg, sgcnt, i) { if ((i && sg->offset) || ((i != sgcnt - 1) && - (sg->length + sg->offset) != PAGE_SIZE)) + (sg->length + sg->offset) != PAGE_SIZE)) { + cxgb3i_tag_debug("sg %u/%u, off %u, len %u.\n", + i, sgcnt, sg->offset, sg->length); return -EINVAL; + } } return 0; @@ -212,12 +217,18 @@ u32 cxgb3i_ddp_tag_reserve(struct cxgb3i_adapter *snic, unsigned int tid, u32 tag; int err; - if (!ddp || !sgcnt || xferlen < PAGE_SIZE) + if (!ddp || !sgcnt || xferlen < PAGE_SIZE) { + cxgb3i_tag_debug("sgcnt %u, xferlen %u < %lu, NO DDP.\n", + sgcnt, xferlen, PAGE_SIZE); return RESERVED_ITT; + } err = cxgb3i_ddp_sgl_check(sgl, sgcnt); - if (err < 0) + if (err < 0) { + cxgb3i_tag_debug("sgcnt %u, xferlen %u, SGL check fail.\n", + sgcnt, xferlen); return RESERVED_ITT; + } npods = (sgcnt + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT; idx_max = ddp->nppods - npods + 1; @@ -232,17 +243,23 @@ u32 cxgb3i_ddp_tag_reserve(struct cxgb3i_adapter *snic, unsigned int tid, ddp->idx_last - npods + 1, npods); } - if (idx < 0) + if (idx < 0) { + cxgb3i_tag_debug("sgcnt %u, xferlen %u, npods %u NO DDP.\n", + sgcnt, xferlen, npods); return RESERVED_ITT; + } - if (pci_map_sg(snic->pdev, sgl, sgcnt, PCI_DMA_FROMDEVICE) <= 0) + if (pci_map_sg(snic->pdev, sgl, sgcnt, PCI_DMA_FROMDEVICE) <= 0) { + cxgb3i_tag_debug("sgcnt %u, xferlen %u, pci map failed.\n", + sgcnt, xferlen); goto unmark_entries; + } tag = sw_tag | (idx << snic->tag_format.rsvd_shift); hdr.rsvd = 0; hdr.vld_tid = htonl(F_PPOD_VALID | V_PPOD_TID(tid)); - hdr.pgsz_tag_clr = htonl(tag); + hdr.pgsz_tag_clr = htonl(tag & snic->tag_format.rsvd_tag_mask); hdr.maxoffset = htonl(xferlen); hdr.pgoffset = htonl(sgl->offset); @@ -250,7 +267,7 @@ u32 cxgb3i_ddp_tag_reserve(struct cxgb3i_adapter *snic, unsigned int tid, goto unmap_sgl; ddp->idx_last = idx; - cxgb3i_tag_debug("tid 0x%x, xfer %u, 0x%x -> ddp tag 0x%x (%u, %u).\n", + cxgb3i_tag_debug("tid 0x%x, xfer %u, 0x%x -> ddp 0x%x (0x%x, %u).\n", tid, xferlen, sw_tag, tag, idx, npods); return tag; @@ -358,12 +375,9 @@ static int cxgb3i_conn_read_pdu_skb(struct iscsi_conn *conn, hdr->opcode & ISCSI_OPCODE_MASK, tcp_conn->in.datalen); segment->total_copied = segment->total_size; - } else { - cxgb3i_ddp_debug("opcode 0x%x, data %u, not ddp'ed.\n", - hdr->opcode & ISCSI_OPCODE_MASK, - tcp_conn->in.datalen); + } else offset += sizeof(struct cpl_iscsi_hdr_norss); - } + while (segment->total_copied < segment->total_size) { iscsi_tcp_segment_map(segment, 1); err = skb_copy_bits(skb, offset, segment->data, @@ -643,11 +657,8 @@ int cxgb3i_adapter_ulp_init(struct cxgb3i_adapter *snic) snic->tag_format.rsvd_bits = bits; snic->tag_format.rsvd_shift = PPOD_IDX_SHIFT; snic->tag_format.rsvd_mask = (1 << snic->tag_format.rsvd_bits) - 1; - - cxgb3i_log_debug("snic nppods %u, rsvd shift %u, bits %u, mask 0x%x.\n", - ppmax, snic->tag_format.rsvd_shift, - snic->tag_format.rsvd_bits, - snic->tag_format.rsvd_mask); + snic->tag_format.rsvd_tag_mask = + (1 << (snic->tag_format.rsvd_bits + PPOD_IDX_SHIFT)) - 1; ddp->map = cxgb3i_alloc_big_mem(ppmax); if (!ddp->map) { @@ -663,6 +674,8 @@ int cxgb3i_adapter_ulp_init(struct cxgb3i_adapter *snic) for (i = 0; i < ULP2_PGIDX_MAX; i++) uinfo.pgsz_factor[i] = ddp_page_order[i]; + uinfo.ulimit = uinfo.llimit + (ppmax << PPOD_SIZE_SHIFT); + err = tdev->ctl(tdev, ULP_ISCSI_SET_PARAMS, &uinfo); if (err < 0) { cxgb3i_log_warn("snic unable to set iscsi param err=%d, " @@ -675,6 +688,14 @@ int cxgb3i_adapter_ulp_init(struct cxgb3i_adapter *snic) tdev->ulp_iscsi = ddp; + cxgb3i_log_info("snic nppods %u (0x%x ~ 0x%x), rsvd shift %u, " + "bits %u, mask 0x%x, 0x%x.\n", + ppmax, ddp->llimit, ddp->ulimit, + snic->tag_format.rsvd_shift, + snic->tag_format.rsvd_bits, + snic->tag_format.rsvd_mask, + uinfo.tagmask); + return 0; free_ppod_map: --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "open-iscsi" group. To post to this group, send email to open-iscsi@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/open-iscsi -~----------~----~----~----~------~----~------~--~---