linux/drivers/scsi/bnx2i/bnx2i_iscsi.c
<<
>>
Prefs
   1/*
   2 * bnx2i_iscsi.c: Broadcom NetXtreme II iSCSI driver.
   3 *
   4 * Copyright (c) 2006 - 2009 Broadcom Corporation
   5 * Copyright (c) 2007, 2008 Red Hat, Inc.  All rights reserved.
   6 * Copyright (c) 2007, 2008 Mike Christie
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation.
  11 *
  12 * Written by: Anil Veerabhadrappa (anilgv@broadcom.com)
  13 */
  14
  15#include <scsi/scsi_tcq.h>
  16#include <scsi/libiscsi.h>
  17#include "bnx2i.h"
  18
  19struct scsi_transport_template *bnx2i_scsi_xport_template;
  20struct iscsi_transport bnx2i_iscsi_transport;
  21static struct scsi_host_template bnx2i_host_template;
  22
  23/*
  24 * Global endpoint resource info
  25 */
  26static DEFINE_SPINLOCK(bnx2i_resc_lock); /* protects global resources */
  27
  28
  29static int bnx2i_adapter_ready(struct bnx2i_hba *hba)
  30{
  31        int retval = 0;
  32
  33        if (!hba || !test_bit(ADAPTER_STATE_UP, &hba->adapter_state) ||
  34            test_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state) ||
  35            test_bit(ADAPTER_STATE_LINK_DOWN, &hba->adapter_state))
  36                retval = -EPERM;
  37        return retval;
  38}
  39
  40/**
  41 * bnx2i_get_write_cmd_bd_idx - identifies various BD bookmarks
  42 * @cmd:                iscsi cmd struct pointer
  43 * @buf_off:            absolute buffer offset
  44 * @start_bd_off:       u32 pointer to return the offset within the BD
  45 *                      indicated by 'start_bd_idx' on which 'buf_off' falls
  46 * @start_bd_idx:       index of the BD on which 'buf_off' falls
  47 *
  48 * identifies & marks various bd info for scsi command's imm data,
  49 * unsolicited data and the first solicited data seq.
  50 */
  51static void bnx2i_get_write_cmd_bd_idx(struct bnx2i_cmd *cmd, u32 buf_off,
  52                                       u32 *start_bd_off, u32 *start_bd_idx)
  53{
  54        struct iscsi_bd *bd_tbl = cmd->io_tbl.bd_tbl;
  55        u32 cur_offset = 0;
  56        u32 cur_bd_idx = 0;
  57
  58        if (buf_off) {
  59                while (buf_off >= (cur_offset + bd_tbl->buffer_length)) {
  60                        cur_offset += bd_tbl->buffer_length;
  61                        cur_bd_idx++;
  62                        bd_tbl++;
  63                }
  64        }
  65
  66        *start_bd_off = buf_off - cur_offset;
  67        *start_bd_idx = cur_bd_idx;
  68}
  69
  70/**
  71 * bnx2i_setup_write_cmd_bd_info - sets up BD various information
  72 * @task:       transport layer's cmd struct pointer
  73 *
  74 * identifies & marks various bd info for scsi command's immediate data,
  75 * unsolicited data and first solicited data seq which includes BD start
  76 * index & BD buf off. his function takes into account iscsi parameter such
  77 * as immediate data and unsolicited data is support on this connection.
  78 */
  79static void bnx2i_setup_write_cmd_bd_info(struct iscsi_task *task)
  80{
  81        struct bnx2i_cmd *cmd = task->dd_data;
  82        u32 start_bd_offset;
  83        u32 start_bd_idx;
  84        u32 buffer_offset = 0;
  85        u32 cmd_len = cmd->req.total_data_transfer_length;
  86
  87        /* if ImmediateData is turned off & IntialR2T is turned on,
  88         * there will be no immediate or unsolicited data, just return.
  89         */
  90        if (!iscsi_task_has_unsol_data(task) && !task->imm_count)
  91                return;
  92
  93        /* Immediate data */
  94        buffer_offset += task->imm_count;
  95        if (task->imm_count == cmd_len)
  96                return;
  97
  98        if (iscsi_task_has_unsol_data(task)) {
  99                bnx2i_get_write_cmd_bd_idx(cmd, buffer_offset,
 100                                           &start_bd_offset, &start_bd_idx);
 101                cmd->req.ud_buffer_offset = start_bd_offset;
 102                cmd->req.ud_start_bd_index = start_bd_idx;
 103                buffer_offset += task->unsol_r2t.data_length;
 104        }
 105
 106        if (buffer_offset != cmd_len) {
 107                bnx2i_get_write_cmd_bd_idx(cmd, buffer_offset,
 108                                           &start_bd_offset, &start_bd_idx);
 109                if ((start_bd_offset > task->conn->session->first_burst) ||
 110                    (start_bd_idx > scsi_sg_count(cmd->scsi_cmd))) {
 111                        int i = 0;
 112
 113                        iscsi_conn_printk(KERN_ALERT, task->conn,
 114                                          "bnx2i- error, buf offset 0x%x "
 115                                          "bd_valid %d use_sg %d\n",
 116                                          buffer_offset, cmd->io_tbl.bd_valid,
 117                                          scsi_sg_count(cmd->scsi_cmd));
 118                        for (i = 0; i < cmd->io_tbl.bd_valid; i++)
 119                                iscsi_conn_printk(KERN_ALERT, task->conn,
 120                                                  "bnx2i err, bd[%d]: len %x\n",
 121                                                  i, cmd->io_tbl.bd_tbl[i].\
 122                                                  buffer_length);
 123                }
 124                cmd->req.sd_buffer_offset = start_bd_offset;
 125                cmd->req.sd_start_bd_index = start_bd_idx;
 126        }
 127}
 128
 129
 130
 131/**
 132 * bnx2i_map_scsi_sg - maps IO buffer and prepares the BD table
 133 * @hba:        adapter instance
 134 * @cmd:        iscsi cmd struct pointer
 135 *
 136 * map SG list
 137 */
 138static int bnx2i_map_scsi_sg(struct bnx2i_hba *hba, struct bnx2i_cmd *cmd)
 139{
 140        struct scsi_cmnd *sc = cmd->scsi_cmd;
 141        struct iscsi_bd *bd = cmd->io_tbl.bd_tbl;
 142        struct scatterlist *sg;
 143        int byte_count = 0;
 144        int bd_count = 0;
 145        int sg_count;
 146        int sg_len;
 147        u64 addr;
 148        int i;
 149
 150        BUG_ON(scsi_sg_count(sc) > ISCSI_MAX_BDS_PER_CMD);
 151
 152        sg_count = scsi_dma_map(sc);
 153
 154        scsi_for_each_sg(sc, sg, sg_count, i) {
 155                sg_len = sg_dma_len(sg);
 156                addr = (u64) sg_dma_address(sg);
 157                bd[bd_count].buffer_addr_lo = addr & 0xffffffff;
 158                bd[bd_count].buffer_addr_hi = addr >> 32;
 159                bd[bd_count].buffer_length = sg_len;
 160                bd[bd_count].flags = 0;
 161                if (bd_count == 0)
 162                        bd[bd_count].flags = ISCSI_BD_FIRST_IN_BD_CHAIN;
 163
 164                byte_count += sg_len;
 165                bd_count++;
 166        }
 167
 168        if (bd_count)
 169                bd[bd_count - 1].flags |= ISCSI_BD_LAST_IN_BD_CHAIN;
 170
 171        BUG_ON(byte_count != scsi_bufflen(sc));
 172        return bd_count;
 173}
 174
 175/**
 176 * bnx2i_iscsi_map_sg_list - maps SG list
 177 * @cmd:        iscsi cmd struct pointer
 178 *
 179 * creates BD list table for the command
 180 */
 181static void bnx2i_iscsi_map_sg_list(struct bnx2i_cmd *cmd)
 182{
 183        int bd_count;
 184
 185        bd_count  = bnx2i_map_scsi_sg(cmd->conn->hba, cmd);
 186        if (!bd_count) {
 187                struct iscsi_bd *bd = cmd->io_tbl.bd_tbl;
 188
 189                bd[0].buffer_addr_lo = bd[0].buffer_addr_hi = 0;
 190                bd[0].buffer_length = bd[0].flags = 0;
 191        }
 192        cmd->io_tbl.bd_valid = bd_count;
 193}
 194
 195
 196/**
 197 * bnx2i_iscsi_unmap_sg_list - unmaps SG list
 198 * @cmd:        iscsi cmd struct pointer
 199 *
 200 * unmap IO buffers and invalidate the BD table
 201 */
 202void bnx2i_iscsi_unmap_sg_list(struct bnx2i_cmd *cmd)
 203{
 204        struct scsi_cmnd *sc = cmd->scsi_cmd;
 205
 206        if (cmd->io_tbl.bd_valid && sc) {
 207                scsi_dma_unmap(sc);
 208                cmd->io_tbl.bd_valid = 0;
 209        }
 210}
 211
 212static void bnx2i_setup_cmd_wqe_template(struct bnx2i_cmd *cmd)
 213{
 214        memset(&cmd->req, 0x00, sizeof(cmd->req));
 215        cmd->req.op_code = 0xFF;
 216        cmd->req.bd_list_addr_lo = (u32) cmd->io_tbl.bd_tbl_dma;
 217        cmd->req.bd_list_addr_hi =
 218                (u32) ((u64) cmd->io_tbl.bd_tbl_dma >> 32);
 219
 220}
 221
 222
 223/**
 224 * bnx2i_bind_conn_to_iscsi_cid - bind conn structure to 'iscsi_cid'
 225 * @hba:        pointer to adapter instance
 226 * @conn:       pointer to iscsi connection
 227 * @iscsi_cid:  iscsi context ID, range 0 - (MAX_CONN - 1)
 228 *
 229 * update iscsi cid table entry with connection pointer. This enables
 230 *      driver to quickly get hold of connection structure pointer in
 231 *      completion/interrupt thread using iscsi context ID
 232 */
 233static int bnx2i_bind_conn_to_iscsi_cid(struct bnx2i_hba *hba,
 234                                        struct bnx2i_conn *bnx2i_conn,
 235                                        u32 iscsi_cid)
 236{
 237        if (hba && hba->cid_que.conn_cid_tbl[iscsi_cid]) {
 238                iscsi_conn_printk(KERN_ALERT, bnx2i_conn->cls_conn->dd_data,
 239                                 "conn bind - entry #%d not free\n", iscsi_cid);
 240                return -EBUSY;
 241        }
 242
 243        hba->cid_que.conn_cid_tbl[iscsi_cid] = bnx2i_conn;
 244        return 0;
 245}
 246
 247
 248/**
 249 * bnx2i_get_conn_from_id - maps an iscsi cid to corresponding conn ptr
 250 * @hba:        pointer to adapter instance
 251 * @iscsi_cid:  iscsi context ID, range 0 - (MAX_CONN - 1)
 252 */
 253struct bnx2i_conn *bnx2i_get_conn_from_id(struct bnx2i_hba *hba,
 254                                          u16 iscsi_cid)
 255{
 256        if (!hba->cid_que.conn_cid_tbl) {
 257                printk(KERN_ERR "bnx2i: ERROR - missing conn<->cid table\n");
 258                return NULL;
 259
 260        } else if (iscsi_cid >= hba->max_active_conns) {
 261                printk(KERN_ERR "bnx2i: wrong cid #%d\n", iscsi_cid);
 262                return NULL;
 263        }
 264        return hba->cid_que.conn_cid_tbl[iscsi_cid];
 265}
 266
 267
 268/**
 269 * bnx2i_alloc_iscsi_cid - allocates a iscsi_cid from free pool
 270 * @hba:        pointer to adapter instance
 271 */
 272static u32 bnx2i_alloc_iscsi_cid(struct bnx2i_hba *hba)
 273{
 274        int idx;
 275
 276        if (!hba->cid_que.cid_free_cnt)
 277                return -1;
 278
 279        idx = hba->cid_que.cid_q_cons_idx;
 280        hba->cid_que.cid_q_cons_idx++;
 281        if (hba->cid_que.cid_q_cons_idx == hba->cid_que.cid_q_max_idx)
 282                hba->cid_que.cid_q_cons_idx = 0;
 283
 284        hba->cid_que.cid_free_cnt--;
 285        return hba->cid_que.cid_que[idx];
 286}
 287
 288
 289/**
 290 * bnx2i_free_iscsi_cid - returns tcp port to free list
 291 * @hba:                pointer to adapter instance
 292 * @iscsi_cid:          iscsi context ID to free
 293 */
 294static void bnx2i_free_iscsi_cid(struct bnx2i_hba *hba, u16 iscsi_cid)
 295{
 296        int idx;
 297
 298        if (iscsi_cid == (u16) -1)
 299                return;
 300
 301        hba->cid_que.cid_free_cnt++;
 302
 303        idx = hba->cid_que.cid_q_prod_idx;
 304        hba->cid_que.cid_que[idx] = iscsi_cid;
 305        hba->cid_que.conn_cid_tbl[iscsi_cid] = NULL;
 306        hba->cid_que.cid_q_prod_idx++;
 307        if (hba->cid_que.cid_q_prod_idx == hba->cid_que.cid_q_max_idx)
 308                hba->cid_que.cid_q_prod_idx = 0;
 309}
 310
 311
 312/**
 313 * bnx2i_setup_free_cid_que - sets up free iscsi cid queue
 314 * @hba:        pointer to adapter instance
 315 *
 316 * allocates memory for iscsi cid queue & 'cid - conn ptr' mapping table,
 317 *      and initialize table attributes
 318 */
 319static int bnx2i_setup_free_cid_que(struct bnx2i_hba *hba)
 320{
 321        int mem_size;
 322        int i;
 323
 324        mem_size = hba->max_active_conns * sizeof(u32);
 325        mem_size = (mem_size + (PAGE_SIZE - 1)) & PAGE_MASK;
 326
 327        hba->cid_que.cid_que_base = kmalloc(mem_size, GFP_KERNEL);
 328        if (!hba->cid_que.cid_que_base)
 329                return -ENOMEM;
 330
 331        mem_size = hba->max_active_conns * sizeof(struct bnx2i_conn *);
 332        mem_size = (mem_size + (PAGE_SIZE - 1)) & PAGE_MASK;
 333        hba->cid_que.conn_cid_tbl = kmalloc(mem_size, GFP_KERNEL);
 334        if (!hba->cid_que.conn_cid_tbl) {
 335                kfree(hba->cid_que.cid_que_base);
 336                hba->cid_que.cid_que_base = NULL;
 337                return -ENOMEM;
 338        }
 339
 340        hba->cid_que.cid_que = (u32 *)hba->cid_que.cid_que_base;
 341        hba->cid_que.cid_q_prod_idx = 0;
 342        hba->cid_que.cid_q_cons_idx = 0;
 343        hba->cid_que.cid_q_max_idx = hba->max_active_conns;
 344        hba->cid_que.cid_free_cnt = hba->max_active_conns;
 345
 346        for (i = 0; i < hba->max_active_conns; i++) {
 347                hba->cid_que.cid_que[i] = i;
 348                hba->cid_que.conn_cid_tbl[i] = NULL;
 349        }
 350        return 0;
 351}
 352
 353
 354/**
 355 * bnx2i_release_free_cid_que - releases 'iscsi_cid' queue resources
 356 * @hba:        pointer to adapter instance
 357 */
 358static void bnx2i_release_free_cid_que(struct bnx2i_hba *hba)
 359{
 360        kfree(hba->cid_que.cid_que_base);
 361        hba->cid_que.cid_que_base = NULL;
 362
 363        kfree(hba->cid_que.conn_cid_tbl);
 364        hba->cid_que.conn_cid_tbl = NULL;
 365}
 366
 367
 368/**
 369 * bnx2i_alloc_ep - allocates ep structure from global pool
 370 * @hba:        pointer to adapter instance
 371 *
 372 * routine allocates a free endpoint structure from global pool and
 373 *      a tcp port to be used for this connection.  Global resource lock,
 374 *      'bnx2i_resc_lock' is held while accessing shared global data structures
 375 */
 376static struct iscsi_endpoint *bnx2i_alloc_ep(struct bnx2i_hba *hba)
 377{
 378        struct iscsi_endpoint *ep;
 379        struct bnx2i_endpoint *bnx2i_ep;
 380
 381        ep = iscsi_create_endpoint(sizeof(*bnx2i_ep));
 382        if (!ep) {
 383                printk(KERN_ERR "bnx2i: Could not allocate ep\n");
 384                return NULL;
 385        }
 386
 387        bnx2i_ep = ep->dd_data;
 388        INIT_LIST_HEAD(&bnx2i_ep->link);
 389        bnx2i_ep->state = EP_STATE_IDLE;
 390        bnx2i_ep->ep_iscsi_cid = (u16) -1;
 391        bnx2i_ep->hba = hba;
 392        bnx2i_ep->hba_age = hba->age;
 393        hba->ofld_conns_active++;
 394        init_waitqueue_head(&bnx2i_ep->ofld_wait);
 395        return ep;
 396}
 397
 398
 399/**
 400 * bnx2i_free_ep - free endpoint
 401 * @ep:         pointer to iscsi endpoint structure
 402 */
 403static void bnx2i_free_ep(struct iscsi_endpoint *ep)
 404{
 405        struct bnx2i_endpoint *bnx2i_ep = ep->dd_data;
 406        unsigned long flags;
 407
 408        spin_lock_irqsave(&bnx2i_resc_lock, flags);
 409        bnx2i_ep->state = EP_STATE_IDLE;
 410        bnx2i_ep->hba->ofld_conns_active--;
 411
 412        bnx2i_free_iscsi_cid(bnx2i_ep->hba, bnx2i_ep->ep_iscsi_cid);
 413        if (bnx2i_ep->conn) {
 414                bnx2i_ep->conn->ep = NULL;
 415                bnx2i_ep->conn = NULL;
 416        }
 417
 418        bnx2i_ep->hba = NULL;
 419        spin_unlock_irqrestore(&bnx2i_resc_lock, flags);
 420        iscsi_destroy_endpoint(ep);
 421}
 422
 423
 424/**
 425 * bnx2i_alloc_bdt - allocates buffer descriptor (BD) table for the command
 426 * @hba:        adapter instance pointer
 427 * @session:    iscsi session pointer
 428 * @cmd:        iscsi command structure
 429 */
 430static int bnx2i_alloc_bdt(struct bnx2i_hba *hba, struct iscsi_session *session,
 431                           struct bnx2i_cmd *cmd)
 432{
 433        struct io_bdt *io = &cmd->io_tbl;
 434        struct iscsi_bd *bd;
 435
 436        io->bd_tbl = dma_alloc_coherent(&hba->pcidev->dev,
 437                                        ISCSI_MAX_BDS_PER_CMD * sizeof(*bd),
 438                                        &io->bd_tbl_dma, GFP_KERNEL);
 439        if (!io->bd_tbl) {
 440                iscsi_session_printk(KERN_ERR, session, "Could not "
 441                                     "allocate bdt.\n");
 442                return -ENOMEM;
 443        }
 444        io->bd_valid = 0;
 445        return 0;
 446}
 447
 448/**
 449 * bnx2i_destroy_cmd_pool - destroys iscsi command pool and release BD table
 450 * @hba:        adapter instance pointer
 451 * @session:    iscsi session pointer
 452 * @cmd:        iscsi command structure
 453 */
 454static void bnx2i_destroy_cmd_pool(struct bnx2i_hba *hba,
 455                                   struct iscsi_session *session)
 456{
 457        int i;
 458
 459        for (i = 0; i < session->cmds_max; i++) {
 460                struct iscsi_task *task = session->cmds[i];
 461                struct bnx2i_cmd *cmd = task->dd_data;
 462
 463                if (cmd->io_tbl.bd_tbl)
 464                        dma_free_coherent(&hba->pcidev->dev,
 465                                          ISCSI_MAX_BDS_PER_CMD *
 466                                          sizeof(struct iscsi_bd),
 467                                          cmd->io_tbl.bd_tbl,
 468                                          cmd->io_tbl.bd_tbl_dma);
 469        }
 470
 471}
 472
 473
 474/**
 475 * bnx2i_setup_cmd_pool - sets up iscsi command pool for the session
 476 * @hba:        adapter instance pointer
 477 * @session:    iscsi session pointer
 478 */
 479static int bnx2i_setup_cmd_pool(struct bnx2i_hba *hba,
 480                                struct iscsi_session *session)
 481{
 482        int i;
 483
 484        for (i = 0; i < session->cmds_max; i++) {
 485                struct iscsi_task *task = session->cmds[i];
 486                struct bnx2i_cmd *cmd = task->dd_data;
 487
 488                /* Anil */
 489                task->hdr = &cmd->hdr;
 490                task->hdr_max = sizeof(struct iscsi_hdr);
 491
 492                if (bnx2i_alloc_bdt(hba, session, cmd))
 493                        goto free_bdts;
 494        }
 495
 496        return 0;
 497
 498free_bdts:
 499        bnx2i_destroy_cmd_pool(hba, session);
 500        return -ENOMEM;
 501}
 502
 503
 504/**
 505 * bnx2i_setup_mp_bdt - allocate BD table resources
 506 * @hba:        pointer to adapter structure
 507 *
 508 * Allocate memory for dummy buffer and associated BD
 509 * table to be used by middle path (MP) requests
 510 */
 511static int bnx2i_setup_mp_bdt(struct bnx2i_hba *hba)
 512{
 513        int rc = 0;
 514        struct iscsi_bd *mp_bdt;
 515        u64 addr;
 516
 517        hba->mp_bd_tbl = dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
 518                                            &hba->mp_bd_dma, GFP_KERNEL);
 519        if (!hba->mp_bd_tbl) {
 520                printk(KERN_ERR "unable to allocate Middle Path BDT\n");
 521                rc = -1;
 522                goto out;
 523        }
 524
 525        hba->dummy_buffer = dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
 526                                               &hba->dummy_buf_dma, GFP_KERNEL);
 527        if (!hba->dummy_buffer) {
 528                printk(KERN_ERR "unable to alloc Middle Path Dummy Buffer\n");
 529                dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
 530                                  hba->mp_bd_tbl, hba->mp_bd_dma);
 531                hba->mp_bd_tbl = NULL;
 532                rc = -1;
 533                goto out;
 534        }
 535
 536        mp_bdt = (struct iscsi_bd *) hba->mp_bd_tbl;
 537        addr = (unsigned long) hba->dummy_buf_dma;
 538        mp_bdt->buffer_addr_lo = addr & 0xffffffff;
 539        mp_bdt->buffer_addr_hi = addr >> 32;
 540        mp_bdt->buffer_length = PAGE_SIZE;
 541        mp_bdt->flags = ISCSI_BD_LAST_IN_BD_CHAIN |
 542                        ISCSI_BD_FIRST_IN_BD_CHAIN;
 543out:
 544        return rc;
 545}
 546
 547
 548/**
 549 * bnx2i_free_mp_bdt - releases ITT back to free pool
 550 * @hba:        pointer to adapter instance
 551 *
 552 * free MP dummy buffer and associated BD table
 553 */
 554static void bnx2i_free_mp_bdt(struct bnx2i_hba *hba)
 555{
 556        if (hba->mp_bd_tbl) {
 557                dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
 558                                  hba->mp_bd_tbl, hba->mp_bd_dma);
 559                hba->mp_bd_tbl = NULL;
 560        }
 561        if (hba->dummy_buffer) {
 562                dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
 563                                  hba->dummy_buffer, hba->dummy_buf_dma);
 564                hba->dummy_buffer = NULL;
 565        }
 566                return;
 567}
 568
 569/**
 570 * bnx2i_drop_session - notifies iscsid of connection error.
 571 * @hba:        adapter instance pointer
 572 * @session:    iscsi session pointer
 573 *
 574 * This notifies iscsid that there is a error, so it can initiate
 575 * recovery.
 576 *
 577 * This relies on caller using the iscsi class iterator so the object
 578 * is refcounted and does not disapper from under us.
 579 */
 580void bnx2i_drop_session(struct iscsi_cls_session *cls_session)
 581{
 582        iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_CONN_FAILED);
 583}
 584
 585/**
 586 * bnx2i_ep_destroy_list_add - add an entry to EP destroy list
 587 * @hba:        pointer to adapter instance
 588 * @ep:         pointer to endpoint (transport indentifier) structure
 589 *
 590 * EP destroy queue manager
 591 */
 592static int bnx2i_ep_destroy_list_add(struct bnx2i_hba *hba,
 593                                     struct bnx2i_endpoint *ep)
 594{
 595        write_lock_bh(&hba->ep_rdwr_lock);
 596        list_add_tail(&ep->link, &hba->ep_destroy_list);
 597        write_unlock_bh(&hba->ep_rdwr_lock);
 598        return 0;
 599}
 600
 601/**
 602 * bnx2i_ep_destroy_list_del - add an entry to EP destroy list
 603 *
 604 * @hba:                pointer to adapter instance
 605 * @ep:                 pointer to endpoint (transport indentifier) structure
 606 *
 607 * EP destroy queue manager
 608 */
 609static int bnx2i_ep_destroy_list_del(struct bnx2i_hba *hba,
 610                                     struct bnx2i_endpoint *ep)
 611{
 612        write_lock_bh(&hba->ep_rdwr_lock);
 613        list_del_init(&ep->link);
 614        write_unlock_bh(&hba->ep_rdwr_lock);
 615
 616        return 0;
 617}
 618
 619/**
 620 * bnx2i_ep_ofld_list_add - add an entry to ep offload pending list
 621 * @hba:        pointer to adapter instance
 622 * @ep:         pointer to endpoint (transport indentifier) structure
 623 *
 624 * pending conn offload completion queue manager
 625 */
 626static int bnx2i_ep_ofld_list_add(struct bnx2i_hba *hba,
 627                                  struct bnx2i_endpoint *ep)
 628{
 629        write_lock_bh(&hba->ep_rdwr_lock);
 630        list_add_tail(&ep->link, &hba->ep_ofld_list);
 631        write_unlock_bh(&hba->ep_rdwr_lock);
 632        return 0;
 633}
 634
 635/**
 636 * bnx2i_ep_ofld_list_del - add an entry to ep offload pending list
 637 * @hba:                pointer to adapter instance
 638 * @ep:                 pointer to endpoint (transport indentifier) structure
 639 *
 640 * pending conn offload completion queue manager
 641 */
 642static int bnx2i_ep_ofld_list_del(struct bnx2i_hba *hba,
 643                                  struct bnx2i_endpoint *ep)
 644{
 645        write_lock_bh(&hba->ep_rdwr_lock);
 646        list_del_init(&ep->link);
 647        write_unlock_bh(&hba->ep_rdwr_lock);
 648        return 0;
 649}
 650
 651
 652/**
 653 * bnx2i_find_ep_in_ofld_list - find iscsi_cid in pending list of endpoints
 654 *
 655 * @hba:                pointer to adapter instance
 656 * @iscsi_cid:          iscsi context ID to find
 657 *
 658 */
 659struct bnx2i_endpoint *
 660bnx2i_find_ep_in_ofld_list(struct bnx2i_hba *hba, u32 iscsi_cid)
 661{
 662        struct list_head *list;
 663        struct list_head *tmp;
 664        struct bnx2i_endpoint *ep;
 665
 666        read_lock_bh(&hba->ep_rdwr_lock);
 667        list_for_each_safe(list, tmp, &hba->ep_ofld_list) {
 668                ep = (struct bnx2i_endpoint *)list;
 669
 670                if (ep->ep_iscsi_cid == iscsi_cid)
 671                        break;
 672                ep = NULL;
 673        }
 674        read_unlock_bh(&hba->ep_rdwr_lock);
 675
 676        if (!ep)
 677                printk(KERN_ERR "l5 cid %d not found\n", iscsi_cid);
 678        return ep;
 679}
 680
 681
 682/**
 683 * bnx2i_find_ep_in_destroy_list - find iscsi_cid in destroy list
 684 * @hba:                pointer to adapter instance
 685 * @iscsi_cid:          iscsi context ID to find
 686 *
 687 */
 688struct bnx2i_endpoint *
 689bnx2i_find_ep_in_destroy_list(struct bnx2i_hba *hba, u32 iscsi_cid)
 690{
 691        struct list_head *list;
 692        struct list_head *tmp;
 693        struct bnx2i_endpoint *ep;
 694
 695        read_lock_bh(&hba->ep_rdwr_lock);
 696        list_for_each_safe(list, tmp, &hba->ep_destroy_list) {
 697                ep = (struct bnx2i_endpoint *)list;
 698
 699                if (ep->ep_iscsi_cid == iscsi_cid)
 700                        break;
 701                ep = NULL;
 702        }
 703        read_unlock_bh(&hba->ep_rdwr_lock);
 704
 705        if (!ep)
 706                printk(KERN_ERR "l5 cid %d not found\n", iscsi_cid);
 707
 708        return ep;
 709}
 710
 711/**
 712 * bnx2i_setup_host_queue_size - assigns shost->can_queue param
 713 * @hba:        pointer to adapter instance
 714 * @shost:      scsi host pointer
 715 *
 716 * Initializes 'can_queue' parameter based on how many outstanding commands
 717 *      the device can handle. Each device 5708/5709/57710 has different
 718 *      capabilities
 719 */
 720static void bnx2i_setup_host_queue_size(struct bnx2i_hba *hba,
 721                                        struct Scsi_Host *shost)
 722{
 723        if (test_bit(BNX2I_NX2_DEV_5708, &hba->cnic_dev_type))
 724                shost->can_queue = ISCSI_MAX_CMDS_PER_HBA_5708;
 725        else if (test_bit(BNX2I_NX2_DEV_5709, &hba->cnic_dev_type))
 726                shost->can_queue = ISCSI_MAX_CMDS_PER_HBA_5709;
 727        else if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type))
 728                shost->can_queue = ISCSI_MAX_CMDS_PER_HBA_57710;
 729        else
 730                shost->can_queue = ISCSI_MAX_CMDS_PER_HBA_5708;
 731}
 732
 733
 734/**
 735 * bnx2i_alloc_hba - allocate and init adapter instance
 736 * @cnic:       cnic device pointer
 737 *
 738 * allocate & initialize adapter structure and call other
 739 *      support routines to do per adapter initialization
 740 */
 741struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic)
 742{
 743        struct Scsi_Host *shost;
 744        struct bnx2i_hba *hba;
 745
 746        shost = iscsi_host_alloc(&bnx2i_host_template, sizeof(*hba), 0);
 747        if (!shost)
 748                return NULL;
 749        shost->dma_boundary = cnic->pcidev->dma_mask;
 750        shost->transportt = bnx2i_scsi_xport_template;
 751        shost->max_id = ISCSI_MAX_CONNS_PER_HBA;
 752        shost->max_channel = 0;
 753        shost->max_lun = 512;
 754        shost->max_cmd_len = 16;
 755
 756        hba = iscsi_host_priv(shost);
 757        hba->shost = shost;
 758        hba->netdev = cnic->netdev;
 759        /* Get PCI related information and update hba struct members */
 760        hba->pcidev = cnic->pcidev;
 761        pci_dev_get(hba->pcidev);
 762        hba->pci_did = hba->pcidev->device;
 763        hba->pci_vid = hba->pcidev->vendor;
 764        hba->pci_sdid = hba->pcidev->subsystem_device;
 765        hba->pci_svid = hba->pcidev->subsystem_vendor;
 766        hba->pci_func = PCI_FUNC(hba->pcidev->devfn);
 767        hba->pci_devno = PCI_SLOT(hba->pcidev->devfn);
 768        bnx2i_identify_device(hba);
 769
 770        bnx2i_identify_device(hba);
 771        bnx2i_setup_host_queue_size(hba, shost);
 772
 773        if (test_bit(BNX2I_NX2_DEV_5709, &hba->cnic_dev_type)) {
 774                hba->regview = ioremap_nocache(hba->netdev->base_addr,
 775                                               BNX2_MQ_CONFIG2);
 776                if (!hba->regview)
 777                        goto ioreg_map_err;
 778        } else if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) {
 779                hba->regview = ioremap_nocache(hba->netdev->base_addr, 4096);
 780                if (!hba->regview)
 781                        goto ioreg_map_err;
 782        }
 783
 784        if (bnx2i_setup_mp_bdt(hba))
 785                goto mp_bdt_mem_err;
 786
 787        INIT_LIST_HEAD(&hba->ep_ofld_list);
 788        INIT_LIST_HEAD(&hba->ep_destroy_list);
 789        rwlock_init(&hba->ep_rdwr_lock);
 790
 791        hba->mtu_supported = BNX2I_MAX_MTU_SUPPORTED;
 792
 793        /* different values for 5708/5709/57710 */
 794        hba->max_active_conns = ISCSI_MAX_CONNS_PER_HBA;
 795
 796        if (bnx2i_setup_free_cid_que(hba))
 797                goto cid_que_err;
 798
 799        /* SQ/RQ/CQ size can be changed via sysfx interface */
 800        if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) {
 801                if (sq_size && sq_size <= BNX2I_5770X_SQ_WQES_MAX)
 802                        hba->max_sqes = sq_size;
 803                else
 804                        hba->max_sqes = BNX2I_5770X_SQ_WQES_DEFAULT;
 805        } else {        /* 5706/5708/5709 */
 806                if (sq_size && sq_size <= BNX2I_570X_SQ_WQES_MAX)
 807                        hba->max_sqes = sq_size;
 808                else
 809                        hba->max_sqes = BNX2I_570X_SQ_WQES_DEFAULT;
 810        }
 811
 812        hba->max_rqes = rq_size;
 813        hba->max_cqes = hba->max_sqes + rq_size;
 814        if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) {
 815                if (hba->max_cqes > BNX2I_5770X_CQ_WQES_MAX)
 816                        hba->max_cqes = BNX2I_5770X_CQ_WQES_MAX;
 817        } else if (hba->max_cqes > BNX2I_570X_CQ_WQES_MAX)
 818                hba->max_cqes = BNX2I_570X_CQ_WQES_MAX;
 819
 820        hba->num_ccell = hba->max_sqes / 2;
 821
 822        spin_lock_init(&hba->lock);
 823        mutex_init(&hba->net_dev_lock);
 824
 825        if (iscsi_host_add(shost, &hba->pcidev->dev))
 826                goto free_dump_mem;
 827        return hba;
 828
 829free_dump_mem:
 830        bnx2i_release_free_cid_que(hba);
 831cid_que_err:
 832        bnx2i_free_mp_bdt(hba);
 833mp_bdt_mem_err:
 834        if (hba->regview) {
 835                iounmap(hba->regview);
 836                hba->regview = NULL;
 837        }
 838ioreg_map_err:
 839        pci_dev_put(hba->pcidev);
 840        scsi_host_put(shost);
 841        return NULL;
 842}
 843
 844/**
 845 * bnx2i_free_hba- releases hba structure and resources held by the adapter
 846 * @hba:        pointer to adapter instance
 847 *
 848 * free adapter structure and call various cleanup routines.
 849 */
 850void bnx2i_free_hba(struct bnx2i_hba *hba)
 851{
 852        struct Scsi_Host *shost = hba->shost;
 853
 854        iscsi_host_remove(shost);
 855        INIT_LIST_HEAD(&hba->ep_ofld_list);
 856        INIT_LIST_HEAD(&hba->ep_destroy_list);
 857        pci_dev_put(hba->pcidev);
 858
 859        if (hba->regview) {
 860                iounmap(hba->regview);
 861                hba->regview = NULL;
 862        }
 863        bnx2i_free_mp_bdt(hba);
 864        bnx2i_release_free_cid_que(hba);
 865        iscsi_host_free(shost);
 866}
 867
 868/**
 869 * bnx2i_conn_free_login_resources - free DMA resources used for login process
 870 * @hba:                pointer to adapter instance
 871 * @bnx2i_conn:         iscsi connection pointer
 872 *
 873 * Login related resources, mostly BDT & payload DMA memory is freed
 874 */
 875static void bnx2i_conn_free_login_resources(struct bnx2i_hba *hba,
 876                                            struct bnx2i_conn *bnx2i_conn)
 877{
 878        if (bnx2i_conn->gen_pdu.resp_bd_tbl) {
 879                dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
 880                                  bnx2i_conn->gen_pdu.resp_bd_tbl,
 881                                  bnx2i_conn->gen_pdu.resp_bd_dma);
 882                bnx2i_conn->gen_pdu.resp_bd_tbl = NULL;
 883        }
 884
 885        if (bnx2i_conn->gen_pdu.req_bd_tbl) {
 886                dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
 887                                  bnx2i_conn->gen_pdu.req_bd_tbl,
 888                                  bnx2i_conn->gen_pdu.req_bd_dma);
 889                bnx2i_conn->gen_pdu.req_bd_tbl = NULL;
 890        }
 891
 892        if (bnx2i_conn->gen_pdu.resp_buf) {
 893                dma_free_coherent(&hba->pcidev->dev,
 894                                  ISCSI_DEF_MAX_RECV_SEG_LEN,
 895                                  bnx2i_conn->gen_pdu.resp_buf,
 896                                  bnx2i_conn->gen_pdu.resp_dma_addr);
 897                bnx2i_conn->gen_pdu.resp_buf = NULL;
 898        }
 899
 900        if (bnx2i_conn->gen_pdu.req_buf) {
 901                dma_free_coherent(&hba->pcidev->dev,
 902                                  ISCSI_DEF_MAX_RECV_SEG_LEN,
 903                                  bnx2i_conn->gen_pdu.req_buf,
 904                                  bnx2i_conn->gen_pdu.req_dma_addr);
 905                bnx2i_conn->gen_pdu.req_buf = NULL;
 906        }
 907}
 908
 909/**
 910 * bnx2i_conn_alloc_login_resources - alloc DMA resources for login/nop.
 911 * @hba:                pointer to adapter instance
 912 * @bnx2i_conn:         iscsi connection pointer
 913 *
 914 * Mgmt task DNA resources are allocated in this routine.
 915 */
 916static int bnx2i_conn_alloc_login_resources(struct bnx2i_hba *hba,
 917                                            struct bnx2i_conn *bnx2i_conn)
 918{
 919        /* Allocate memory for login request/response buffers */
 920        bnx2i_conn->gen_pdu.req_buf =
 921                dma_alloc_coherent(&hba->pcidev->dev,
 922                                   ISCSI_DEF_MAX_RECV_SEG_LEN,
 923                                   &bnx2i_conn->gen_pdu.req_dma_addr,
 924                                   GFP_KERNEL);
 925        if (bnx2i_conn->gen_pdu.req_buf == NULL)
 926                goto login_req_buf_failure;
 927
 928        bnx2i_conn->gen_pdu.req_buf_size = 0;
 929        bnx2i_conn->gen_pdu.req_wr_ptr = bnx2i_conn->gen_pdu.req_buf;
 930
 931        bnx2i_conn->gen_pdu.resp_buf =
 932                dma_alloc_coherent(&hba->pcidev->dev,
 933                                   ISCSI_DEF_MAX_RECV_SEG_LEN,
 934                                   &bnx2i_conn->gen_pdu.resp_dma_addr,
 935                                   GFP_KERNEL);
 936        if (bnx2i_conn->gen_pdu.resp_buf == NULL)
 937                goto login_resp_buf_failure;
 938
 939        bnx2i_conn->gen_pdu.resp_buf_size = ISCSI_DEF_MAX_RECV_SEG_LEN;
 940        bnx2i_conn->gen_pdu.resp_wr_ptr = bnx2i_conn->gen_pdu.resp_buf;
 941
 942        bnx2i_conn->gen_pdu.req_bd_tbl =
 943                dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
 944                                   &bnx2i_conn->gen_pdu.req_bd_dma, GFP_KERNEL);
 945        if (bnx2i_conn->gen_pdu.req_bd_tbl == NULL)
 946                goto login_req_bd_tbl_failure;
 947
 948        bnx2i_conn->gen_pdu.resp_bd_tbl =
 949                dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
 950                                   &bnx2i_conn->gen_pdu.resp_bd_dma,
 951                                   GFP_KERNEL);
 952        if (bnx2i_conn->gen_pdu.resp_bd_tbl == NULL)
 953                goto login_resp_bd_tbl_failure;
 954
 955        return 0;
 956
 957login_resp_bd_tbl_failure:
 958        dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
 959                          bnx2i_conn->gen_pdu.req_bd_tbl,
 960                          bnx2i_conn->gen_pdu.req_bd_dma);
 961        bnx2i_conn->gen_pdu.req_bd_tbl = NULL;
 962
 963login_req_bd_tbl_failure:
 964        dma_free_coherent(&hba->pcidev->dev, ISCSI_DEF_MAX_RECV_SEG_LEN,
 965                          bnx2i_conn->gen_pdu.resp_buf,
 966                          bnx2i_conn->gen_pdu.resp_dma_addr);
 967        bnx2i_conn->gen_pdu.resp_buf = NULL;
 968login_resp_buf_failure:
 969        dma_free_coherent(&hba->pcidev->dev, ISCSI_DEF_MAX_RECV_SEG_LEN,
 970                          bnx2i_conn->gen_pdu.req_buf,
 971                          bnx2i_conn->gen_pdu.req_dma_addr);
 972        bnx2i_conn->gen_pdu.req_buf = NULL;
 973login_req_buf_failure:
 974        iscsi_conn_printk(KERN_ERR, bnx2i_conn->cls_conn->dd_data,
 975                          "login resource alloc failed!!\n");
 976        return -ENOMEM;
 977
 978}
 979
 980
 981/**
 982 * bnx2i_iscsi_prep_generic_pdu_bd - prepares BD table.
 983 * @bnx2i_conn:         iscsi connection pointer
 984 *
 985 * Allocates buffers and BD tables before shipping requests to cnic
 986 *      for PDUs prepared by 'iscsid' daemon
 987 */
 988static void bnx2i_iscsi_prep_generic_pdu_bd(struct bnx2i_conn *bnx2i_conn)
 989{
 990        struct iscsi_bd *bd_tbl;
 991
 992        bd_tbl = (struct iscsi_bd *) bnx2i_conn->gen_pdu.req_bd_tbl;
 993
 994        bd_tbl->buffer_addr_hi =
 995                (u32) ((u64) bnx2i_conn->gen_pdu.req_dma_addr >> 32);
 996        bd_tbl->buffer_addr_lo = (u32) bnx2i_conn->gen_pdu.req_dma_addr;
 997        bd_tbl->buffer_length = bnx2i_conn->gen_pdu.req_wr_ptr -
 998                                bnx2i_conn->gen_pdu.req_buf;
 999        bd_tbl->reserved0 = 0;
1000        bd_tbl->flags = ISCSI_BD_LAST_IN_BD_CHAIN |
1001                        ISCSI_BD_FIRST_IN_BD_CHAIN;
1002
1003        bd_tbl = (struct iscsi_bd  *) bnx2i_conn->gen_pdu.resp_bd_tbl;
1004        bd_tbl->buffer_addr_hi = (u64) bnx2i_conn->gen_pdu.resp_dma_addr >> 32;
1005        bd_tbl->buffer_addr_lo = (u32) bnx2i_conn->gen_pdu.resp_dma_addr;
1006        bd_tbl->buffer_length = ISCSI_DEF_MAX_RECV_SEG_LEN;
1007        bd_tbl->reserved0 = 0;
1008        bd_tbl->flags = ISCSI_BD_LAST_IN_BD_CHAIN |
1009                        ISCSI_BD_FIRST_IN_BD_CHAIN;
1010}
1011
1012
1013/**
1014 * bnx2i_iscsi_send_generic_request - called to send mgmt tasks.
1015 * @task:       transport layer task pointer
1016 *
1017 * called to transmit PDUs prepared by the 'iscsid' daemon. iSCSI login,
1018 *      Nop-out and Logout requests flow through this path.
1019 */
1020static int bnx2i_iscsi_send_generic_request(struct iscsi_task *task)
1021{
1022        struct bnx2i_cmd *cmd = task->dd_data;
1023        struct bnx2i_conn *bnx2i_conn = cmd->conn;
1024        int rc = 0;
1025        char *buf;
1026        int data_len;
1027
1028        bnx2i_iscsi_prep_generic_pdu_bd(bnx2i_conn);
1029        switch (task->hdr->opcode & ISCSI_OPCODE_MASK) {
1030        case ISCSI_OP_LOGIN:
1031                bnx2i_send_iscsi_login(bnx2i_conn, task);
1032                break;
1033        case ISCSI_OP_NOOP_OUT:
1034                data_len = bnx2i_conn->gen_pdu.req_buf_size;
1035                buf = bnx2i_conn->gen_pdu.req_buf;
1036                if (data_len)
1037                        rc = bnx2i_send_iscsi_nopout(bnx2i_conn, task,
1038                                                     RESERVED_ITT,
1039                                                     buf, data_len, 1);
1040                else
1041                        rc = bnx2i_send_iscsi_nopout(bnx2i_conn, task,
1042                                                     RESERVED_ITT,
1043                                                     NULL, 0, 1);
1044                break;
1045        case ISCSI_OP_LOGOUT:
1046                rc = bnx2i_send_iscsi_logout(bnx2i_conn, task);
1047                break;
1048        case ISCSI_OP_SCSI_TMFUNC:
1049                rc = bnx2i_send_iscsi_tmf(bnx2i_conn, task);
1050                break;
1051        default:
1052                iscsi_conn_printk(KERN_ALERT, bnx2i_conn->cls_conn->dd_data,
1053                                  "send_gen: unsupported op 0x%x\n",
1054                                  task->hdr->opcode);
1055        }
1056        return rc;
1057}
1058
1059
1060/**********************************************************************
1061 *              SCSI-ML Interface
1062 **********************************************************************/
1063
1064/**
1065 * bnx2i_cpy_scsi_cdb - copies LUN & CDB fields in required format to sq wqe
1066 * @sc:         SCSI-ML command pointer
1067 * @cmd:        iscsi cmd pointer
1068 */
1069static void bnx2i_cpy_scsi_cdb(struct scsi_cmnd *sc, struct bnx2i_cmd *cmd)
1070{
1071        u32 dword;
1072        int lpcnt;
1073        u8 *srcp;
1074        u32 *dstp;
1075        u32 scsi_lun[2];
1076
1077        int_to_scsilun(sc->device->lun, (struct scsi_lun *) scsi_lun);
1078        cmd->req.lun[0] = be32_to_cpu(scsi_lun[0]);
1079        cmd->req.lun[1] = be32_to_cpu(scsi_lun[1]);
1080
1081        lpcnt = cmd->scsi_cmd->cmd_len / sizeof(dword);
1082        srcp = (u8 *) sc->cmnd;
1083        dstp = (u32 *) cmd->req.cdb;
1084        while (lpcnt--) {
1085                memcpy(&dword, (const void *) srcp, 4);
1086                *dstp = cpu_to_be32(dword);
1087                srcp += 4;
1088                dstp++;
1089        }
1090        if (sc->cmd_len & 0x3) {
1091                dword = (u32) srcp[0] | ((u32) srcp[1] << 8);
1092                *dstp = cpu_to_be32(dword);
1093        }
1094}
1095
1096static void bnx2i_cleanup_task(struct iscsi_task *task)
1097{
1098        struct iscsi_conn *conn = task->conn;
1099        struct bnx2i_conn *bnx2i_conn = conn->dd_data;
1100        struct bnx2i_hba *hba = bnx2i_conn->hba;
1101
1102        /*
1103         * mgmt task or cmd was never sent to us to transmit.
1104         */
1105        if (!task->sc || task->state == ISCSI_TASK_PENDING)
1106                return;
1107        /*
1108         * need to clean-up task context to claim dma buffers
1109         */
1110        if (task->state == ISCSI_TASK_ABRT_TMF) {
1111                bnx2i_send_cmd_cleanup_req(hba, task->dd_data);
1112
1113                spin_unlock_bh(&conn->session->lock);
1114                wait_for_completion_timeout(&bnx2i_conn->cmd_cleanup_cmpl,
1115                                msecs_to_jiffies(ISCSI_CMD_CLEANUP_TIMEOUT));
1116                spin_lock_bh(&conn->session->lock);
1117        }
1118        bnx2i_iscsi_unmap_sg_list(task->dd_data);
1119}
1120
1121/**
1122 * bnx2i_mtask_xmit - transmit mtask to chip for further processing
1123 * @conn:       transport layer conn structure pointer
1124 * @task:       transport layer command structure pointer
1125 */
1126static int
1127bnx2i_mtask_xmit(struct iscsi_conn *conn, struct iscsi_task *task)
1128{
1129        struct bnx2i_conn *bnx2i_conn = conn->dd_data;
1130        struct bnx2i_cmd *cmd = task->dd_data;
1131
1132        memset(bnx2i_conn->gen_pdu.req_buf, 0, ISCSI_DEF_MAX_RECV_SEG_LEN);
1133
1134        bnx2i_setup_cmd_wqe_template(cmd);
1135        bnx2i_conn->gen_pdu.req_buf_size = task->data_count;
1136        if (task->data_count) {
1137                memcpy(bnx2i_conn->gen_pdu.req_buf, task->data,
1138                       task->data_count);
1139                bnx2i_conn->gen_pdu.req_wr_ptr =
1140                        bnx2i_conn->gen_pdu.req_buf + task->data_count;
1141        }
1142        cmd->conn = conn->dd_data;
1143        cmd->scsi_cmd = NULL;
1144        return bnx2i_iscsi_send_generic_request(task);
1145}
1146
1147/**
1148 * bnx2i_task_xmit - transmit iscsi command to chip for further processing
1149 * @task:       transport layer command structure pointer
1150 *
1151 * maps SG buffers and send request to chip/firmware in the form of SQ WQE
1152 */
1153static int bnx2i_task_xmit(struct iscsi_task *task)
1154{
1155        struct iscsi_conn *conn = task->conn;
1156        struct iscsi_session *session = conn->session;
1157        struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session);
1158        struct bnx2i_hba *hba = iscsi_host_priv(shost);
1159        struct bnx2i_conn *bnx2i_conn = conn->dd_data;
1160        struct scsi_cmnd *sc = task->sc;
1161        struct bnx2i_cmd *cmd = task->dd_data;
1162        struct iscsi_cmd *hdr = (struct iscsi_cmd *) task->hdr;
1163
1164        if (!bnx2i_conn->is_bound)
1165                return -ENOTCONN;
1166
1167        /*
1168         * If there is no scsi_cmnd this must be a mgmt task
1169         */
1170        if (!sc)
1171                return bnx2i_mtask_xmit(conn, task);
1172
1173        bnx2i_setup_cmd_wqe_template(cmd);
1174        cmd->req.op_code = ISCSI_OP_SCSI_CMD;
1175        cmd->conn = bnx2i_conn;
1176        cmd->scsi_cmd = sc;
1177        cmd->req.total_data_transfer_length = scsi_bufflen(sc);
1178        cmd->req.cmd_sn = be32_to_cpu(hdr->cmdsn);
1179
1180        bnx2i_iscsi_map_sg_list(cmd);
1181        bnx2i_cpy_scsi_cdb(sc, cmd);
1182
1183        cmd->req.op_attr = ISCSI_ATTR_SIMPLE;
1184        if (sc->sc_data_direction == DMA_TO_DEVICE) {
1185                cmd->req.op_attr |= ISCSI_CMD_REQUEST_WRITE;
1186                cmd->req.itt = task->itt |
1187                        (ISCSI_TASK_TYPE_WRITE << ISCSI_CMD_REQUEST_TYPE_SHIFT);
1188                bnx2i_setup_write_cmd_bd_info(task);
1189        } else {
1190                if (scsi_bufflen(sc))
1191                        cmd->req.op_attr |= ISCSI_CMD_REQUEST_READ;
1192                cmd->req.itt = task->itt |
1193                        (ISCSI_TASK_TYPE_READ << ISCSI_CMD_REQUEST_TYPE_SHIFT);
1194        }
1195
1196        cmd->req.num_bds = cmd->io_tbl.bd_valid;
1197        if (!cmd->io_tbl.bd_valid) {
1198                cmd->req.bd_list_addr_lo = (u32) hba->mp_bd_dma;
1199                cmd->req.bd_list_addr_hi = (u32) ((u64) hba->mp_bd_dma >> 32);
1200                cmd->req.num_bds = 1;
1201        }
1202
1203        bnx2i_send_iscsi_scsicmd(bnx2i_conn, cmd);
1204        return 0;
1205}
1206
1207/**
1208 * bnx2i_session_create - create a new iscsi session
1209 * @cmds_max:           max commands supported
1210 * @qdepth:             scsi queue depth to support
1211 * @initial_cmdsn:      initial iscsi CMDSN to be used for this session
1212 *
1213 * Creates a new iSCSI session instance on given device.
1214 */
1215static struct iscsi_cls_session *
1216bnx2i_session_create(struct iscsi_endpoint *ep,
1217                     uint16_t cmds_max, uint16_t qdepth,
1218                     uint32_t initial_cmdsn)
1219{
1220        struct Scsi_Host *shost;
1221        struct iscsi_cls_session *cls_session;
1222        struct bnx2i_hba *hba;
1223        struct bnx2i_endpoint *bnx2i_ep;
1224
1225        if (!ep) {
1226                printk(KERN_ERR "bnx2i: missing ep.\n");
1227                return NULL;
1228        }
1229
1230        bnx2i_ep = ep->dd_data;
1231        shost = bnx2i_ep->hba->shost;
1232        hba = iscsi_host_priv(shost);
1233        if (bnx2i_adapter_ready(hba))
1234                return NULL;
1235
1236        /*
1237         * user can override hw limit as long as it is within
1238         * the min/max.
1239         */
1240        if (cmds_max > hba->max_sqes)
1241                cmds_max = hba->max_sqes;
1242        else if (cmds_max < BNX2I_SQ_WQES_MIN)
1243                cmds_max = BNX2I_SQ_WQES_MIN;
1244
1245        cls_session = iscsi_session_setup(&bnx2i_iscsi_transport, shost,
1246                                          cmds_max, 0, sizeof(struct bnx2i_cmd),
1247                                          initial_cmdsn, ISCSI_MAX_TARGET);
1248        if (!cls_session)
1249                return NULL;
1250
1251        if (bnx2i_setup_cmd_pool(hba, cls_session->dd_data))
1252                goto session_teardown;
1253        return cls_session;
1254
1255session_teardown:
1256        iscsi_session_teardown(cls_session);
1257        return NULL;
1258}
1259
1260
1261/**
1262 * bnx2i_session_destroy - destroys iscsi session
1263 * @cls_session:        pointer to iscsi cls session
1264 *
1265 * Destroys previously created iSCSI session instance and releases
1266 *      all resources held by it
1267 */
1268static void bnx2i_session_destroy(struct iscsi_cls_session *cls_session)
1269{
1270        struct iscsi_session *session = cls_session->dd_data;
1271        struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
1272        struct bnx2i_hba *hba = iscsi_host_priv(shost);
1273
1274        bnx2i_destroy_cmd_pool(hba, session);
1275        iscsi_session_teardown(cls_session);
1276}
1277
1278
1279/**
1280 * bnx2i_conn_create - create iscsi connection instance
1281 * @cls_session:        pointer to iscsi cls session
1282 * @cid:                iscsi cid as per rfc (not NX2's CID terminology)
1283 *
1284 * Creates a new iSCSI connection instance for a given session
1285 */
1286static struct iscsi_cls_conn *
1287bnx2i_conn_create(struct iscsi_cls_session *cls_session, uint32_t cid)
1288{
1289        struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
1290        struct bnx2i_hba *hba = iscsi_host_priv(shost);
1291        struct bnx2i_conn *bnx2i_conn;
1292        struct iscsi_cls_conn *cls_conn;
1293        struct iscsi_conn *conn;
1294
1295        cls_conn = iscsi_conn_setup(cls_session, sizeof(*bnx2i_conn),
1296                                    cid);
1297        if (!cls_conn)
1298                return NULL;
1299        conn = cls_conn->dd_data;
1300
1301        bnx2i_conn = conn->dd_data;
1302        bnx2i_conn->cls_conn = cls_conn;
1303        bnx2i_conn->hba = hba;
1304        /* 'ep' ptr will be assigned in bind() call */
1305        bnx2i_conn->ep = NULL;
1306        init_completion(&bnx2i_conn->cmd_cleanup_cmpl);
1307
1308        if (bnx2i_conn_alloc_login_resources(hba, bnx2i_conn)) {
1309                iscsi_conn_printk(KERN_ALERT, conn,
1310                                  "conn_new: login resc alloc failed!!\n");
1311                goto free_conn;
1312        }
1313
1314        return cls_conn;
1315
1316free_conn:
1317        iscsi_conn_teardown(cls_conn);
1318        return NULL;
1319}
1320
1321/**
1322 * bnx2i_conn_bind - binds iscsi sess, conn and ep objects together
1323 * @cls_session:        pointer to iscsi cls session
1324 * @cls_conn:           pointer to iscsi cls conn
1325 * @transport_fd:       64-bit EP handle
1326 * @is_leading:         leading connection on this session?
1327 *
1328 * Binds together iSCSI session instance, iSCSI connection instance
1329 *      and the TCP connection. This routine returns error code if
1330 *      TCP connection does not belong on the device iSCSI sess/conn
1331 *      is bound
1332 */
1333static int bnx2i_conn_bind(struct iscsi_cls_session *cls_session,
1334                           struct iscsi_cls_conn *cls_conn,
1335                           uint64_t transport_fd, int is_leading)
1336{
1337        struct iscsi_conn *conn = cls_conn->dd_data;
1338        struct bnx2i_conn *bnx2i_conn = conn->dd_data;
1339        struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
1340        struct bnx2i_hba *hba = iscsi_host_priv(shost);
1341        struct bnx2i_endpoint *bnx2i_ep;
1342        struct iscsi_endpoint *ep;
1343        int ret_code;
1344
1345        ep = iscsi_lookup_endpoint(transport_fd);
1346        if (!ep)
1347                return -EINVAL;
1348
1349        bnx2i_ep = ep->dd_data;
1350        if ((bnx2i_ep->state == EP_STATE_TCP_FIN_RCVD) ||
1351            (bnx2i_ep->state == EP_STATE_TCP_RST_RCVD))
1352                /* Peer disconnect via' FIN or RST */
1353                return -EINVAL;
1354
1355        if (iscsi_conn_bind(cls_session, cls_conn, is_leading))
1356                return -EINVAL;
1357
1358        if (bnx2i_ep->hba != hba) {
1359                /* Error - TCP connection does not belong to this device
1360                 */
1361                iscsi_conn_printk(KERN_ALERT, cls_conn->dd_data,
1362                                  "conn bind, ep=0x%p (%s) does not",
1363                                  bnx2i_ep, bnx2i_ep->hba->netdev->name);
1364                iscsi_conn_printk(KERN_ALERT, cls_conn->dd_data,
1365                                  "belong to hba (%s)\n",
1366                                  hba->netdev->name);
1367                return -EEXIST;
1368        }
1369
1370        bnx2i_ep->conn = bnx2i_conn;
1371        bnx2i_conn->ep = bnx2i_ep;
1372        bnx2i_conn->iscsi_conn_cid = bnx2i_ep->ep_iscsi_cid;
1373        bnx2i_conn->fw_cid = bnx2i_ep->ep_cid;
1374        bnx2i_conn->is_bound = 1;
1375
1376        ret_code = bnx2i_bind_conn_to_iscsi_cid(hba, bnx2i_conn,
1377                                                bnx2i_ep->ep_iscsi_cid);
1378
1379        /* 5706/5708/5709 FW takes RQ as full when initiated, but for 57710
1380         * driver needs to explicitly replenish RQ index during setup.
1381         */
1382        if (test_bit(BNX2I_NX2_DEV_57710, &bnx2i_ep->hba->cnic_dev_type))
1383                bnx2i_put_rq_buf(bnx2i_conn, 0);
1384
1385        bnx2i_arm_cq_event_coalescing(bnx2i_conn->ep, CNIC_ARM_CQE);
1386        return ret_code;
1387}
1388
1389
1390/**
1391 * bnx2i_conn_destroy - destroy iscsi connection instance & release resources
1392 * @cls_conn:   pointer to iscsi cls conn
1393 *
1394 * Destroy an iSCSI connection instance and release memory resources held by
1395 *      this connection
1396 */
1397static void bnx2i_conn_destroy(struct iscsi_cls_conn *cls_conn)
1398{
1399        struct iscsi_conn *conn = cls_conn->dd_data;
1400        struct bnx2i_conn *bnx2i_conn = conn->dd_data;
1401        struct Scsi_Host *shost;
1402        struct bnx2i_hba *hba;
1403
1404        shost = iscsi_session_to_shost(iscsi_conn_to_session(cls_conn));
1405        hba = iscsi_host_priv(shost);
1406
1407        bnx2i_conn_free_login_resources(hba, bnx2i_conn);
1408        iscsi_conn_teardown(cls_conn);
1409}
1410
1411
1412/**
1413 * bnx2i_conn_get_param - return iscsi connection parameter to caller
1414 * @cls_conn:   pointer to iscsi cls conn
1415 * @param:      parameter type identifier
1416 * @buf:        buffer pointer
1417 *
1418 * returns iSCSI connection parameters
1419 */
1420static int bnx2i_conn_get_param(struct iscsi_cls_conn *cls_conn,
1421                                enum iscsi_param param, char *buf)
1422{
1423        struct iscsi_conn *conn = cls_conn->dd_data;
1424        struct bnx2i_conn *bnx2i_conn = conn->dd_data;
1425        int len = 0;
1426
1427        switch (param) {
1428        case ISCSI_PARAM_CONN_PORT:
1429                if (bnx2i_conn->ep)
1430                        len = sprintf(buf, "%hu\n",
1431                                      bnx2i_conn->ep->cm_sk->dst_port);
1432                break;
1433        case ISCSI_PARAM_CONN_ADDRESS:
1434                if (bnx2i_conn->ep)
1435                        len = sprintf(buf, NIPQUAD_FMT "\n",
1436                                      NIPQUAD(bnx2i_conn->ep->cm_sk->dst_ip));
1437                break;
1438        default:
1439                return iscsi_conn_get_param(cls_conn, param, buf);
1440        }
1441
1442        return len;
1443}
1444
1445/**
1446 * bnx2i_host_get_param - returns host (adapter) related parameters
1447 * @shost:      scsi host pointer
1448 * @param:      parameter type identifier
1449 * @buf:        buffer pointer
1450 */
1451static int bnx2i_host_get_param(struct Scsi_Host *shost,
1452                                enum iscsi_host_param param, char *buf)
1453{
1454        struct bnx2i_hba *hba = iscsi_host_priv(shost);
1455        int len = 0;
1456
1457        switch (param) {
1458        case ISCSI_HOST_PARAM_HWADDRESS:
1459                len = sysfs_format_mac(buf, hba->cnic->mac_addr, 6);
1460                break;
1461        case ISCSI_HOST_PARAM_NETDEV_NAME:
1462                len = sprintf(buf, "%s\n", hba->netdev->name);
1463                break;
1464        default:
1465                return iscsi_host_get_param(shost, param, buf);
1466        }
1467        return len;
1468}
1469
1470/**
1471 * bnx2i_conn_start - completes iscsi connection migration to FFP
1472 * @cls_conn:   pointer to iscsi cls conn
1473 *
1474 * last call in FFP migration to handover iscsi conn to the driver
1475 */
1476static int bnx2i_conn_start(struct iscsi_cls_conn *cls_conn)
1477{
1478        struct iscsi_conn *conn = cls_conn->dd_data;
1479        struct bnx2i_conn *bnx2i_conn = conn->dd_data;
1480
1481        bnx2i_conn->ep->state = EP_STATE_ULP_UPDATE_START;
1482        bnx2i_update_iscsi_conn(conn);
1483
1484        /*
1485         * this should normally not sleep for a long time so it should
1486         * not disrupt the caller.
1487         */
1488        bnx2i_conn->ep->ofld_timer.expires = 1 * HZ + jiffies;
1489        bnx2i_conn->ep->ofld_timer.function = bnx2i_ep_ofld_timer;
1490        bnx2i_conn->ep->ofld_timer.data = (unsigned long) bnx2i_conn->ep;
1491        add_timer(&bnx2i_conn->ep->ofld_timer);
1492        /* update iSCSI context for this conn, wait for CNIC to complete */
1493        wait_event_interruptible(bnx2i_conn->ep->ofld_wait,
1494                        bnx2i_conn->ep->state != EP_STATE_ULP_UPDATE_START);
1495
1496        if (signal_pending(current))
1497                flush_signals(current);
1498        del_timer_sync(&bnx2i_conn->ep->ofld_timer);
1499
1500        iscsi_conn_start(cls_conn);
1501        return 0;
1502}
1503
1504
1505/**
1506 * bnx2i_conn_get_stats - returns iSCSI stats
1507 * @cls_conn:   pointer to iscsi cls conn
1508 * @stats:      pointer to iscsi statistic struct
1509 */
1510static void bnx2i_conn_get_stats(struct iscsi_cls_conn *cls_conn,
1511                                 struct iscsi_stats *stats)
1512{
1513        struct iscsi_conn *conn = cls_conn->dd_data;
1514
1515        stats->txdata_octets = conn->txdata_octets;
1516        stats->rxdata_octets = conn->rxdata_octets;
1517        stats->scsicmd_pdus = conn->scsicmd_pdus_cnt;
1518        stats->dataout_pdus = conn->dataout_pdus_cnt;
1519        stats->scsirsp_pdus = conn->scsirsp_pdus_cnt;
1520        stats->datain_pdus = conn->datain_pdus_cnt;
1521        stats->r2t_pdus = conn->r2t_pdus_cnt;
1522        stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt;
1523        stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt;
1524        stats->custom_length = 3;
1525        strcpy(stats->custom[2].desc, "eh_abort_cnt");
1526        stats->custom[2].value = conn->eh_abort_cnt;
1527        stats->digest_err = 0;
1528        stats->timeout_err = 0;
1529        stats->custom_length = 0;
1530}
1531
1532
1533/**
1534 * bnx2i_check_route - checks if target IP route belongs to one of NX2 devices
1535 * @dst_addr:   target IP address
1536 *
1537 * check if route resolves to BNX2 device
1538 */
1539static struct bnx2i_hba *bnx2i_check_route(struct sockaddr *dst_addr)
1540{
1541        struct sockaddr_in *desti = (struct sockaddr_in *) dst_addr;
1542        struct bnx2i_hba *hba;
1543        struct cnic_dev *cnic = NULL;
1544
1545        bnx2i_reg_dev_all();
1546
1547        hba = get_adapter_list_head();
1548        if (hba && hba->cnic)
1549                cnic = hba->cnic->cm_select_dev(desti, CNIC_ULP_ISCSI);
1550        if (!cnic) {
1551                printk(KERN_ALERT "bnx2i: no route,"
1552                       "can't connect using cnic\n");
1553                goto no_nx2_route;
1554        }
1555        hba = bnx2i_find_hba_for_cnic(cnic);
1556        if (!hba)
1557                goto no_nx2_route;
1558
1559        if (bnx2i_adapter_ready(hba)) {
1560                printk(KERN_ALERT "bnx2i: check route, hba not found\n");
1561                goto no_nx2_route;
1562        }
1563        if (hba->netdev->mtu > hba->mtu_supported) {
1564                printk(KERN_ALERT "bnx2i: %s network i/f mtu is set to %d\n",
1565                                  hba->netdev->name, hba->netdev->mtu);
1566                printk(KERN_ALERT "bnx2i: iSCSI HBA can support mtu of %d\n",
1567                                  hba->mtu_supported);
1568                goto no_nx2_route;
1569        }
1570        return hba;
1571no_nx2_route:
1572        return NULL;
1573}
1574
1575
1576/**
1577 * bnx2i_tear_down_conn - tear down iscsi/tcp connection and free resources
1578 * @hba:        pointer to adapter instance
1579 * @ep:         endpoint (transport indentifier) structure
1580 *
1581 * destroys cm_sock structure and on chip iscsi context
1582 */
1583static int bnx2i_tear_down_conn(struct bnx2i_hba *hba,
1584                                 struct bnx2i_endpoint *ep)
1585{
1586        if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic))
1587                hba->cnic->cm_destroy(ep->cm_sk);
1588
1589        if (test_bit(ADAPTER_STATE_GOING_DOWN, &ep->hba->adapter_state))
1590                ep->state = EP_STATE_DISCONN_COMPL;
1591
1592        if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type) &&
1593            ep->state == EP_STATE_DISCONN_TIMEDOUT) {
1594                printk(KERN_ALERT "bnx2i - ERROR - please submit GRC Dump,"
1595                                  " NW/PCIe trace, driver msgs to developers"
1596                                  " for analysis\n");
1597                return 1;
1598        }
1599
1600        ep->state = EP_STATE_CLEANUP_START;
1601        init_timer(&ep->ofld_timer);
1602        ep->ofld_timer.expires = 10*HZ + jiffies;
1603        ep->ofld_timer.function = bnx2i_ep_ofld_timer;
1604        ep->ofld_timer.data = (unsigned long) ep;
1605        add_timer(&ep->ofld_timer);
1606
1607        bnx2i_ep_destroy_list_add(hba, ep);
1608
1609        /* destroy iSCSI context, wait for it to complete */
1610        bnx2i_send_conn_destroy(hba, ep);
1611        wait_event_interruptible(ep->ofld_wait,
1612                                 (ep->state != EP_STATE_CLEANUP_START));
1613
1614        if (signal_pending(current))
1615                flush_signals(current);
1616        del_timer_sync(&ep->ofld_timer);
1617
1618        bnx2i_ep_destroy_list_del(hba, ep);
1619
1620        if (ep->state != EP_STATE_CLEANUP_CMPL)
1621                /* should never happen */
1622                printk(KERN_ALERT "bnx2i - conn destroy failed\n");
1623
1624        return 0;
1625}
1626
1627
1628/**
1629 * bnx2i_ep_connect - establish TCP connection to target portal
1630 * @shost:              scsi host
1631 * @dst_addr:           target IP address
1632 * @non_blocking:       blocking or non-blocking call
1633 *
1634 * this routine initiates the TCP/IP connection by invoking Option-2 i/f
1635 *      with l5_core and the CNIC. This is a multi-step process of resolving
1636 *      route to target, create a iscsi connection context, handshaking with
1637 *      CNIC module to create/initialize the socket struct and finally
1638 *      sending down option-2 request to complete TCP 3-way handshake
1639 */
1640static struct iscsi_endpoint *bnx2i_ep_connect(struct Scsi_Host *shost,
1641                                               struct sockaddr *dst_addr,
1642                                               int non_blocking)
1643{
1644        u32 iscsi_cid = BNX2I_CID_RESERVED;
1645        struct sockaddr_in *desti = (struct sockaddr_in *) dst_addr;
1646        struct sockaddr_in6 *desti6;
1647        struct bnx2i_endpoint *bnx2i_ep;
1648        struct bnx2i_hba *hba;
1649        struct cnic_dev *cnic;
1650        struct cnic_sockaddr saddr;
1651        struct iscsi_endpoint *ep;
1652        int rc = 0;
1653
1654        if (shost) {
1655                /* driver is given scsi host to work with */
1656                hba = iscsi_host_priv(shost);
1657                /* Register the device with cnic if not already done so */
1658                bnx2i_register_device(hba);
1659        } else
1660                /*
1661                 * check if the given destination can be reached through
1662                 * a iscsi capable NetXtreme2 device
1663                 */
1664                hba = bnx2i_check_route(dst_addr);
1665
1666        if (!hba) {
1667                rc = -ENOMEM;
1668                goto check_busy;
1669        }
1670
1671        cnic = hba->cnic;
1672        ep = bnx2i_alloc_ep(hba);
1673        if (!ep) {
1674                rc = -ENOMEM;
1675                goto check_busy;
1676        }
1677        bnx2i_ep = ep->dd_data;
1678
1679        mutex_lock(&hba->net_dev_lock);
1680        if (bnx2i_adapter_ready(hba)) {
1681                rc = -EPERM;
1682                goto net_if_down;
1683        }
1684
1685        bnx2i_ep->num_active_cmds = 0;
1686        iscsi_cid = bnx2i_alloc_iscsi_cid(hba);
1687        if (iscsi_cid == -1) {
1688                printk(KERN_ALERT "alloc_ep: unable to allocate iscsi cid\n");
1689                rc = -ENOMEM;
1690                goto iscsi_cid_err;
1691        }
1692        bnx2i_ep->hba_age = hba->age;
1693
1694        rc = bnx2i_alloc_qp_resc(hba, bnx2i_ep);
1695        if (rc != 0) {
1696                printk(KERN_ALERT "bnx2i: ep_conn, alloc QP resc error\n");
1697                rc = -ENOMEM;
1698                goto qp_resc_err;
1699        }
1700
1701        bnx2i_ep->ep_iscsi_cid = (u16)iscsi_cid;
1702        bnx2i_ep->state = EP_STATE_OFLD_START;
1703        bnx2i_ep_ofld_list_add(hba, bnx2i_ep);
1704
1705        init_timer(&bnx2i_ep->ofld_timer);
1706        bnx2i_ep->ofld_timer.expires = 2 * HZ + jiffies;
1707        bnx2i_ep->ofld_timer.function = bnx2i_ep_ofld_timer;
1708        bnx2i_ep->ofld_timer.data = (unsigned long) bnx2i_ep;
1709        add_timer(&bnx2i_ep->ofld_timer);
1710
1711        bnx2i_send_conn_ofld_req(hba, bnx2i_ep);
1712
1713        /* Wait for CNIC hardware to setup conn context and return 'cid' */
1714        wait_event_interruptible(bnx2i_ep->ofld_wait,
1715                                 bnx2i_ep->state != EP_STATE_OFLD_START);
1716
1717        if (signal_pending(current))
1718                flush_signals(current);
1719        del_timer_sync(&bnx2i_ep->ofld_timer);
1720
1721        bnx2i_ep_ofld_list_del(hba, bnx2i_ep);
1722
1723        if (bnx2i_ep->state != EP_STATE_OFLD_COMPL) {
1724                rc = -ENOSPC;
1725                goto conn_failed;
1726        }
1727
1728        rc = cnic->cm_create(cnic, CNIC_ULP_ISCSI, bnx2i_ep->ep_cid,
1729                             iscsi_cid, &bnx2i_ep->cm_sk, bnx2i_ep);
1730        if (rc) {
1731                rc = -EINVAL;
1732                goto conn_failed;
1733        }
1734
1735        bnx2i_ep->cm_sk->rcv_buf = 256 * 1024;
1736        bnx2i_ep->cm_sk->snd_buf = 256 * 1024;
1737        clear_bit(SK_TCP_TIMESTAMP, &bnx2i_ep->cm_sk->tcp_flags);
1738
1739        memset(&saddr, 0, sizeof(saddr));
1740        if (dst_addr->sa_family == AF_INET) {
1741                desti = (struct sockaddr_in *) dst_addr;
1742                saddr.remote.v4 = *desti;
1743                saddr.local.v4.sin_family = desti->sin_family;
1744        } else if (dst_addr->sa_family == AF_INET6) {
1745                desti6 = (struct sockaddr_in6 *) dst_addr;
1746                saddr.remote.v6 = *desti6;
1747                saddr.local.v6.sin6_family = desti6->sin6_family;
1748        }
1749
1750        bnx2i_ep->timestamp = jiffies;
1751        bnx2i_ep->state = EP_STATE_CONNECT_START;
1752        if (!test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) {
1753                rc = -EINVAL;
1754                goto conn_failed;
1755        } else
1756                rc = cnic->cm_connect(bnx2i_ep->cm_sk, &saddr);
1757
1758        if (rc)
1759                goto release_ep;
1760
1761        if (bnx2i_map_ep_dbell_regs(bnx2i_ep))
1762                goto release_ep;
1763        mutex_unlock(&hba->net_dev_lock);
1764        return ep;
1765
1766release_ep:
1767        if (bnx2i_tear_down_conn(hba, bnx2i_ep)) {
1768                mutex_unlock(&hba->net_dev_lock);
1769                return ERR_PTR(rc);
1770        }
1771conn_failed:
1772net_if_down:
1773iscsi_cid_err:
1774        bnx2i_free_qp_resc(hba, bnx2i_ep);
1775qp_resc_err:
1776        bnx2i_free_ep(ep);
1777        mutex_unlock(&hba->net_dev_lock);
1778check_busy:
1779        bnx2i_unreg_dev_all();
1780        return ERR_PTR(rc);
1781}
1782
1783
1784/**
1785 * bnx2i_ep_poll - polls for TCP connection establishement
1786 * @ep:                 TCP connection (endpoint) handle
1787 * @timeout_ms:         timeout value in milli secs
1788 *
1789 * polls for TCP connect request to complete
1790 */
1791static int bnx2i_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
1792{
1793        struct bnx2i_endpoint *bnx2i_ep;
1794        int rc = 0;
1795
1796        bnx2i_ep = ep->dd_data;
1797        if ((bnx2i_ep->state == EP_STATE_IDLE) ||
1798            (bnx2i_ep->state == EP_STATE_CONNECT_FAILED) ||
1799            (bnx2i_ep->state == EP_STATE_OFLD_FAILED))
1800                return -1;
1801        if (bnx2i_ep->state == EP_STATE_CONNECT_COMPL)
1802                return 1;
1803
1804        rc = wait_event_interruptible_timeout(bnx2i_ep->ofld_wait,
1805                                              ((bnx2i_ep->state ==
1806                                                EP_STATE_OFLD_FAILED) ||
1807                                               (bnx2i_ep->state ==
1808                                                EP_STATE_CONNECT_FAILED) ||
1809                                               (bnx2i_ep->state ==
1810                                                EP_STATE_CONNECT_COMPL)),
1811                                              msecs_to_jiffies(timeout_ms));
1812        if (!rc || (bnx2i_ep->state == EP_STATE_OFLD_FAILED))
1813                rc = -1;
1814
1815        if (rc > 0)
1816                return 1;
1817        else if (!rc)
1818                return 0;       /* timeout */
1819        else
1820                return rc;
1821}
1822
1823
1824/**
1825 * bnx2i_ep_tcp_conn_active - check EP state transition
1826 * @ep:         endpoint pointer
1827 *
1828 * check if underlying TCP connection is active
1829 */
1830static int bnx2i_ep_tcp_conn_active(struct bnx2i_endpoint *bnx2i_ep)
1831{
1832        int ret;
1833        int cnic_dev_10g = 0;
1834
1835        if (test_bit(BNX2I_NX2_DEV_57710, &bnx2i_ep->hba->cnic_dev_type))
1836                cnic_dev_10g = 1;
1837
1838        switch (bnx2i_ep->state) {
1839        case EP_STATE_CONNECT_START:
1840        case EP_STATE_CLEANUP_FAILED:
1841        case EP_STATE_OFLD_FAILED:
1842        case EP_STATE_DISCONN_TIMEDOUT:
1843                ret = 0;
1844                break;
1845        case EP_STATE_CONNECT_COMPL:
1846        case EP_STATE_ULP_UPDATE_START:
1847        case EP_STATE_ULP_UPDATE_COMPL:
1848        case EP_STATE_TCP_FIN_RCVD:
1849        case EP_STATE_ULP_UPDATE_FAILED:
1850                ret = 1;
1851                break;
1852        case EP_STATE_TCP_RST_RCVD:
1853                ret = 0;
1854                break;
1855        case EP_STATE_CONNECT_FAILED:
1856                if (cnic_dev_10g)
1857                        ret = 1;
1858                else
1859                        ret = 0;
1860                break;
1861        default:
1862                ret = 0;
1863        }
1864
1865        return ret;
1866}
1867
1868
1869/**
1870 * bnx2i_ep_disconnect - executes TCP connection teardown process
1871 * @ep:         TCP connection (endpoint) handle
1872 *
1873 * executes  TCP connection teardown process
1874 */
1875static void bnx2i_ep_disconnect(struct iscsi_endpoint *ep)
1876{
1877        struct bnx2i_endpoint *bnx2i_ep;
1878        struct bnx2i_conn *bnx2i_conn = NULL;
1879        struct iscsi_session *session = NULL;
1880        struct iscsi_conn *conn;
1881        struct cnic_dev *cnic;
1882        struct bnx2i_hba *hba;
1883
1884        bnx2i_ep = ep->dd_data;
1885
1886        /* driver should not attempt connection cleanup untill TCP_CONNECT
1887         * completes either successfully or fails. Timeout is 9-secs, so
1888         * wait for it to complete
1889         */
1890        while ((bnx2i_ep->state == EP_STATE_CONNECT_START) &&
1891                !time_after(jiffies, bnx2i_ep->timestamp + (12 * HZ)))
1892                msleep(250);
1893
1894        if (bnx2i_ep->conn) {
1895                bnx2i_conn = bnx2i_ep->conn;
1896                conn = bnx2i_conn->cls_conn->dd_data;
1897                session = conn->session;
1898
1899                spin_lock_bh(&session->lock);
1900                bnx2i_conn->is_bound = 0;
1901                spin_unlock_bh(&session->lock);
1902        }
1903
1904        hba = bnx2i_ep->hba;
1905        if (bnx2i_ep->state == EP_STATE_IDLE)
1906                goto return_bnx2i_ep;
1907        cnic = hba->cnic;
1908
1909        mutex_lock(&hba->net_dev_lock);
1910
1911        if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state))
1912                goto free_resc;
1913        if (bnx2i_ep->hba_age != hba->age)
1914                goto free_resc;
1915
1916        if (!bnx2i_ep_tcp_conn_active(bnx2i_ep))
1917                goto destory_conn;
1918
1919        bnx2i_ep->state = EP_STATE_DISCONN_START;
1920
1921        init_timer(&bnx2i_ep->ofld_timer);
1922        bnx2i_ep->ofld_timer.expires = 10*HZ + jiffies;
1923        bnx2i_ep->ofld_timer.function = bnx2i_ep_ofld_timer;
1924        bnx2i_ep->ofld_timer.data = (unsigned long) bnx2i_ep;
1925        add_timer(&bnx2i_ep->ofld_timer);
1926
1927        if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) {
1928                int close = 0;
1929
1930                if (session) {
1931                        spin_lock_bh(&session->lock);
1932                        if (session->state == ISCSI_STATE_LOGGING_OUT)
1933                                close = 1;
1934                        spin_unlock_bh(&session->lock);
1935                }
1936                if (close)
1937                        cnic->cm_close(bnx2i_ep->cm_sk);
1938                else
1939                        cnic->cm_abort(bnx2i_ep->cm_sk);
1940        } else
1941                goto free_resc;
1942
1943        /* wait for option-2 conn teardown */
1944        wait_event_interruptible(bnx2i_ep->ofld_wait,
1945                                 bnx2i_ep->state != EP_STATE_DISCONN_START);
1946
1947        if (signal_pending(current))
1948                flush_signals(current);
1949        del_timer_sync(&bnx2i_ep->ofld_timer);
1950
1951destory_conn:
1952        if (bnx2i_tear_down_conn(hba, bnx2i_ep)) {
1953                mutex_unlock(&hba->net_dev_lock);
1954                return;
1955        }
1956free_resc:
1957        mutex_unlock(&hba->net_dev_lock);
1958        bnx2i_free_qp_resc(hba, bnx2i_ep);
1959return_bnx2i_ep:
1960        if (bnx2i_conn)
1961                bnx2i_conn->ep = NULL;
1962
1963        bnx2i_free_ep(ep);
1964
1965        if (!hba->ofld_conns_active)
1966                bnx2i_unreg_dev_all();
1967}
1968
1969
1970/**
1971 * bnx2i_nl_set_path - ISCSI_UEVENT_PATH_UPDATE user message handler
1972 * @buf:        pointer to buffer containing iscsi path message
1973 *
1974 */
1975static int bnx2i_nl_set_path(struct Scsi_Host *shost, struct iscsi_path *params)
1976{
1977        struct bnx2i_hba *hba = iscsi_host_priv(shost);
1978        char *buf = (char *) params;
1979        u16 len = sizeof(*params);
1980
1981        /* handled by cnic driver */
1982        hba->cnic->iscsi_nl_msg_recv(hba->cnic, ISCSI_UEVENT_PATH_UPDATE, buf,
1983                                     len);
1984
1985        return 0;
1986}
1987
1988
1989/*
1990 * 'Scsi_Host_Template' structure and 'iscsi_tranport' structure template
1991 * used while registering with the scsi host and iSCSI transport module.
1992 */
1993static struct scsi_host_template bnx2i_host_template = {
1994        .module                 = THIS_MODULE,
1995        .name                   = "Broadcom Offload iSCSI Initiator",
1996        .proc_name              = "bnx2i",
1997        .queuecommand           = iscsi_queuecommand,
1998        .eh_abort_handler       = iscsi_eh_abort,
1999        .eh_device_reset_handler = iscsi_eh_device_reset,
2000        .eh_target_reset_handler = iscsi_eh_target_reset,
2001        .can_queue              = 1024,
2002        .max_sectors            = 127,
2003        .cmd_per_lun            = 32,
2004        .this_id                = -1,
2005        .use_clustering         = ENABLE_CLUSTERING,
2006        .sg_tablesize           = ISCSI_MAX_BDS_PER_CMD,
2007        .shost_attrs            = bnx2i_dev_attributes,
2008};
2009
2010struct iscsi_transport bnx2i_iscsi_transport = {
2011        .owner                  = THIS_MODULE,
2012        .name                   = "bnx2i",
2013        .caps                   = CAP_RECOVERY_L0 | CAP_HDRDGST |
2014                                  CAP_MULTI_R2T | CAP_DATADGST |
2015                                  CAP_DATA_PATH_OFFLOAD,
2016        .param_mask             = ISCSI_MAX_RECV_DLENGTH |
2017                                  ISCSI_MAX_XMIT_DLENGTH |
2018                                  ISCSI_HDRDGST_EN |
2019                                  ISCSI_DATADGST_EN |
2020                                  ISCSI_INITIAL_R2T_EN |
2021                                  ISCSI_MAX_R2T |
2022                                  ISCSI_IMM_DATA_EN |
2023                                  ISCSI_FIRST_BURST |
2024                                  ISCSI_MAX_BURST |
2025                                  ISCSI_PDU_INORDER_EN |
2026                                  ISCSI_DATASEQ_INORDER_EN |
2027                                  ISCSI_ERL |
2028                                  ISCSI_CONN_PORT |
2029                                  ISCSI_CONN_ADDRESS |
2030                                  ISCSI_EXP_STATSN |
2031                                  ISCSI_PERSISTENT_PORT |
2032                                  ISCSI_PERSISTENT_ADDRESS |
2033                                  ISCSI_TARGET_NAME | ISCSI_TPGT |
2034                                  ISCSI_USERNAME | ISCSI_PASSWORD |
2035                                  ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN |
2036                                  ISCSI_FAST_ABORT | ISCSI_ABORT_TMO |
2037                                  ISCSI_LU_RESET_TMO |
2038                                  ISCSI_PING_TMO | ISCSI_RECV_TMO |
2039                                  ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME,
2040        .host_param_mask        = ISCSI_HOST_HWADDRESS | ISCSI_HOST_NETDEV_NAME,
2041        .create_session         = bnx2i_session_create,
2042        .destroy_session        = bnx2i_session_destroy,
2043        .create_conn            = bnx2i_conn_create,
2044        .bind_conn              = bnx2i_conn_bind,
2045        .destroy_conn           = bnx2i_conn_destroy,
2046        .set_param              = iscsi_set_param,
2047        .get_conn_param         = bnx2i_conn_get_param,
2048        .get_session_param      = iscsi_session_get_param,
2049        .get_host_param         = bnx2i_host_get_param,
2050        .start_conn             = bnx2i_conn_start,
2051        .stop_conn              = iscsi_conn_stop,
2052        .send_pdu               = iscsi_conn_send_pdu,
2053        .xmit_task              = bnx2i_task_xmit,
2054        .get_stats              = bnx2i_conn_get_stats,
2055        /* TCP connect - disconnect - option-2 interface calls */
2056        .ep_connect             = bnx2i_ep_connect,
2057        .ep_poll                = bnx2i_ep_poll,
2058        .ep_disconnect          = bnx2i_ep_disconnect,
2059        .set_path               = bnx2i_nl_set_path,
2060        /* Error recovery timeout call */
2061        .session_recovery_timedout = iscsi_session_recovery_timedout,
2062        .cleanup_task           = bnx2i_cleanup_task,
2063};
2064