1/* cxgb3i_iscsi.c: Chelsio S3xx iSCSI driver. 2 * 3 * Copyright (c) 2008 Chelsio Communications, Inc. 4 * Copyright (c) 2008 Mike Christie 5 * Copyright (c) 2008 Red Hat, Inc. All rights reserved. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation. 10 * 11 * Written by: Karen Xie (kxie@chelsio.com) 12 */ 13 14#include <linux/inet.h> 15#include <linux/slab.h> 16#include <linux/crypto.h> 17#include <linux/if_vlan.h> 18#include <net/dst.h> 19#include <net/tcp.h> 20#include <scsi/scsi_cmnd.h> 21#include <scsi/scsi_device.h> 22#include <scsi/scsi_eh.h> 23#include <scsi/scsi_host.h> 24#include <scsi/scsi.h> 25#include <scsi/iscsi_proto.h> 26#include <scsi/libiscsi.h> 27#include <scsi/scsi_transport_iscsi.h> 28 29#include "cxgb3i.h" 30#include "cxgb3i_pdu.h" 31 32#ifdef __DEBUG_CXGB3I_TAG__ 33#define cxgb3i_tag_debug cxgb3i_log_debug 34#else 35#define cxgb3i_tag_debug(fmt...) 36#endif 37 38#ifdef __DEBUG_CXGB3I_API__ 39#define cxgb3i_api_debug cxgb3i_log_debug 40#else 41#define cxgb3i_api_debug(fmt...) 42#endif 43 44/* 45 * align pdu size to multiple of 512 for better performance 46 */ 47#define align_pdu_size(n) do { n = (n) & (~511); } while (0) 48 49static struct scsi_transport_template *cxgb3i_scsi_transport; 50static struct scsi_host_template cxgb3i_host_template; 51static struct iscsi_transport cxgb3i_iscsi_transport; 52static unsigned char sw_tag_idx_bits; 53static unsigned char sw_tag_age_bits; 54 55static LIST_HEAD(cxgb3i_snic_list); 56static DEFINE_RWLOCK(cxgb3i_snic_rwlock); 57 58/** 59 * cxgb3i_adpater_find_by_tdev - find the cxgb3i_adapter structure via t3cdev 60 * @tdev: t3cdev pointer 61 */ 62struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *tdev) 63{ 64 struct cxgb3i_adapter *snic; 65 66 read_lock(&cxgb3i_snic_rwlock); 67 list_for_each_entry(snic, &cxgb3i_snic_list, list_head) { 68 if (snic->tdev == tdev) { 69 read_unlock(&cxgb3i_snic_rwlock); 70 return snic; 71 } 72 } 73 read_unlock(&cxgb3i_snic_rwlock); 74 return NULL; 75} 76 77static inline int adapter_update(struct cxgb3i_adapter *snic) 78{ 79 cxgb3i_log_info("snic 0x%p, t3dev 0x%p, updating.\n", 80 snic, snic->tdev); 81 return cxgb3i_adapter_ddp_info(snic->tdev, &snic->tag_format, 82 &snic->tx_max_size, 83 &snic->rx_max_size); 84} 85 86static int adapter_add(struct cxgb3i_adapter *snic) 87{ 88 struct t3cdev *t3dev = snic->tdev; 89 struct adapter *adapter = tdev2adap(t3dev); 90 int i, err; 91 92 snic->pdev = adapter->pdev; 93 snic->tag_format.sw_bits = sw_tag_idx_bits + sw_tag_age_bits; 94 95 err = cxgb3i_adapter_ddp_info(t3dev, &snic->tag_format, 96 &snic->tx_max_size, 97 &snic->rx_max_size); 98 if (err < 0) 99 return err; 100 101 for_each_port(adapter, i) { 102 snic->hba[i] = cxgb3i_hba_host_add(snic, adapter->port[i]); 103 if (!snic->hba[i]) 104 return -EINVAL; 105 } 106 snic->hba_cnt = adapter->params.nports; 107 108 /* add to the list */ 109 write_lock(&cxgb3i_snic_rwlock); 110 list_add_tail(&snic->list_head, &cxgb3i_snic_list); 111 write_unlock(&cxgb3i_snic_rwlock); 112 113 cxgb3i_log_info("t3dev 0x%p open, snic 0x%p, %u scsi hosts added.\n", 114 t3dev, snic, snic->hba_cnt); 115 return 0; 116} 117 118/** 119 * cxgb3i_adapter_open - init a s3 adapter structure and any h/w settings 120 * @t3dev: t3cdev adapter 121 */ 122void cxgb3i_adapter_open(struct t3cdev *t3dev) 123{ 124 struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev); 125 int err; 126 127 if (snic) 128 err = adapter_update(snic); 129 else { 130 snic = kzalloc(sizeof(*snic), GFP_KERNEL); 131 if (snic) { 132 spin_lock_init(&snic->lock); 133 snic->tdev = t3dev; 134 err = adapter_add(snic); 135 } else 136 err = -ENOMEM; 137 } 138 139 if (err < 0) { 140 cxgb3i_log_info("snic 0x%p, f 0x%x, t3dev 0x%p open, err %d.\n", 141 snic, snic ? snic->flags : 0, t3dev, err); 142 if (snic) { 143 snic->flags &= ~CXGB3I_ADAPTER_FLAG_RESET; 144 cxgb3i_adapter_close(t3dev); 145 } 146 } 147} 148 149/** 150 * cxgb3i_adapter_close - release the resources held and cleanup h/w settings 151 * @t3dev: t3cdev adapter 152 */ 153void cxgb3i_adapter_close(struct t3cdev *t3dev) 154{ 155 struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev); 156 int i; 157 158 if (!snic || snic->flags & CXGB3I_ADAPTER_FLAG_RESET) { 159 cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, f 0x%x.\n", 160 t3dev, snic, snic ? snic->flags : 0); 161 return; 162 } 163 164 /* remove from the list */ 165 write_lock(&cxgb3i_snic_rwlock); 166 list_del(&snic->list_head); 167 write_unlock(&cxgb3i_snic_rwlock); 168 169 for (i = 0; i < snic->hba_cnt; i++) { 170 if (snic->hba[i]) { 171 cxgb3i_hba_host_remove(snic->hba[i]); 172 snic->hba[i] = NULL; 173 } 174 } 175 cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, %u scsi hosts removed.\n", 176 t3dev, snic, snic->hba_cnt); 177 kfree(snic); 178} 179 180/** 181 * cxgb3i_hba_find_by_netdev - find the cxgb3i_hba structure via net_device 182 * @t3dev: t3cdev adapter 183 */ 184static struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev) 185{ 186 struct cxgb3i_adapter *snic; 187 int i; 188 189 if (ndev->priv_flags & IFF_802_1Q_VLAN) 190 ndev = vlan_dev_real_dev(ndev); 191 192 read_lock(&cxgb3i_snic_rwlock); 193 list_for_each_entry(snic, &cxgb3i_snic_list, list_head) { 194 for (i = 0; i < snic->hba_cnt; i++) { 195 if (snic->hba[i]->ndev == ndev) { 196 read_unlock(&cxgb3i_snic_rwlock); 197 return snic->hba[i]; 198 } 199 } 200 } 201 read_unlock(&cxgb3i_snic_rwlock); 202 return NULL; 203} 204 205/** 206 * cxgb3i_hba_host_add - register a new host with scsi/iscsi 207 * @snic: the cxgb3i adapter 208 * @ndev: associated net_device 209 */ 210struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic, 211 struct net_device *ndev) 212{ 213 struct cxgb3i_hba *hba; 214 struct Scsi_Host *shost; 215 int err; 216 217 shost = iscsi_host_alloc(&cxgb3i_host_template, 218 sizeof(struct cxgb3i_hba), 1); 219 if (!shost) { 220 cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_alloc failed.\n", 221 snic, ndev); 222 return NULL; 223 } 224 225 shost->transportt = cxgb3i_scsi_transport; 226 shost->max_lun = CXGB3I_MAX_LUN; 227 shost->max_id = CXGB3I_MAX_TARGET; 228 shost->max_channel = 0; 229 shost->max_cmd_len = 16; 230 231 hba = iscsi_host_priv(shost); 232 hba->snic = snic; 233 hba->ndev = ndev; 234 hba->shost = shost; 235 236 pci_dev_get(snic->pdev); 237 err = iscsi_host_add(shost, &snic->pdev->dev); 238 if (err) { 239 cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_add failed.\n", 240 snic, ndev); 241 goto pci_dev_put; 242 } 243 244 cxgb3i_api_debug("shost 0x%p, hba 0x%p, no %u.\n", 245 shost, hba, shost->host_no); 246 247 return hba; 248 249pci_dev_put: 250 pci_dev_put(snic->pdev); 251 scsi_host_put(shost); 252 return NULL; 253} 254 255/** 256 * cxgb3i_hba_host_remove - de-register the host with scsi/iscsi 257 * @hba: the cxgb3i hba 258 */ 259void cxgb3i_hba_host_remove(struct cxgb3i_hba *hba) 260{ 261 cxgb3i_api_debug("shost 0x%p, hba 0x%p, no %u.\n", 262 hba->shost, hba, hba->shost->host_no); 263 iscsi_host_remove(hba->shost); 264 pci_dev_put(hba->snic->pdev); 265 iscsi_host_free(hba->shost); 266} 267 268/** 269 * cxgb3i_ep_connect - establish TCP connection to target portal 270 * @shost: scsi host to use 271 * @dst_addr: target IP address 272 * @non_blocking: blocking or non-blocking call 273 * 274 * Initiates a TCP/IP connection to the dst_addr 275 */ 276static struct iscsi_endpoint *cxgb3i_ep_connect(struct Scsi_Host *shost, 277 struct sockaddr *dst_addr, 278 int non_blocking) 279{ 280 struct iscsi_endpoint *ep; 281 struct cxgb3i_endpoint *cep; 282 struct cxgb3i_hba *hba = NULL; 283 struct s3_conn *c3cn = NULL; 284 int err = 0; 285 286 if (shost) 287 hba = iscsi_host_priv(shost); 288 289 cxgb3i_api_debug("shost 0x%p, hba 0x%p.\n", shost, hba); 290 291 c3cn = cxgb3i_c3cn_create(); 292 if (!c3cn) { 293 cxgb3i_log_info("ep connect OOM.\n"); 294 err = -ENOMEM; 295 goto release_conn; 296 } 297 298 err = cxgb3i_c3cn_connect(hba ? hba->ndev : NULL, c3cn, 299 (struct sockaddr_in *)dst_addr); 300 if (err < 0) { 301 cxgb3i_log_info("ep connect failed.\n"); 302 goto release_conn; 303 } 304 305 hba = cxgb3i_hba_find_by_netdev(c3cn->dst_cache->dev); 306 if (!hba) { 307 err = -ENOSPC; 308 cxgb3i_log_info("NOT going through cxgbi device.\n"); 309 goto release_conn; 310 } 311 312 if (shost && hba != iscsi_host_priv(shost)) { 313 err = -ENOSPC; 314 cxgb3i_log_info("Could not connect through request host%u\n", 315 shost->host_no); 316 goto release_conn; 317 } 318 319 if (c3cn_is_closing(c3cn)) { 320 err = -ENOSPC; 321 cxgb3i_log_info("ep connect unable to connect.\n"); 322 goto release_conn; 323 } 324 325 ep = iscsi_create_endpoint(sizeof(*cep)); 326 if (!ep) { 327 err = -ENOMEM; 328 cxgb3i_log_info("iscsi alloc ep, OOM.\n"); 329 goto release_conn; 330 } 331 cep = ep->dd_data; 332 cep->c3cn = c3cn; 333 cep->hba = hba; 334 335 cxgb3i_api_debug("ep 0x%p, 0x%p, c3cn 0x%p, hba 0x%p.\n", 336 ep, cep, c3cn, hba); 337 return ep; 338 339release_conn: 340 cxgb3i_api_debug("conn 0x%p failed, release.\n", c3cn); 341 if (c3cn) 342 cxgb3i_c3cn_release(c3cn); 343 return ERR_PTR(err); 344} 345 346/** 347 * cxgb3i_ep_poll - polls for TCP connection establishement 348 * @ep: TCP connection (endpoint) handle 349 * @timeout_ms: timeout value in milli secs 350 * 351 * polls for TCP connect request to complete 352 */ 353static int cxgb3i_ep_poll(struct iscsi_endpoint *ep, int timeout_ms) 354{ 355 struct cxgb3i_endpoint *cep = ep->dd_data; 356 struct s3_conn *c3cn = cep->c3cn; 357 358 if (!c3cn_is_established(c3cn)) 359 return 0; 360 cxgb3i_api_debug("ep 0x%p, c3cn 0x%p established.\n", ep, c3cn); 361 return 1; 362} 363 364/** 365 * cxgb3i_ep_disconnect - teardown TCP connection 366 * @ep: TCP connection (endpoint) handle 367 * 368 * teardown TCP connection 369 */ 370static void cxgb3i_ep_disconnect(struct iscsi_endpoint *ep) 371{ 372 struct cxgb3i_endpoint *cep = ep->dd_data; 373 struct cxgb3i_conn *cconn = cep->cconn; 374 375 cxgb3i_api_debug("ep 0x%p, cep 0x%p.\n", ep, cep); 376 377 if (cconn && cconn->conn) { 378 /* 379 * stop the xmit path so the xmit_pdu function is 380 * not being called 381 */ 382 iscsi_suspend_tx(cconn->conn); 383 384 write_lock_bh(&cep->c3cn->callback_lock); 385 cep->c3cn->user_data = NULL; 386 cconn->cep = NULL; 387 write_unlock_bh(&cep->c3cn->callback_lock); 388 } 389 390 cxgb3i_api_debug("ep 0x%p, cep 0x%p, release c3cn 0x%p.\n", 391 ep, cep, cep->c3cn); 392 cxgb3i_c3cn_release(cep->c3cn); 393 iscsi_destroy_endpoint(ep); 394} 395 396/** 397 * cxgb3i_session_create - create a new iscsi session 398 * @cmds_max: max # of commands 399 * @qdepth: scsi queue depth 400 * @initial_cmdsn: initial iscsi CMDSN for this session 401 * 402 * Creates a new iSCSI session 403 */ 404static struct iscsi_cls_session * 405cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth, 406 u32 initial_cmdsn) 407{ 408 struct cxgb3i_endpoint *cep; 409 struct cxgb3i_hba *hba; 410 struct Scsi_Host *shost; 411 struct iscsi_cls_session *cls_session; 412 struct iscsi_session *session; 413 414 if (!ep) { 415 cxgb3i_log_error("%s, missing endpoint.\n", __func__); 416 return NULL; 417 } 418 419 cep = ep->dd_data; 420 hba = cep->hba; 421 shost = hba->shost; 422 cxgb3i_api_debug("ep 0x%p, cep 0x%p, hba 0x%p.\n", ep, cep, hba); 423 BUG_ON(hba != iscsi_host_priv(shost)); 424 425 cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost, 426 cmds_max, 0, 427 sizeof(struct iscsi_tcp_task) + 428 sizeof(struct cxgb3i_task_data), 429 initial_cmdsn, ISCSI_MAX_TARGET); 430 if (!cls_session) 431 return NULL; 432 session = cls_session->dd_data; 433 if (iscsi_tcp_r2tpool_alloc(session)) 434 goto remove_session; 435 436 return cls_session; 437 438remove_session: 439 iscsi_session_teardown(cls_session); 440 return NULL; 441} 442 443/** 444 * cxgb3i_session_destroy - destroys iscsi session 445 * @cls_session: pointer to iscsi cls session 446 * 447 * Destroys an iSCSI session instance and releases its all resources held 448 */ 449static void cxgb3i_session_destroy(struct iscsi_cls_session *cls_session) 450{ 451 cxgb3i_api_debug("sess 0x%p.\n", cls_session); 452 iscsi_tcp_r2tpool_free(cls_session->dd_data); 453 iscsi_session_teardown(cls_session); 454} 455 456/** 457 * cxgb3i_conn_max_xmit_dlength -- calc the max. xmit pdu segment size 458 * @conn: iscsi connection 459 * check the max. xmit pdu payload, reduce it if needed 460 */ 461static inline int cxgb3i_conn_max_xmit_dlength(struct iscsi_conn *conn) 462 463{ 464 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 465 struct cxgb3i_conn *cconn = tcp_conn->dd_data; 466 unsigned int max = max(512 * MAX_SKB_FRAGS, SKB_TX_HEADROOM); 467 468 max = min(cconn->hba->snic->tx_max_size, max); 469 if (conn->max_xmit_dlength) 470 conn->max_xmit_dlength = min(conn->max_xmit_dlength, max); 471 else 472 conn->max_xmit_dlength = max; 473 align_pdu_size(conn->max_xmit_dlength); 474 cxgb3i_api_debug("conn 0x%p, max xmit %u.\n", 475 conn, conn->max_xmit_dlength); 476 return 0; 477} 478 479/** 480 * cxgb3i_conn_max_recv_dlength -- check the max. recv pdu segment size 481 * @conn: iscsi connection 482 * return 0 if the value is valid, < 0 otherwise. 483 */ 484static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn *conn) 485{ 486 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 487 struct cxgb3i_conn *cconn = tcp_conn->dd_data; 488 unsigned int max = cconn->hba->snic->rx_max_size; 489 490 align_pdu_size(max); 491 if (conn->max_recv_dlength) { 492 if (conn->max_recv_dlength > max) { 493 cxgb3i_log_error("MaxRecvDataSegmentLength %u too big." 494 " Need to be <= %u.\n", 495 conn->max_recv_dlength, max); 496 return -EINVAL; 497 } 498 conn->max_recv_dlength = min(conn->max_recv_dlength, max); 499 align_pdu_size(conn->max_recv_dlength); 500 } else 501 conn->max_recv_dlength = max; 502 cxgb3i_api_debug("conn 0x%p, max recv %u.\n", 503 conn, conn->max_recv_dlength); 504 return 0; 505} 506 507/** 508 * cxgb3i_conn_create - create iscsi connection instance 509 * @cls_session: pointer to iscsi cls session 510 * @cid: iscsi cid 511 * 512 * Creates a new iSCSI connection instance for a given session 513 */ 514static struct iscsi_cls_conn *cxgb3i_conn_create(struct iscsi_cls_session 515 *cls_session, u32 cid) 516{ 517 struct iscsi_cls_conn *cls_conn; 518 struct iscsi_conn *conn; 519 struct iscsi_tcp_conn *tcp_conn; 520 struct cxgb3i_conn *cconn; 521 522 cxgb3i_api_debug("sess 0x%p, cid %u.\n", cls_session, cid); 523 524 cls_conn = iscsi_tcp_conn_setup(cls_session, sizeof(*cconn), cid); 525 if (!cls_conn) 526 return NULL; 527 conn = cls_conn->dd_data; 528 tcp_conn = conn->dd_data; 529 cconn = tcp_conn->dd_data; 530 531 cconn->conn = conn; 532 return cls_conn; 533} 534 535/** 536 * cxgb3i_conn_bind - binds iscsi sess, conn and endpoint together 537 * @cls_session: pointer to iscsi cls session 538 * @cls_conn: pointer to iscsi cls conn 539 * @transport_eph: 64-bit EP handle 540 * @is_leading: leading connection on this session? 541 * 542 * Binds together an iSCSI session, an iSCSI connection and a 543 * TCP connection. This routine returns error code if the TCP 544 * connection does not belong on the device iSCSI sess/conn is bound 545 */ 546 547static int cxgb3i_conn_bind(struct iscsi_cls_session *cls_session, 548 struct iscsi_cls_conn *cls_conn, 549 u64 transport_eph, int is_leading) 550{ 551 struct iscsi_conn *conn = cls_conn->dd_data; 552 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 553 struct cxgb3i_conn *cconn = tcp_conn->dd_data; 554 struct cxgb3i_adapter *snic; 555 struct iscsi_endpoint *ep; 556 struct cxgb3i_endpoint *cep; 557 struct s3_conn *c3cn; 558 int err; 559 560 ep = iscsi_lookup_endpoint(transport_eph); 561 if (!ep) 562 return -EINVAL; 563 564 /* setup ddp pagesize */ 565 cep = ep->dd_data; 566 c3cn = cep->c3cn; 567 snic = cep->hba->snic; 568 err = cxgb3i_setup_conn_host_pagesize(snic->tdev, c3cn->tid, 0); 569 if (err < 0) 570 return err; 571 572 cxgb3i_api_debug("ep 0x%p, cls sess 0x%p, cls conn 0x%p.\n", 573 ep, cls_session, cls_conn); 574 575 err = iscsi_conn_bind(cls_session, cls_conn, is_leading); 576 if (err) 577 return -EINVAL; 578 579 /* calculate the tag idx bits needed for this conn based on cmds_max */ 580 cconn->task_idx_bits = (__ilog2_u32(conn->session->cmds_max - 1)) + 1; 581 cxgb3i_api_debug("session cmds_max 0x%x, bits %u.\n", 582 conn->session->cmds_max, cconn->task_idx_bits); 583 584 read_lock(&c3cn->callback_lock); 585 c3cn->user_data = conn; 586 cconn->hba = cep->hba; 587 cconn->cep = cep; 588 cep->cconn = cconn; 589 read_unlock(&c3cn->callback_lock); 590 591 cxgb3i_conn_max_xmit_dlength(conn); 592 cxgb3i_conn_max_recv_dlength(conn); 593 594 spin_lock_bh(&conn->session->lock); 595 sprintf(conn->portal_address, "%pI4", &c3cn->daddr.sin_addr.s_addr); 596 conn->portal_port = ntohs(c3cn->daddr.sin_port); 597 spin_unlock_bh(&conn->session->lock); 598 599 /* init recv engine */ 600 iscsi_tcp_hdr_recv_prep(tcp_conn); 601 602 return 0; 603} 604 605/** 606 * cxgb3i_conn_get_param - return iscsi connection parameter to caller 607 * @cls_conn: pointer to iscsi cls conn 608 * @param: parameter type identifier 609 * @buf: buffer pointer 610 * 611 * returns iSCSI connection parameters 612 */ 613static int cxgb3i_conn_get_param(struct iscsi_cls_conn *cls_conn, 614 enum iscsi_param param, char *buf) 615{ 616 struct iscsi_conn *conn = cls_conn->dd_data; 617 int len; 618 619 cxgb3i_api_debug("cls_conn 0x%p, param %d.\n", cls_conn, param); 620 621 switch (param) { 622 case ISCSI_PARAM_CONN_PORT: 623 spin_lock_bh(&conn->session->lock); 624 len = sprintf(buf, "%hu\n", conn->portal_port); 625 spin_unlock_bh(&conn->session->lock); 626 break; 627 case ISCSI_PARAM_CONN_ADDRESS: 628 spin_lock_bh(&conn->session->lock); 629 len = sprintf(buf, "%s\n", conn->portal_address); 630 spin_unlock_bh(&conn->session->lock); 631 break; 632 default: 633 return iscsi_conn_get_param(cls_conn, param, buf); 634 } 635 636 return len; 637} 638 639/** 640 * cxgb3i_conn_set_param - set iscsi connection parameter 641 * @cls_conn: pointer to iscsi cls conn 642 * @param: parameter type identifier 643 * @buf: buffer pointer 644 * @buflen: buffer length 645 * 646 * set iSCSI connection parameters 647 */ 648static int cxgb3i_conn_set_param(struct iscsi_cls_conn *cls_conn, 649 enum iscsi_param param, char *buf, int buflen) 650{ 651 struct iscsi_conn *conn = cls_conn->dd_data; 652 struct iscsi_session *session = conn->session; 653 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 654 struct cxgb3i_conn *cconn = tcp_conn->dd_data; 655 struct cxgb3i_adapter *snic = cconn->hba->snic; 656 struct s3_conn *c3cn = cconn->cep->c3cn; 657 int value, err = 0; 658 659 switch (param) { 660 case ISCSI_PARAM_HDRDGST_EN: 661 err = iscsi_set_param(cls_conn, param, buf, buflen); 662 if (!err && conn->hdrdgst_en) 663 err = cxgb3i_setup_conn_digest(snic->tdev, c3cn->tid, 664 conn->hdrdgst_en, 665 conn->datadgst_en, 0); 666 break; 667 case ISCSI_PARAM_DATADGST_EN: 668 err = iscsi_set_param(cls_conn, param, buf, buflen); 669 if (!err && conn->datadgst_en) 670 err = cxgb3i_setup_conn_digest(snic->tdev, c3cn->tid, 671 conn->hdrdgst_en, 672 conn->datadgst_en, 0); 673 break; 674 case ISCSI_PARAM_MAX_R2T: 675 sscanf(buf, "%d", &value); 676 if (value <= 0 || !is_power_of_2(value)) 677 return -EINVAL; 678 if (session->max_r2t == value) 679 break; 680 iscsi_tcp_r2tpool_free(session); 681 err = iscsi_set_param(cls_conn, param, buf, buflen); 682 if (!err && iscsi_tcp_r2tpool_alloc(session)) 683 return -ENOMEM; 684 case ISCSI_PARAM_MAX_RECV_DLENGTH: 685 err = iscsi_set_param(cls_conn, param, buf, buflen); 686 if (!err) 687 err = cxgb3i_conn_max_recv_dlength(conn); 688 break; 689 case ISCSI_PARAM_MAX_XMIT_DLENGTH: 690 err = iscsi_set_param(cls_conn, param, buf, buflen); 691 if (!err) 692 err = cxgb3i_conn_max_xmit_dlength(conn); 693 break; 694 default: 695 return iscsi_set_param(cls_conn, param, buf, buflen); 696 } 697 return err; 698} 699 700/** 701 * cxgb3i_host_set_param - configure host (adapter) related parameters 702 * @shost: scsi host pointer 703 * @param: parameter type identifier 704 * @buf: buffer pointer 705 */ 706static int cxgb3i_host_set_param(struct Scsi_Host *shost, 707 enum iscsi_host_param param, 708 char *buf, int buflen) 709{ 710 struct cxgb3i_hba *hba = iscsi_host_priv(shost); 711 712 if (!hba->ndev) { 713 shost_printk(KERN_ERR, shost, "Could not set host param. " 714 "Netdev for host not set.\n"); 715 return -ENODEV; 716 } 717 718 cxgb3i_api_debug("param %d, buf %s.\n", param, buf); 719 720 switch (param) { 721 case ISCSI_HOST_PARAM_IPADDRESS: 722 { 723 __be32 addr = in_aton(buf); 724 cxgb3i_set_private_ipv4addr(hba->ndev, addr); 725 return 0; 726 } 727 case ISCSI_HOST_PARAM_HWADDRESS: 728 case ISCSI_HOST_PARAM_NETDEV_NAME: 729 /* ignore */ 730 return 0; 731 default: 732 return iscsi_host_set_param(shost, param, buf, buflen); 733 } 734} 735 736/** 737 * cxgb3i_host_get_param - returns host (adapter) related parameters 738 * @shost: scsi host pointer 739 * @param: parameter type identifier 740 * @buf: buffer pointer 741 */ 742static int cxgb3i_host_get_param(struct Scsi_Host *shost, 743 enum iscsi_host_param param, char *buf) 744{ 745 struct cxgb3i_hba *hba = iscsi_host_priv(shost); 746 int len = 0; 747 748 if (!hba->ndev) { 749 shost_printk(KERN_ERR, shost, "Could not set host param. " 750 "Netdev for host not set.\n"); 751 return -ENODEV; 752 } 753 754 cxgb3i_api_debug("hba %s, param %d.\n", hba->ndev->name, param); 755 756 switch (param) { 757 case ISCSI_HOST_PARAM_HWADDRESS: 758 len = sysfs_format_mac(buf, hba->ndev->dev_addr, 6); 759 break; 760 case ISCSI_HOST_PARAM_NETDEV_NAME: 761 len = sprintf(buf, "%s\n", hba->ndev->name); 762 break; 763 case ISCSI_HOST_PARAM_IPADDRESS: 764 { 765 __be32 addr; 766 767 addr = cxgb3i_get_private_ipv4addr(hba->ndev); 768 len = sprintf(buf, "%pI4", &addr); 769 break; 770 } 771 default: 772 return iscsi_host_get_param(shost, param, buf); 773 } 774 return len; 775} 776 777/** 778 * cxgb3i_conn_get_stats - returns iSCSI stats 779 * @cls_conn: pointer to iscsi cls conn 780 * @stats: pointer to iscsi statistic struct 781 */ 782static void cxgb3i_conn_get_stats(struct iscsi_cls_conn *cls_conn, 783 struct iscsi_stats *stats) 784{ 785 struct iscsi_conn *conn = cls_conn->dd_data; 786 787 stats->txdata_octets = conn->txdata_octets; 788 stats->rxdata_octets = conn->rxdata_octets; 789 stats->scsicmd_pdus = conn->scsicmd_pdus_cnt; 790 stats->dataout_pdus = conn->dataout_pdus_cnt; 791 stats->scsirsp_pdus = conn->scsirsp_pdus_cnt; 792 stats->datain_pdus = conn->datain_pdus_cnt; 793 stats->r2t_pdus = conn->r2t_pdus_cnt; 794 stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt; 795 stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt; 796 stats->digest_err = 0; 797 stats->timeout_err = 0; 798 stats->custom_length = 1; 799 strcpy(stats->custom[0].desc, "eh_abort_cnt"); 800 stats->custom[0].value = conn->eh_abort_cnt; 801} 802 803/** 804 * cxgb3i_parse_itt - get the idx and age bits from a given tag 805 * @conn: iscsi connection 806 * @itt: itt tag 807 * @idx: task index, filled in by this function 808 * @age: session age, filled in by this function 809 */ 810static void cxgb3i_parse_itt(struct iscsi_conn *conn, itt_t itt, 811 int *idx, int *age) 812{ 813 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 814 struct cxgb3i_conn *cconn = tcp_conn->dd_data; 815 struct cxgb3i_adapter *snic = cconn->hba->snic; 816 u32 tag = ntohl((__force u32) itt); 817 u32 sw_bits; 818 819 sw_bits = cxgb3i_tag_nonrsvd_bits(&snic->tag_format, tag); 820 if (idx) 821 *idx = sw_bits & ((1 << cconn->task_idx_bits) - 1); 822 if (age) 823 *age = (sw_bits >> cconn->task_idx_bits) & ISCSI_AGE_MASK; 824 825 cxgb3i_tag_debug("parse tag 0x%x/0x%x, sw 0x%x, itt 0x%x, age 0x%x.\n", 826 tag, itt, sw_bits, idx ? *idx : 0xFFFFF, 827 age ? *age : 0xFF); 828} 829 830/** 831 * cxgb3i_reserve_itt - generate tag for a give task 832 * @task: iscsi task 833 * @hdr_itt: tag, filled in by this function 834 * Set up ddp for scsi read tasks if possible. 835 */ 836int cxgb3i_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt) 837{ 838 struct scsi_cmnd *sc = task->sc; 839 struct iscsi_conn *conn = task->conn; 840 struct iscsi_session *sess = conn->session; 841 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 842 struct cxgb3i_conn *cconn = tcp_conn->dd_data; 843 struct cxgb3i_adapter *snic = cconn->hba->snic; 844 struct cxgb3i_tag_format *tformat = &snic->tag_format; 845 u32 sw_tag = (sess->age << cconn->task_idx_bits) | task->itt; 846 u32 tag; 847 int err = -EINVAL; 848 849 if (sc && 850 (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_FROM_DEVICE) && 851 cxgb3i_sw_tag_usable(tformat, sw_tag)) { 852 struct s3_conn *c3cn = cconn->cep->c3cn; 853 struct cxgb3i_gather_list *gl; 854 855 gl = cxgb3i_ddp_make_gl(scsi_in(sc)->length, 856 scsi_in(sc)->table.sgl, 857 scsi_in(sc)->table.nents, 858 snic->pdev, 859 GFP_ATOMIC); 860 if (gl) { 861 tag = sw_tag; 862 err = cxgb3i_ddp_tag_reserve(snic->tdev, c3cn->tid, 863 tformat, &tag, 864 gl, GFP_ATOMIC); 865 if (err < 0) 866 cxgb3i_ddp_release_gl(gl, snic->pdev); 867 } 868 } 869 870 if (err < 0) 871 tag = cxgb3i_set_non_ddp_tag(tformat, sw_tag); 872 /* the itt need to sent in big-endian order */ 873 *hdr_itt = (__force itt_t)htonl(tag); 874 875 cxgb3i_tag_debug("new tag 0x%x/0x%x (itt 0x%x, age 0x%x).\n", 876 tag, *hdr_itt, task->itt, sess->age); 877 return 0; 878} 879 880/** 881 * cxgb3i_release_itt - release the tag for a given task 882 * @task: iscsi task 883 * @hdr_itt: tag 884 * If the tag is a ddp tag, release the ddp setup 885 */ 886void cxgb3i_release_itt(struct iscsi_task *task, itt_t hdr_itt) 887{ 888 struct scsi_cmnd *sc = task->sc; 889 struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data; 890 struct cxgb3i_conn *cconn = tcp_conn->dd_data; 891 struct cxgb3i_adapter *snic = cconn->hba->snic; 892 struct cxgb3i_tag_format *tformat = &snic->tag_format; 893 u32 tag = ntohl((__force u32)hdr_itt); 894 895 cxgb3i_tag_debug("release tag 0x%x.\n", tag); 896 897 if (sc && 898 (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_FROM_DEVICE) && 899 cxgb3i_is_ddp_tag(tformat, tag)) 900 cxgb3i_ddp_tag_release(snic->tdev, tag); 901} 902 903/** 904 * cxgb3i_host_template -- Scsi_Host_Template structure 905 * used when registering with the scsi mid layer 906 */ 907static struct scsi_host_template cxgb3i_host_template = { 908 .module = THIS_MODULE, 909 .name = "Chelsio S3xx iSCSI Initiator", 910 .proc_name = "cxgb3i", 911 .queuecommand = iscsi_queuecommand, 912 .change_queue_depth = iscsi_change_queue_depth, 913 .can_queue = CXGB3I_SCSI_HOST_QDEPTH, 914 .sg_tablesize = SG_ALL, 915 .max_sectors = 0xFFFF, 916 .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, 917 .eh_abort_handler = iscsi_eh_abort, 918 .eh_device_reset_handler = iscsi_eh_device_reset, 919 .eh_target_reset_handler = iscsi_eh_recover_target, 920 .target_alloc = iscsi_target_alloc, 921 .use_clustering = DISABLE_CLUSTERING, 922 .this_id = -1, 923}; 924 925static struct iscsi_transport cxgb3i_iscsi_transport = { 926 .owner = THIS_MODULE, 927 .name = "cxgb3i", 928 .caps = CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST 929 | CAP_DATADGST | CAP_DIGEST_OFFLOAD | 930 CAP_PADDING_OFFLOAD, 931 .param_mask = ISCSI_MAX_RECV_DLENGTH | 932 ISCSI_MAX_XMIT_DLENGTH | 933 ISCSI_HDRDGST_EN | 934 ISCSI_DATADGST_EN | 935 ISCSI_INITIAL_R2T_EN | 936 ISCSI_MAX_R2T | 937 ISCSI_IMM_DATA_EN | 938 ISCSI_FIRST_BURST | 939 ISCSI_MAX_BURST | 940 ISCSI_PDU_INORDER_EN | 941 ISCSI_DATASEQ_INORDER_EN | 942 ISCSI_ERL | 943 ISCSI_CONN_PORT | 944 ISCSI_CONN_ADDRESS | 945 ISCSI_EXP_STATSN | 946 ISCSI_PERSISTENT_PORT | 947 ISCSI_PERSISTENT_ADDRESS | 948 ISCSI_TARGET_NAME | ISCSI_TPGT | 949 ISCSI_USERNAME | ISCSI_PASSWORD | 950 ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN | 951 ISCSI_FAST_ABORT | ISCSI_ABORT_TMO | 952 ISCSI_LU_RESET_TMO | ISCSI_TGT_RESET_TMO | 953 ISCSI_PING_TMO | ISCSI_RECV_TMO | 954 ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME, 955 .host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | 956 ISCSI_HOST_INITIATOR_NAME | ISCSI_HOST_NETDEV_NAME, 957 .get_host_param = cxgb3i_host_get_param, 958 .set_host_param = cxgb3i_host_set_param, 959 /* session management */ 960 .create_session = cxgb3i_session_create, 961 .destroy_session = cxgb3i_session_destroy, 962 .get_session_param = iscsi_session_get_param, 963 /* connection management */ 964 .create_conn = cxgb3i_conn_create, 965 .bind_conn = cxgb3i_conn_bind, 966 .destroy_conn = iscsi_tcp_conn_teardown, 967 .start_conn = iscsi_conn_start, 968 .stop_conn = iscsi_conn_stop, 969 .get_conn_param = cxgb3i_conn_get_param, 970 .set_param = cxgb3i_conn_set_param, 971 .get_stats = cxgb3i_conn_get_stats, 972 /* pdu xmit req. from user space */ 973 .send_pdu = iscsi_conn_send_pdu, 974 /* task */ 975 .init_task = iscsi_tcp_task_init, 976 .xmit_task = iscsi_tcp_task_xmit, 977 .cleanup_task = cxgb3i_conn_cleanup_task, 978 979 /* pdu */ 980 .alloc_pdu = cxgb3i_conn_alloc_pdu, 981 .init_pdu = cxgb3i_conn_init_pdu, 982 .xmit_pdu = cxgb3i_conn_xmit_pdu, 983 .parse_pdu_itt = cxgb3i_parse_itt, 984 985 /* TCP connect/disconnect */ 986 .ep_connect = cxgb3i_ep_connect, 987 .ep_poll = cxgb3i_ep_poll, 988 .ep_disconnect = cxgb3i_ep_disconnect, 989 /* Error recovery timeout call */ 990 .session_recovery_timedout = iscsi_session_recovery_timedout, 991}; 992 993int cxgb3i_iscsi_init(void) 994{ 995 sw_tag_idx_bits = (__ilog2_u32(ISCSI_ITT_MASK)) + 1; 996 sw_tag_age_bits = (__ilog2_u32(ISCSI_AGE_MASK)) + 1; 997 cxgb3i_log_info("tag itt 0x%x, %u bits, age 0x%x, %u bits.\n", 998 ISCSI_ITT_MASK, sw_tag_idx_bits, 999 ISCSI_AGE_MASK, sw_tag_age_bits); 1000 1001 cxgb3i_scsi_transport = 1002 iscsi_register_transport(&cxgb3i_iscsi_transport); 1003 if (!cxgb3i_scsi_transport) { 1004 cxgb3i_log_error("Could not register cxgb3i transport.\n"); 1005 return -ENODEV; 1006 } 1007 cxgb3i_api_debug("cxgb3i transport 0x%p.\n", cxgb3i_scsi_transport); 1008 return 0; 1009} 1010 1011void cxgb3i_iscsi_cleanup(void) 1012{ 1013 if (cxgb3i_scsi_transport) { 1014 cxgb3i_api_debug("cxgb3i transport 0x%p.\n", 1015 cxgb3i_scsi_transport); 1016 iscsi_unregister_transport(&cxgb3i_iscsi_transport); 1017 } 1018} 1019