diff options
Diffstat (limited to 'drivers/scsi/cxgbi')
| -rw-r--r-- | drivers/scsi/cxgbi/cxgb3i/Kbuild | 2 | ||||
| -rw-r--r-- | drivers/scsi/cxgbi/cxgb3i/Kconfig | 3 | ||||
| -rw-r--r-- | drivers/scsi/cxgbi/cxgb3i/cxgb3i.c | 30 | ||||
| -rw-r--r-- | drivers/scsi/cxgbi/cxgb4i/Kbuild | 2 | ||||
| -rw-r--r-- | drivers/scsi/cxgbi/cxgb4i/Kconfig | 3 | ||||
| -rw-r--r-- | drivers/scsi/cxgbi/cxgb4i/cxgb4i.c | 153 | ||||
| -rw-r--r-- | drivers/scsi/cxgbi/libcxgbi.c | 122 | ||||
| -rw-r--r-- | drivers/scsi/cxgbi/libcxgbi.h | 11 |
8 files changed, 208 insertions, 118 deletions
diff --git a/drivers/scsi/cxgbi/cxgb3i/Kbuild b/drivers/scsi/cxgbi/cxgb3i/Kbuild index 09dbf9efc8e..6f095e28a97 100644 --- a/drivers/scsi/cxgbi/cxgb3i/Kbuild +++ b/drivers/scsi/cxgbi/cxgb3i/Kbuild @@ -1,3 +1,3 @@ -EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb3 +EXTRA_CFLAGS += -I$(srctree)/drivers/net/ethernet/chelsio/cxgb3 obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o diff --git a/drivers/scsi/cxgbi/cxgb3i/Kconfig b/drivers/scsi/cxgbi/cxgb3i/Kconfig index 11dff23f783..6bbc36fbd6e 100644 --- a/drivers/scsi/cxgbi/cxgb3i/Kconfig +++ b/drivers/scsi/cxgbi/cxgb3i/Kconfig @@ -2,7 +2,8 @@ config SCSI_CXGB3_ISCSI tristate "Chelsio T3 iSCSI support" depends on PCI && INET select NETDEVICES - select NETDEV_10000 + select ETHERNET + select NET_VENDOR_CHELSIO select CHELSIO_T3 select SCSI_ISCSI_ATTRS ---help--- diff --git a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c index fc2cdb62f53..49692a1ac44 100644 --- a/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c +++ b/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c @@ -14,7 +14,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ -#include <linux/version.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <scsi/scsi_host.h> @@ -106,25 +105,7 @@ static struct iscsi_transport cxgb3i_iscsi_transport = { .caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST | CAP_DATADGST | CAP_DIGEST_OFFLOAD | CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO, - .param_mask = ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH | - ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN | - ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T | - ISCSI_IMM_DATA_EN | ISCSI_FIRST_BURST | - ISCSI_MAX_BURST | ISCSI_PDU_INORDER_EN | - ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL | - ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS | - ISCSI_EXP_STATSN | ISCSI_PERSISTENT_PORT | - ISCSI_PERSISTENT_ADDRESS | - ISCSI_TARGET_NAME | ISCSI_TPGT | - ISCSI_USERNAME | ISCSI_PASSWORD | - ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN | - ISCSI_FAST_ABORT | ISCSI_ABORT_TMO | - ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO | - ISCSI_PING_TMO | ISCSI_RECV_TMO | - ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME, - .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | - ISCSI_HOST_INITIATOR_NAME | - ISCSI_HOST_NETDEV_NAME, + .attr_is_visible = cxgbi_attr_is_visible, .get_host_param = cxgbi_get_host_param, .set_host_param = cxgbi_set_host_param, /* session management */ @@ -913,7 +894,7 @@ static void l2t_put(struct cxgbi_sock *csk) struct t3cdev *t3dev = (struct t3cdev *)csk->cdev->lldev; if (csk->l2t) { - l2t_release(L2DATA(t3dev), csk->l2t); + l2t_release(t3dev, csk->l2t); csk->l2t = NULL; cxgbi_sock_put(csk); } @@ -985,7 +966,8 @@ static int init_act_open(struct cxgbi_sock *csk) csk->saddr.sin_addr.s_addr = chba->ipv4addr; csk->rss_qid = 0; - csk->l2t = t3_l2t_get(t3dev, dst->neighbour, ndev); + csk->l2t = t3_l2t_get(t3dev, dst, ndev, + &csk->daddr.sin_addr.s_addr); if (!csk->l2t) { pr_err("NO l2t available.\n"); return -EINVAL; @@ -1245,7 +1227,7 @@ static int cxgb3i_ddp_init(struct cxgbi_device *cdev) struct cxgbi_ddp_info *ddp = tdev->ulp_iscsi; struct ulp_iscsi_info uinfo; unsigned int pgsz_factor[4]; - int err; + int i, err; if (ddp) { kref_get(&ddp->refcnt); @@ -1271,6 +1253,8 @@ static int cxgb3i_ddp_init(struct cxgbi_device *cdev) uinfo.tagmask = ddp->idx_mask << PPOD_IDX_SHIFT; cxgbi_ddp_page_size_factor(pgsz_factor); + for (i = 0; i < 4; i++) + uinfo.pgsz_factor[i] = pgsz_factor[i]; uinfo.ulimit = uinfo.llimit + (ddp->nppods << PPOD_SIZE_SHIFT); err = tdev->ctl(tdev, ULP_ISCSI_SET_PARAMS, &uinfo); diff --git a/drivers/scsi/cxgbi/cxgb4i/Kbuild b/drivers/scsi/cxgbi/cxgb4i/Kbuild index b9f4af7454b..8290cdaa465 100644 --- a/drivers/scsi/cxgbi/cxgb4i/Kbuild +++ b/drivers/scsi/cxgbi/cxgb4i/Kbuild @@ -1,3 +1,3 @@ -EXTRA_CFLAGS += -I$(srctree)/drivers/net/cxgb4 +EXTRA_CFLAGS += -I$(srctree)/drivers/net/ethernet/chelsio/cxgb4 obj-$(CONFIG_SCSI_CXGB4_ISCSI) += cxgb4i.o diff --git a/drivers/scsi/cxgbi/cxgb4i/Kconfig b/drivers/scsi/cxgbi/cxgb4i/Kconfig index d5302c27f37..16b2c7d2661 100644 --- a/drivers/scsi/cxgbi/cxgb4i/Kconfig +++ b/drivers/scsi/cxgbi/cxgb4i/Kconfig @@ -2,7 +2,8 @@ config SCSI_CXGB4_ISCSI tristate "Chelsio T4 iSCSI support" depends on PCI && INET select NETDEVICES - select NETDEV_10000 + select ETHERNET + select NET_VENDOR_CHELSIO select CHELSIO_T4 select SCSI_ISCSI_ATTRS ---help--- diff --git a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c index f3a4cd7cf78..e8ee5e5fe0e 100644 --- a/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c +++ b/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c @@ -13,7 +13,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__ -#include <linux/version.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <scsi/scsi_host.h> @@ -21,6 +20,7 @@ #include <net/dst.h> #include <linux/netdevice.h> +#include "t4_regs.h" #include "t4_msg.h" #include "cxgb4.h" #include "cxgb4_uld.h" @@ -33,13 +33,12 @@ static unsigned int dbg_level; #include "../libcxgbi.h" #define DRV_MODULE_NAME "cxgb4i" -#define DRV_MODULE_DESC "Chelsio T4 iSCSI Driver" -#define DRV_MODULE_VERSION "0.9.1" -#define DRV_MODULE_RELDATE "Aug. 2010" +#define DRV_MODULE_DESC "Chelsio T4/T5 iSCSI Driver" +#define DRV_MODULE_VERSION "0.9.4" static char version[] = DRV_MODULE_DESC " " DRV_MODULE_NAME - " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; + " v" DRV_MODULE_VERSION "\n"; MODULE_AUTHOR("Chelsio Communications, Inc."); MODULE_DESCRIPTION(DRV_MODULE_DESC); @@ -107,25 +106,7 @@ static struct iscsi_transport cxgb4i_iscsi_transport = { .caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST | CAP_DATADGST | CAP_DIGEST_OFFLOAD | CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO, - .param_mask = ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH | - ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN | - ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T | - ISCSI_IMM_DATA_EN | ISCSI_FIRST_BURST | - ISCSI_MAX_BURST | ISCSI_PDU_INORDER_EN | - ISCSI_DATASEQ_INORDER_EN | ISCSI_ERL | - ISCSI_CONN_PORT | ISCSI_CONN_ADDRESS | - ISCSI_EXP_STATSN | ISCSI_PERSISTENT_PORT | - ISCSI_PERSISTENT_ADDRESS | - ISCSI_TARGET_NAME | ISCSI_TPGT | - ISCSI_USERNAME | ISCSI_PASSWORD | - ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN | - ISCSI_FAST_ABORT | ISCSI_ABORT_TMO | - ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO | - ISCSI_PING_TMO | ISCSI_RECV_TMO | - ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME, - .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | - ISCSI_HOST_INITIATOR_NAME | - ISCSI_HOST_NETDEV_NAME, + .attr_is_visible = cxgbi_attr_is_visible, .get_host_param = cxgbi_get_host_param, .set_host_param = cxgbi_set_host_param, /* session management */ @@ -197,7 +178,7 @@ static inline int is_ofld_imm(const struct sk_buff *skb) static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb, struct l2t_entry *e) { - struct cpl_act_open_req *req; + struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(csk->cdev); int wscale = cxgbi_sock_compute_wscale(csk->mss_idx); unsigned long long opt0; unsigned int opt2; @@ -214,29 +195,59 @@ static void send_act_open_req(struct cxgbi_sock *csk, struct sk_buff *skb, RCV_BUFSIZ(cxgb4i_rcv_win >> 10); opt2 = RX_CHANNEL(0) | RSS_QUEUE_VALID | - (1 << 20) | (1 << 22) | + (1 << 20) | RSS_QUEUE(csk->rss_qid); - set_wr_txq(skb, CPL_PRIORITY_SETUP, csk->port_id); - req = (struct cpl_act_open_req *)skb->head; + if (is_t4(lldi->adapter_type)) { + struct cpl_act_open_req *req = + (struct cpl_act_open_req *)skb->head; - INIT_TP_WR(req, 0); - OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, + INIT_TP_WR(req, 0); + OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, qid_atid)); - req->local_port = csk->saddr.sin_port; - req->peer_port = csk->daddr.sin_port; - req->local_ip = csk->saddr.sin_addr.s_addr; - req->peer_ip = csk->daddr.sin_addr.s_addr; - req->opt0 = cpu_to_be64(opt0); - req->params = 0; - req->opt2 = cpu_to_be32(opt2); + req->local_port = csk->saddr.sin_port; + req->peer_port = csk->daddr.sin_port; + req->local_ip = csk->saddr.sin_addr.s_addr; + req->peer_ip = csk->daddr.sin_addr.s_addr; + req->opt0 = cpu_to_be64(opt0); + req->params = cpu_to_be32(cxgb4_select_ntuple( + csk->cdev->ports[csk->port_id], + csk->l2t)); + opt2 |= 1 << 22; + req->opt2 = cpu_to_be32(opt2); - log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, - "csk 0x%p, %pI4:%u-%pI4:%u, atid %d, qid %u.\n", - csk, &req->local_ip, ntohs(req->local_port), - &req->peer_ip, ntohs(req->peer_port), - csk->atid, csk->rss_qid); + log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, + "csk t4 0x%p, %pI4:%u-%pI4:%u, atid %d, qid %u.\n", + csk, &req->local_ip, ntohs(req->local_port), + &req->peer_ip, ntohs(req->peer_port), + csk->atid, csk->rss_qid); + } else { + struct cpl_t5_act_open_req *req = + (struct cpl_t5_act_open_req *)skb->head; + + INIT_TP_WR(req, 0); + OPCODE_TID(req) = cpu_to_be32(MK_OPCODE_TID(CPL_ACT_OPEN_REQ, + qid_atid)); + req->local_port = csk->saddr.sin_port; + req->peer_port = csk->daddr.sin_port; + req->local_ip = csk->saddr.sin_addr.s_addr; + req->peer_ip = csk->daddr.sin_addr.s_addr; + req->opt0 = cpu_to_be64(opt0); + req->params = cpu_to_be64(V_FILTER_TUPLE( + cxgb4_select_ntuple( + csk->cdev->ports[csk->port_id], + csk->l2t))); + opt2 |= 1 << 31; + req->opt2 = cpu_to_be32(opt2); + + log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, + "csk t5 0x%p, %pI4:%u-%pI4:%u, atid %d, qid %u.\n", + csk, &req->local_ip, ntohs(req->local_port), + &req->peer_ip, ntohs(req->peer_port), + csk->atid, csk->rss_qid); + } + set_wr_txq(skb, CPL_PRIORITY_SETUP, csk->port_id); cxgb4_l2t_send(csk->cdev->ports[csk->port_id], skb, csk->l2t); } @@ -377,7 +388,7 @@ static inline unsigned int calc_tx_flits_ofld(const struct sk_buff *skb) return DIV_ROUND_UP(skb->len, 8); flits = skb_transport_offset(skb) / 8; cnt = skb_shinfo(skb)->nr_frags; - if (skb->tail != skb->transport_header) + if (skb_tail_pointer(skb) != skb_transport_header(skb)) cnt++; return flits + sgl_len(cnt); } @@ -457,8 +468,8 @@ static inline void make_tx_data_wr(struct cxgbi_sock *csk, struct sk_buff *skb, if (submode) wr_ulp_mode = FW_OFLD_TX_DATA_WR_ULPMODE(ULP2_MODE_ISCSI) | FW_OFLD_TX_DATA_WR_ULPSUBMODE(submode); - req->tunnel_to_proxy = htonl(wr_ulp_mode) | - FW_OFLD_TX_DATA_WR_SHOVE(skb_peek(&csk->write_queue) ? 0 : 1); + req->tunnel_to_proxy = htonl(wr_ulp_mode | + FW_OFLD_TX_DATA_WR_SHOVE(skb_peek(&csk->write_queue) ? 0 : 1)); req->plen = htonl(len); if (!cxgbi_sock_flag(csk, CTPF_TX_DATA_SENT)) cxgbi_sock_set_flag(csk, CTPF_TX_DATA_SENT); @@ -651,6 +662,7 @@ static void csk_act_open_retry_timer(unsigned long data) { struct sk_buff *skb; struct cxgbi_sock *csk = (struct cxgbi_sock *)data; + struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(csk->cdev); log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, "csk 0x%p,%u,0x%lx,%u.\n", @@ -658,7 +670,10 @@ static void csk_act_open_retry_timer(unsigned long data) cxgbi_sock_get(csk); spin_lock_bh(&csk->lock); - skb = alloc_wr(sizeof(struct cpl_act_open_req), 0, GFP_ATOMIC); + skb = alloc_wr(is_t4(lldi->adapter_type) ? + sizeof(struct cpl_act_open_req) : + sizeof(struct cpl_t5_act_open_req), + 0, GFP_ATOMIC); if (!skb) cxgbi_sock_fail_act_open(csk, -ENOMEM); else { @@ -890,7 +905,7 @@ static void do_rx_iscsi_hdr(struct cxgbi_device *cdev, struct sk_buff *skb) if (!csk->skb_ulp_lhdr) { unsigned char *bhs; - unsigned int hlen, dlen; + unsigned int hlen, dlen, plen; log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_PDU_RX, "csk 0x%p,%u,0x%lx, tid %u, skb 0x%p header.\n", @@ -909,11 +924,15 @@ static void do_rx_iscsi_hdr(struct cxgbi_device *cdev, struct sk_buff *skb) hlen = ntohs(cpl->len); dlen = ntohl(*(unsigned int *)(bhs + 4)) & 0xFFFFFF; - if ((hlen + dlen) != ISCSI_PDU_LEN(pdu_len_ddp) - 40) { + plen = ISCSI_PDU_LEN(pdu_len_ddp); + if (is_t4(lldi->adapter_type)) + plen -= 40; + + if ((hlen + dlen) != plen) { pr_info("tid 0x%x, CPL_ISCSI_HDR, pdu len " "mismatch %u != %u + %u, seq 0x%x.\n", - csk->tid, ISCSI_PDU_LEN(pdu_len_ddp) - 40, - hlen, dlen, cxgbi_skcb_tcp_seq(skb)); + csk->tid, plen, hlen, dlen, + cxgbi_skcb_tcp_seq(skb)); goto abort_conn; } @@ -1146,6 +1165,7 @@ static int init_act_open(struct cxgbi_sock *csk) struct net_device *ndev = cdev->ports[csk->port_id]; struct port_info *pi = netdev_priv(ndev); struct sk_buff *skb = NULL; + struct neighbour *n; unsigned int step; log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK, @@ -1160,14 +1180,22 @@ static int init_act_open(struct cxgbi_sock *csk) cxgbi_sock_set_flag(csk, CTPF_HAS_ATID); cxgbi_sock_get(csk); - csk->l2t = cxgb4_l2t_get(lldi->l2t, csk->dst->neighbour, ndev, 0); + n = dst_neigh_lookup(csk->dst, &csk->daddr.sin_addr.s_addr); + if (!n) { + pr_err("%s, can't get neighbour of csk->dst.\n", ndev->name); + goto rel_resource; + } + csk->l2t = cxgb4_l2t_get(lldi->l2t, n, ndev, 0); if (!csk->l2t) { pr_err("%s, cannot alloc l2t.\n", ndev->name); goto rel_resource; } cxgbi_sock_get(csk); - skb = alloc_wr(sizeof(struct cpl_act_open_req), 0, GFP_KERNEL); + skb = alloc_wr(is_t4(lldi->adapter_type) ? + sizeof(struct cpl_act_open_req) : + sizeof(struct cpl_t5_act_open_req), + 0, GFP_ATOMIC); if (!skb) goto rel_resource; skb->sk = (struct sock *)csk; @@ -1195,14 +1223,19 @@ static int init_act_open(struct cxgbi_sock *csk) cxgbi_sock_set_state(csk, CTP_ACTIVE_OPEN); send_act_open_req(csk, skb, csk->l2t); + neigh_release(n); return 0; rel_resource: + if (n) + neigh_release(n); if (skb) __kfree_skb(skb); return -EINVAL; } +#define CPL_ISCSI_DATA 0xB2 +#define CPL_RX_ISCSI_DDP 0x49 cxgb4i_cplhandler_func cxgb4i_cplhandlers[NUM_CPL_CMDS] = { [CPL_ACT_ESTABLISH] = do_act_establish, [CPL_ACT_OPEN_RPL] = do_act_open_rpl, @@ -1212,8 +1245,10 @@ cxgb4i_cplhandler_func cxgb4i_cplhandlers[NUM_CPL_CMDS] = { [CPL_CLOSE_CON_RPL] = do_close_con_rpl, [CPL_FW4_ACK] = do_fw4_ack, [CPL_ISCSI_HDR] = do_rx_iscsi_hdr, + [CPL_ISCSI_DATA] = do_rx_iscsi_hdr, [CPL_SET_TCB_RPL] = do_set_tcb_rpl, [CPL_RX_DATA_DDP] = do_rx_data_ddp, + [CPL_RX_ISCSI_DDP] = do_rx_data_ddp, }; int cxgb4i_ofld_init(struct cxgbi_device *cdev) @@ -1244,14 +1279,20 @@ int cxgb4i_ofld_init(struct cxgbi_device *cdev) * functions to program the pagepod in h/w */ #define ULPMEM_IDATA_MAX_NPPODS 4 /* 256/PPOD_SIZE */ -static inline void ulp_mem_io_set_hdr(struct ulp_mem_io *req, +static inline void ulp_mem_io_set_hdr(struct cxgb4_lld_info *lldi, + struct ulp_mem_io *req, unsigned int wr_len, unsigned int dlen, unsigned int pm_addr) { struct ulptx_idata *idata = (struct ulptx_idata *)(req + 1); INIT_ULPTX_WR(req, wr_len, 0, 0); - req->cmd = htonl(ULPTX_CMD(ULP_TX_MEM_WRITE) | (1 << 23)); + if (is_t4(lldi->adapter_type)) + req->cmd = htonl(ULPTX_CMD(ULP_TX_MEM_WRITE) | + (ULP_MEMIO_ORDER(1))); + else + req->cmd = htonl(ULPTX_CMD(ULP_TX_MEM_WRITE) | + (V_T5_ULP_MEMIO_IMM(1))); req->dlen = htonl(ULP_MEMIO_DATA_LEN(dlen >> 5)); req->lock_addr = htonl(ULP_MEMIO_ADDR(pm_addr >> 5)); req->len16 = htonl(DIV_ROUND_UP(wr_len - sizeof(req->wr), 16)); @@ -1267,6 +1308,7 @@ static int ddp_ppod_write_idata(struct cxgbi_device *cdev, unsigned int port_id, unsigned int gl_pidx) { struct cxgbi_ddp_info *ddp = cdev->ddp; + struct cxgb4_lld_info *lldi = cxgbi_cdev_priv(cdev); struct sk_buff *skb; struct ulp_mem_io *req; struct ulptx_idata *idata; @@ -1286,7 +1328,7 @@ static int ddp_ppod_write_idata(struct cxgbi_device *cdev, unsigned int port_id, req = (struct ulp_mem_io *)skb->head; set_queue(skb, CPL_PRIORITY_CONTROL, NULL); - ulp_mem_io_set_hdr(req, wr_len, dlen, pm_addr); + ulp_mem_io_set_hdr(lldi, req, wr_len, dlen, pm_addr); idata = (struct ulptx_idata *)(req + 1); ppod = (struct cxgbi_pagepod *)(idata + 1); @@ -1574,6 +1616,7 @@ static int t4_uld_state_change(void *handle, enum cxgb4_state state) break; case CXGB4_STATE_DETACH: pr_info("cdev 0x%p, DETACH.\n", cdev); + cxgbi_device_unregister(cdev); break; default: pr_info("cdev 0x%p, unknown state %d.\n", cdev, state); diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index a2a9c7c6c64..b44c1cff311 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -25,6 +25,7 @@ #include <net/dst.h> #include <net/route.h> #include <linux/inetdevice.h> /* ip_dev_find */ +#include <linux/module.h> #include <net/tcp.h> static unsigned int dbg_level; @@ -471,6 +472,7 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr) struct net_device *ndev; struct cxgbi_device *cdev; struct rtable *rt = NULL; + struct neighbour *n; struct flowi4 fl4; struct cxgbi_sock *csk = NULL; unsigned int mtu = 0; @@ -492,21 +494,26 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr) goto err_out; } dst = &rt->dst; - ndev = dst->neighbour->dev; + n = dst_neigh_lookup(dst, &daddr->sin_addr.s_addr); + if (!n) { + err = -ENODEV; + goto rel_rt; + } + ndev = n->dev; if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) { pr_info("multi-cast route %pI4, port %u, dev %s.\n", &daddr->sin_addr.s_addr, ntohs(daddr->sin_port), ndev->name); err = -ENETUNREACH; - goto rel_rt; + goto rel_neigh; } if (ndev->flags & IFF_LOOPBACK) { ndev = ip_dev_find(&init_net, daddr->sin_addr.s_addr); mtu = ndev->mtu; pr_info("rt dev %s, loopback -> %s, mtu %u.\n", - dst->neighbour->dev->name, ndev->name, mtu); + n->dev->name, ndev->name, mtu); } cdev = cxgbi_device_find_by_netdev(ndev, &port); @@ -514,7 +521,7 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr) pr_info("dst %pI4, %s, NOT cxgbi device.\n", &daddr->sin_addr.s_addr, ndev->name); err = -ENETUNREACH; - goto rel_rt; + goto rel_neigh; } log_debug(1 << CXGBI_DBG_SOCK, "route to %pI4 :%u, ndev p#%d,%s, cdev 0x%p.\n", @@ -524,7 +531,7 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr) csk = cxgbi_sock_create(cdev); if (!csk) { err = -ENOMEM; - goto rel_rt; + goto rel_neigh; } csk->cdev = cdev; csk->port_id = port; @@ -534,9 +541,13 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr) csk->daddr.sin_port = daddr->sin_port; csk->daddr.sin_family = daddr->sin_family; csk->saddr.sin_addr.s_addr = fl4.saddr; + neigh_release(n); return csk; +rel_neigh: + neigh_release(n); + rel_rt: ip_rt_put(rt); if (csk) @@ -1787,7 +1798,7 @@ static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt, } static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset, - unsigned int dlen, skb_frag_t *frags, + unsigned int dlen, struct page_frag *frags, int frag_max) { unsigned int datalen = dlen; @@ -1814,7 +1825,7 @@ static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset, copy = min(datalen, sglen); if (i && page == frags[i - 1].page && sgoffset + sg->offset == - frags[i - 1].page_offset + frags[i - 1].size) { + frags[i - 1].offset + frags[i - 1].size) { frags[i - 1].size += copy; } else { if (i >= frag_max) { @@ -1824,7 +1835,7 @@ static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset, } frags[i].page = page; - frags[i].page_offset = sg->offset + sgoffset; + frags[i].offset = sg->offset + sgoffset; frags[i].size = copy; i++; } @@ -1861,8 +1872,9 @@ int cxgbi_conn_alloc_pdu(struct iscsi_task *task, u8 opcode) tdata->skb = alloc_skb(cdev->skb_tx_rsvd + headroom, GFP_ATOMIC); if (!tdata->skb) { - pr_warn("alloc skb %u+%u, opcode 0x%x failed.\n", - cdev->skb_tx_rsvd, headroom, opcode); + struct cxgbi_sock *csk = cconn->cep->csk; + struct net_device *ndev = cdev->ports[csk->port_id]; + ndev->stats.tx_dropped++; return -ENOMEM; } @@ -1944,16 +1956,15 @@ int cxgbi_conn_init_pdu(struct iscsi_task *task, unsigned int offset, if (tdata->nr_frags > MAX_SKB_FRAGS || (padlen && tdata->nr_frags == MAX_SKB_FRAGS)) { char *dst = skb->data + task->hdr_len; - skb_frag_t *frag = tdata->frags; + struct page_frag *frag = tdata->frags; /* data fits in the skb's headroom */ for (i = 0; i < tdata->nr_frags; i++, frag++) { - char *src = kmap_atomic(frag->page, - KM_SOFTIRQ0); + char *src = kmap_atomic(frag->page); - memcpy(dst, src+frag->page_offset, frag->size); + memcpy(dst, src+frag->offset, frag->size); dst += frag->size; - kunmap_atomic(src, KM_SOFTIRQ0); + kunmap_atomic(src); } if (padlen) { memset(dst, 0, padlen); @@ -1962,11 +1973,13 @@ int cxgbi_conn_init_pdu(struct iscsi_task *task, unsigned int offset, skb_put(skb, count + padlen); } else { /* data fit into frag_list */ - for (i = 0; i < tdata->nr_frags; i++) - get_page(tdata->frags[i].page); - - memcpy(skb_shinfo(skb)->frags, tdata->frags, - sizeof(skb_frag_t) * tdata->nr_frags); + for (i = 0; i < tdata->nr_frags; i++) { + __skb_fill_page_desc(skb, i, + tdata->frags[i].page, + tdata->frags[i].offset, + tdata->frags[i].size); + skb_frag_ref(skb, i); + } skb_shinfo(skb)->nr_frags = tdata->nr_frags; skb->len += count; skb->data_len += count; @@ -2138,11 +2151,10 @@ int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn, enum iscsi_param param, char *buf, int buflen) { struct iscsi_conn *conn = cls_conn->dd_data; - struct iscsi_session *session = conn->session; struct iscsi_tcp_conn *tcp_conn = conn->dd_data; struct cxgbi_conn *cconn = tcp_conn->dd_data; struct cxgbi_sock *csk = cconn->cep->csk; - int value, err = 0; + int err; log_debug(1 << CXGBI_DBG_ISCSI, "cls_conn 0x%p, param %d, buf(%d) %s.\n", @@ -2164,15 +2176,7 @@ int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn, conn->datadgst_en, 0); break; case ISCSI_PARAM_MAX_R2T: - sscanf(buf, "%d", &value); - if (value <= 0 || !is_power_of_2(value)) - return -EINVAL; - if (session->max_r2t == value) - break; - iscsi_tcp_r2tpool_free(session); - err = iscsi_set_param(cls_conn, param, buf, buflen); - if (!err && iscsi_tcp_r2tpool_alloc(session)) - return -ENOMEM; + return iscsi_tcp_set_max_r2t(conn, buf); case ISCSI_PARAM_MAX_RECV_DLENGTH: err = iscsi_set_param(cls_conn, param, buf, buflen); if (!err) @@ -2566,6 +2570,62 @@ void cxgbi_iscsi_cleanup(struct iscsi_transport *itp, } EXPORT_SYMBOL_GPL(cxgbi_iscsi_cleanup); +umode_t cxgbi_attr_is_visible(int param_type, int param) +{ + switch (param_type) { + case ISCSI_HOST_PARAM: + switch (param) { + case ISCSI_HOST_PARAM_NETDEV_NAME: + case ISCSI_HOST_PARAM_HWADDRESS: + case ISCSI_HOST_PARAM_IPADDRESS: + case ISCSI_HOST_PARAM_INITIATOR_NAME: + return S_IRUGO; + default: + return 0; + } + case ISCSI_PARAM: + switch (param) { + case ISCSI_PARAM_MAX_RECV_DLENGTH: + case ISCSI_PARAM_MAX_XMIT_DLENGTH: + case ISCSI_PARAM_HDRDGST_EN: + case ISCSI_PARAM_DATADGST_EN: + case ISCSI_PARAM_CONN_ADDRESS: + case ISCSI_PARAM_CONN_PORT: + case ISCSI_PARAM_EXP_STATSN: + case ISCSI_PARAM_PERSISTENT_ADDRESS: + case ISCSI_PARAM_PERSISTENT_PORT: + case ISCSI_PARAM_PING_TMO: + case ISCSI_PARAM_RECV_TMO: + case ISCSI_PARAM_INITIAL_R2T_EN: + case ISCSI_PARAM_MAX_R2T: + case ISCSI_PARAM_IMM_DATA_EN: + case ISCSI_PARAM_FIRST_BURST: + case ISCSI_PARAM_MAX_BURST: + case ISCSI_PARAM_PDU_INORDER_EN: + case ISCSI_PARAM_DATASEQ_INORDER_EN: + case ISCSI_PARAM_ERL: + case ISCSI_PARAM_TARGET_NAME: + case ISCSI_PARAM_TPGT: + case ISCSI_PARAM_USERNAME: + case ISCSI_PARAM_PASSWORD: + case ISCSI_PARAM_USERNAME_IN: + case ISCSI_PARAM_PASSWORD_IN: + case ISCSI_PARAM_FAST_ABORT: + case ISCSI_PARAM_ABORT_TMO: + case ISCSI_PARAM_LU_RESET_TMO: + case ISCSI_PARAM_TGT_RESET_TMO: + case ISCSI_PARAM_IFACE_NAME: + case ISCSI_PARAM_INITIATOR_NAME: + return S_IRUGO; + default: + return 0; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(cxgbi_attr_is_visible); + static int __init libcxgbi_init_module(void) { sw_tag_idx_bits = (__ilog2_u32(ISCSI_ITT_MASK)) + 1; diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h index 9267844519c..8135f04671a 100644 --- a/drivers/scsi/cxgbi/libcxgbi.h +++ b/drivers/scsi/cxgbi/libcxgbi.h @@ -574,7 +574,7 @@ struct cxgbi_endpoint { #define MAX_PDU_FRAGS ((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512) struct cxgbi_task_data { unsigned short nr_frags; - skb_frag_t frags[MAX_PDU_FRAGS]; + struct page_frag frags[MAX_PDU_FRAGS]; struct sk_buff *skb; unsigned int offset; unsigned int count; @@ -658,11 +658,11 @@ static inline u32 cxgbi_tag_nonrsvd_bits(struct cxgbi_tag_format *tformat, static inline void *cxgbi_alloc_big_mem(unsigned int size, gfp_t gfp) { - void *p = kmalloc(size, gfp); + void *p = kzalloc(size, gfp | __GFP_NOWARN); + if (!p) - p = vmalloc(size); - if (p) - memset(p, 0, size); + p = vzalloc(size); + return p; } @@ -709,6 +709,7 @@ int cxgbi_conn_xmit_pdu(struct iscsi_task *); void cxgbi_cleanup_task(struct iscsi_task *task); +umode_t cxgbi_attr_is_visible(int param_type, int param); void cxgbi_get_conn_stats(struct iscsi_cls_conn *, struct iscsi_stats *); int cxgbi_set_conn_param(struct iscsi_cls_conn *, enum iscsi_param, char *, int); |
