linux/drivers/scsi/qla4xxx/ql4_bsg.c
<<
>>
Prefs
   1/*
   2 * QLogic iSCSI HBA Driver
   3 * Copyright (c) 2011-2013 QLogic Corporation
   4 *
   5 * See LICENSE.qla4xxx for copyright and licensing details.
   6 */
   7
   8#include "ql4_def.h"
   9#include "ql4_glbl.h"
  10#include "ql4_bsg.h"
  11
  12static int
  13qla4xxx_read_flash(struct bsg_job *bsg_job)
  14{
  15        struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
  16        struct scsi_qla_host *ha = to_qla_host(host);
  17        struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
  18        struct iscsi_bsg_request *bsg_req = bsg_job->request;
  19        uint32_t offset = 0;
  20        uint32_t length = 0;
  21        dma_addr_t flash_dma;
  22        uint8_t *flash = NULL;
  23        int rval = -EINVAL;
  24
  25        bsg_reply->reply_payload_rcv_len = 0;
  26
  27        if (unlikely(pci_channel_offline(ha->pdev)))
  28                goto leave;
  29
  30        if (ql4xxx_reset_active(ha)) {
  31                ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
  32                rval = -EBUSY;
  33                goto leave;
  34        }
  35
  36        if (ha->flash_state != QLFLASH_WAITING) {
  37                ql4_printk(KERN_ERR, ha, "%s: another flash operation "
  38                           "active\n", __func__);
  39                rval = -EBUSY;
  40                goto leave;
  41        }
  42
  43        ha->flash_state = QLFLASH_READING;
  44        offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
  45        length = bsg_job->reply_payload.payload_len;
  46
  47        flash = dma_alloc_coherent(&ha->pdev->dev, length, &flash_dma,
  48                                   GFP_KERNEL);
  49        if (!flash) {
  50                ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash "
  51                           "data\n", __func__);
  52                rval = -ENOMEM;
  53                goto leave;
  54        }
  55
  56        rval = qla4xxx_get_flash(ha, flash_dma, offset, length);
  57        if (rval) {
  58                ql4_printk(KERN_ERR, ha, "%s: get flash failed\n", __func__);
  59                bsg_reply->result = DID_ERROR << 16;
  60                rval = -EIO;
  61        } else {
  62                bsg_reply->reply_payload_rcv_len =
  63                        sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
  64                                            bsg_job->reply_payload.sg_cnt,
  65                                            flash, length);
  66                bsg_reply->result = DID_OK << 16;
  67        }
  68
  69        bsg_job_done(bsg_job, bsg_reply->result,
  70                     bsg_reply->reply_payload_rcv_len);
  71        dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma);
  72leave:
  73        ha->flash_state = QLFLASH_WAITING;
  74        return rval;
  75}
  76
  77static int
  78qla4xxx_update_flash(struct bsg_job *bsg_job)
  79{
  80        struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
  81        struct scsi_qla_host *ha = to_qla_host(host);
  82        struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
  83        struct iscsi_bsg_request *bsg_req = bsg_job->request;
  84        uint32_t length = 0;
  85        uint32_t offset = 0;
  86        uint32_t options = 0;
  87        dma_addr_t flash_dma;
  88        uint8_t *flash = NULL;
  89        int rval = -EINVAL;
  90
  91        bsg_reply->reply_payload_rcv_len = 0;
  92
  93        if (unlikely(pci_channel_offline(ha->pdev)))
  94                goto leave;
  95
  96        if (ql4xxx_reset_active(ha)) {
  97                ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
  98                rval = -EBUSY;
  99                goto leave;
 100        }
 101
 102        if (ha->flash_state != QLFLASH_WAITING) {
 103                ql4_printk(KERN_ERR, ha, "%s: another flash operation "
 104                           "active\n", __func__);
 105                rval = -EBUSY;
 106                goto leave;
 107        }
 108
 109        ha->flash_state = QLFLASH_WRITING;
 110        length = bsg_job->request_payload.payload_len;
 111        offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
 112        options = bsg_req->rqst_data.h_vendor.vendor_cmd[2];
 113
 114        flash = dma_alloc_coherent(&ha->pdev->dev, length, &flash_dma,
 115                                   GFP_KERNEL);
 116        if (!flash) {
 117                ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash "
 118                           "data\n", __func__);
 119                rval = -ENOMEM;
 120                goto leave;
 121        }
 122
 123        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
 124                          bsg_job->request_payload.sg_cnt, flash, length);
 125
 126        rval = qla4xxx_set_flash(ha, flash_dma, offset, length, options);
 127        if (rval) {
 128                ql4_printk(KERN_ERR, ha, "%s: set flash failed\n", __func__);
 129                bsg_reply->result = DID_ERROR << 16;
 130                rval = -EIO;
 131        } else
 132                bsg_reply->result = DID_OK << 16;
 133
 134        bsg_job_done(bsg_job, bsg_reply->result,
 135                     bsg_reply->reply_payload_rcv_len);
 136        dma_free_coherent(&ha->pdev->dev, length, flash, flash_dma);
 137leave:
 138        ha->flash_state = QLFLASH_WAITING;
 139        return rval;
 140}
 141
 142static int
 143qla4xxx_get_acb_state(struct bsg_job *bsg_job)
 144{
 145        struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
 146        struct scsi_qla_host *ha = to_qla_host(host);
 147        struct iscsi_bsg_request *bsg_req = bsg_job->request;
 148        struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
 149        uint32_t status[MBOX_REG_COUNT];
 150        uint32_t acb_idx;
 151        uint32_t ip_idx;
 152        int rval = -EINVAL;
 153
 154        bsg_reply->reply_payload_rcv_len = 0;
 155
 156        if (unlikely(pci_channel_offline(ha->pdev)))
 157                goto leave;
 158
 159        /* Only 4022 and above adapters are supported */
 160        if (is_qla4010(ha))
 161                goto leave;
 162
 163        if (ql4xxx_reset_active(ha)) {
 164                ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
 165                rval = -EBUSY;
 166                goto leave;
 167        }
 168
 169        if (bsg_job->reply_payload.payload_len < sizeof(status)) {
 170                ql4_printk(KERN_ERR, ha, "%s: invalid payload len %d\n",
 171                           __func__, bsg_job->reply_payload.payload_len);
 172                rval = -EINVAL;
 173                goto leave;
 174        }
 175
 176        acb_idx = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
 177        ip_idx = bsg_req->rqst_data.h_vendor.vendor_cmd[2];
 178
 179        rval = qla4xxx_get_ip_state(ha, acb_idx, ip_idx, status);
 180        if (rval) {
 181                ql4_printk(KERN_ERR, ha, "%s: get ip state failed\n",
 182                           __func__);
 183                bsg_reply->result = DID_ERROR << 16;
 184                rval = -EIO;
 185        } else {
 186                bsg_reply->reply_payload_rcv_len =
 187                        sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
 188                                            bsg_job->reply_payload.sg_cnt,
 189                                            status, sizeof(status));
 190                bsg_reply->result = DID_OK << 16;
 191        }
 192
 193        bsg_job_done(bsg_job, bsg_reply->result,
 194                     bsg_reply->reply_payload_rcv_len);
 195leave:
 196        return rval;
 197}
 198
 199static int
 200qla4xxx_read_nvram(struct bsg_job *bsg_job)
 201{
 202        struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
 203        struct scsi_qla_host *ha = to_qla_host(host);
 204        struct iscsi_bsg_request *bsg_req = bsg_job->request;
 205        struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
 206        uint32_t offset = 0;
 207        uint32_t len = 0;
 208        uint32_t total_len = 0;
 209        dma_addr_t nvram_dma;
 210        uint8_t *nvram = NULL;
 211        int rval = -EINVAL;
 212
 213        bsg_reply->reply_payload_rcv_len = 0;
 214
 215        if (unlikely(pci_channel_offline(ha->pdev)))
 216                goto leave;
 217
 218        /* Only 40xx adapters are supported */
 219        if (!(is_qla4010(ha) || is_qla4022(ha) || is_qla4032(ha)))
 220                goto leave;
 221
 222        if (ql4xxx_reset_active(ha)) {
 223                ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
 224                rval = -EBUSY;
 225                goto leave;
 226        }
 227
 228        offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
 229        len = bsg_job->reply_payload.payload_len;
 230        total_len = offset + len;
 231
 232        /* total len should not be greater than max NVRAM size */
 233        if ((is_qla4010(ha) && total_len > QL4010_NVRAM_SIZE) ||
 234            ((is_qla4022(ha) || is_qla4032(ha)) &&
 235             total_len > QL40X2_NVRAM_SIZE)) {
 236                ql4_printk(KERN_ERR, ha, "%s: offset+len greater than max"
 237                           " nvram size, offset=%d len=%d\n",
 238                           __func__, offset, len);
 239                goto leave;
 240        }
 241
 242        nvram = dma_alloc_coherent(&ha->pdev->dev, len, &nvram_dma,
 243                                   GFP_KERNEL);
 244        if (!nvram) {
 245                ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for nvram "
 246                           "data\n", __func__);
 247                rval = -ENOMEM;
 248                goto leave;
 249        }
 250
 251        rval = qla4xxx_get_nvram(ha, nvram_dma, offset, len);
 252        if (rval) {
 253                ql4_printk(KERN_ERR, ha, "%s: get nvram failed\n", __func__);
 254                bsg_reply->result = DID_ERROR << 16;
 255                rval = -EIO;
 256        } else {
 257                bsg_reply->reply_payload_rcv_len =
 258                        sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
 259                                            bsg_job->reply_payload.sg_cnt,
 260                                            nvram, len);
 261                bsg_reply->result = DID_OK << 16;
 262        }
 263
 264        bsg_job_done(bsg_job, bsg_reply->result,
 265                     bsg_reply->reply_payload_rcv_len);
 266        dma_free_coherent(&ha->pdev->dev, len, nvram, nvram_dma);
 267leave:
 268        return rval;
 269}
 270
 271static int
 272qla4xxx_update_nvram(struct bsg_job *bsg_job)
 273{
 274        struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
 275        struct scsi_qla_host *ha = to_qla_host(host);
 276        struct iscsi_bsg_request *bsg_req = bsg_job->request;
 277        struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
 278        uint32_t offset = 0;
 279        uint32_t len = 0;
 280        uint32_t total_len = 0;
 281        dma_addr_t nvram_dma;
 282        uint8_t *nvram = NULL;
 283        int rval = -EINVAL;
 284
 285        bsg_reply->reply_payload_rcv_len = 0;
 286
 287        if (unlikely(pci_channel_offline(ha->pdev)))
 288                goto leave;
 289
 290        if (!(is_qla4010(ha) || is_qla4022(ha) || is_qla4032(ha)))
 291                goto leave;
 292
 293        if (ql4xxx_reset_active(ha)) {
 294                ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
 295                rval = -EBUSY;
 296                goto leave;
 297        }
 298
 299        offset = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
 300        len = bsg_job->request_payload.payload_len;
 301        total_len = offset + len;
 302
 303        /* total len should not be greater than max NVRAM size */
 304        if ((is_qla4010(ha) && total_len > QL4010_NVRAM_SIZE) ||
 305            ((is_qla4022(ha) || is_qla4032(ha)) &&
 306             total_len > QL40X2_NVRAM_SIZE)) {
 307                ql4_printk(KERN_ERR, ha, "%s: offset+len greater than max"
 308                           " nvram size, offset=%d len=%d\n",
 309                           __func__, offset, len);
 310                goto leave;
 311        }
 312
 313        nvram = dma_alloc_coherent(&ha->pdev->dev, len, &nvram_dma,
 314                                   GFP_KERNEL);
 315        if (!nvram) {
 316                ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for flash "
 317                           "data\n", __func__);
 318                rval = -ENOMEM;
 319                goto leave;
 320        }
 321
 322        sg_copy_to_buffer(bsg_job->request_payload.sg_list,
 323                          bsg_job->request_payload.sg_cnt, nvram, len);
 324
 325        rval = qla4xxx_set_nvram(ha, nvram_dma, offset, len);
 326        if (rval) {
 327                ql4_printk(KERN_ERR, ha, "%s: set nvram failed\n", __func__);
 328                bsg_reply->result = DID_ERROR << 16;
 329                rval = -EIO;
 330        } else
 331                bsg_reply->result = DID_OK << 16;
 332
 333        bsg_job_done(bsg_job, bsg_reply->result,
 334                     bsg_reply->reply_payload_rcv_len);
 335        dma_free_coherent(&ha->pdev->dev, len, nvram, nvram_dma);
 336leave:
 337        return rval;
 338}
 339
 340static int
 341qla4xxx_restore_defaults(struct bsg_job *bsg_job)
 342{
 343        struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
 344        struct scsi_qla_host *ha = to_qla_host(host);
 345        struct iscsi_bsg_request *bsg_req = bsg_job->request;
 346        struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
 347        uint32_t region = 0;
 348        uint32_t field0 = 0;
 349        uint32_t field1 = 0;
 350        int rval = -EINVAL;
 351
 352        bsg_reply->reply_payload_rcv_len = 0;
 353
 354        if (unlikely(pci_channel_offline(ha->pdev)))
 355                goto leave;
 356
 357        if (is_qla4010(ha))
 358                goto leave;
 359
 360        if (ql4xxx_reset_active(ha)) {
 361                ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
 362                rval = -EBUSY;
 363                goto leave;
 364        }
 365
 366        region = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
 367        field0 = bsg_req->rqst_data.h_vendor.vendor_cmd[2];
 368        field1 = bsg_req->rqst_data.h_vendor.vendor_cmd[3];
 369
 370        rval = qla4xxx_restore_factory_defaults(ha, region, field0, field1);
 371        if (rval) {
 372                ql4_printk(KERN_ERR, ha, "%s: set nvram failed\n", __func__);
 373                bsg_reply->result = DID_ERROR << 16;
 374                rval = -EIO;
 375        } else
 376                bsg_reply->result = DID_OK << 16;
 377
 378        bsg_job_done(bsg_job, bsg_reply->result,
 379                     bsg_reply->reply_payload_rcv_len);
 380leave:
 381        return rval;
 382}
 383
 384static int
 385qla4xxx_bsg_get_acb(struct bsg_job *bsg_job)
 386{
 387        struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
 388        struct scsi_qla_host *ha = to_qla_host(host);
 389        struct iscsi_bsg_request *bsg_req = bsg_job->request;
 390        struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
 391        uint32_t acb_type = 0;
 392        uint32_t len = 0;
 393        dma_addr_t acb_dma;
 394        uint8_t *acb = NULL;
 395        int rval = -EINVAL;
 396
 397        bsg_reply->reply_payload_rcv_len = 0;
 398
 399        if (unlikely(pci_channel_offline(ha->pdev)))
 400                goto leave;
 401
 402        /* Only 4022 and above adapters are supported */
 403        if (is_qla4010(ha))
 404                goto leave;
 405
 406        if (ql4xxx_reset_active(ha)) {
 407                ql4_printk(KERN_ERR, ha, "%s: reset active\n", __func__);
 408                rval = -EBUSY;
 409                goto leave;
 410        }
 411
 412        acb_type = bsg_req->rqst_data.h_vendor.vendor_cmd[1];
 413        len = bsg_job->reply_payload.payload_len;
 414        if (len < sizeof(struct addr_ctrl_blk)) {
 415                ql4_printk(KERN_ERR, ha, "%s: invalid acb len %d\n",
 416                           __func__, len);
 417                rval = -EINVAL;
 418                goto leave;
 419        }
 420
 421        acb = dma_alloc_coherent(&ha->pdev->dev, len, &acb_dma, GFP_KERNEL);
 422        if (!acb) {
 423                ql4_printk(KERN_ERR, ha, "%s: dma alloc failed for acb "
 424                           "data\n", __func__);
 425                rval = -ENOMEM;
 426                goto leave;
 427        }
 428
 429        rval = qla4xxx_get_acb(ha, acb_dma, acb_type, len);
 430        if (rval) {
 431                ql4_printk(KERN_ERR, ha, "%s: get acb failed\n", __func__);
 432                bsg_reply->result = DID_ERROR << 16;
 433                rval = -EIO;
 434        } else {
 435                bsg_reply->reply_payload_rcv_len =
 436                        sg_copy_from_buffer(bsg_job->reply_payload.sg_list,
 437                                            bsg_job->reply_payload.sg_cnt,
 438                                            acb, len);
 439                bsg_reply->result = DID_OK << 16;
 440        }
 441
 442        bsg_job_done(bsg_job, bsg_reply->result,
 443                     bsg_reply->reply_payload_rcv_len);
 444        dma_free_coherent(&ha->pdev->dev, len, acb, acb_dma);
 445leave:
 446        return rval;
 447}
 448
 449/**
 450 * qla4xxx_process_vendor_specific - handle vendor specific bsg request
 451 * @job: iscsi_bsg_job to handle
 452 **/
 453int qla4xxx_process_vendor_specific(struct bsg_job *bsg_job)
 454{
 455        struct iscsi_bsg_reply *bsg_reply = bsg_job->reply;
 456        struct iscsi_bsg_request *bsg_req = bsg_job->request;
 457        struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
 458        struct scsi_qla_host *ha = to_qla_host(host);
 459
 460        switch (bsg_req->rqst_data.h_vendor.vendor_cmd[0]) {
 461        case QLISCSI_VND_READ_FLASH:
 462                return qla4xxx_read_flash(bsg_job);
 463
 464        case QLISCSI_VND_UPDATE_FLASH:
 465                return qla4xxx_update_flash(bsg_job);
 466
 467        case QLISCSI_VND_GET_ACB_STATE:
 468                return qla4xxx_get_acb_state(bsg_job);
 469
 470        case QLISCSI_VND_READ_NVRAM:
 471                return qla4xxx_read_nvram(bsg_job);
 472
 473        case QLISCSI_VND_UPDATE_NVRAM:
 474                return qla4xxx_update_nvram(bsg_job);
 475
 476        case QLISCSI_VND_RESTORE_DEFAULTS:
 477                return qla4xxx_restore_defaults(bsg_job);
 478
 479        case QLISCSI_VND_GET_ACB:
 480                return qla4xxx_bsg_get_acb(bsg_job);
 481
 482        default:
 483                ql4_printk(KERN_ERR, ha, "%s: invalid BSG vendor command: "
 484                           "0x%x\n", __func__, bsg_req->msgcode);
 485                bsg_reply->result = (DID_ERROR << 16);
 486                bsg_reply->reply_payload_rcv_len = 0;
 487                bsg_job_done(bsg_job, bsg_reply->result,
 488                             bsg_reply->reply_payload_rcv_len);
 489                return -ENOSYS;
 490        }
 491}
 492
 493/**
 494 * qla4xxx_bsg_request - handle bsg request from ISCSI transport
 495 * @job: iscsi_bsg_job to handle
 496 */
 497int qla4xxx_bsg_request(struct bsg_job *bsg_job)
 498{
 499        struct iscsi_bsg_request *bsg_req = bsg_job->request;
 500        struct Scsi_Host *host = iscsi_job_to_shost(bsg_job);
 501        struct scsi_qla_host *ha = to_qla_host(host);
 502
 503        switch (bsg_req->msgcode) {
 504        case ISCSI_BSG_HST_VENDOR:
 505                return qla4xxx_process_vendor_specific(bsg_job);
 506
 507        default:
 508                ql4_printk(KERN_ERR, ha, "%s: invalid BSG command: 0x%x\n",
 509                           __func__, bsg_req->msgcode);
 510        }
 511
 512        return -ENOSYS;
 513}
 514