diff options
Diffstat (limited to 'drivers/scsi/be2iscsi/be_main.c')
| -rw-r--r-- | drivers/scsi/be2iscsi/be_main.c | 311 |
1 files changed, 311 insertions, 0 deletions
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 7436c5ad5697..8220bde6c04c 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/string.h> | 26 | #include <linux/string.h> |
| 27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
| 28 | #include <linux/semaphore.h> | 28 | #include <linux/semaphore.h> |
| 29 | #include <linux/iscsi_boot_sysfs.h> | ||
| 29 | 30 | ||
| 30 | #include <scsi/libiscsi.h> | 31 | #include <scsi/libiscsi.h> |
| 31 | #include <scsi/scsi_transport_iscsi.h> | 32 | #include <scsi/scsi_transport_iscsi.h> |
| @@ -211,6 +212,218 @@ unlock: | |||
| 211 | return rc; | 212 | return rc; |
| 212 | } | 213 | } |
| 213 | 214 | ||
| 215 | static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf) | ||
| 216 | { | ||
| 217 | struct beiscsi_hba *phba = data; | ||
| 218 | char *str = buf; | ||
| 219 | int rc; | ||
| 220 | |||
| 221 | switch (type) { | ||
| 222 | case ISCSI_BOOT_TGT_NAME: | ||
| 223 | rc = sprintf(buf, "%.*s\n", | ||
| 224 | (int)strlen(phba->boot_sess.target_name), | ||
| 225 | (char *)&phba->boot_sess.target_name); | ||
| 226 | break; | ||
| 227 | case ISCSI_BOOT_TGT_IP_ADDR: | ||
| 228 | if (phba->boot_sess.conn_list[0].dest_ipaddr.ip_type == 0x1) | ||
| 229 | rc = sprintf(buf, "%pI4\n", | ||
| 230 | (char *)&phba->boot_sess.conn_list[0]. | ||
| 231 | dest_ipaddr.ip_address); | ||
| 232 | else | ||
| 233 | rc = sprintf(str, "%pI6\n", | ||
| 234 | (char *)&phba->boot_sess.conn_list[0]. | ||
| 235 | dest_ipaddr.ip_address); | ||
| 236 | break; | ||
| 237 | case ISCSI_BOOT_TGT_PORT: | ||
| 238 | rc = sprintf(str, "%d\n", phba->boot_sess.conn_list[0]. | ||
| 239 | dest_port); | ||
| 240 | break; | ||
| 241 | |||
| 242 | case ISCSI_BOOT_TGT_CHAP_NAME: | ||
| 243 | rc = sprintf(str, "%.*s\n", | ||
| 244 | phba->boot_sess.conn_list[0]. | ||
| 245 | negotiated_login_options.auth_data.chap. | ||
| 246 | target_chap_name_length, | ||
| 247 | (char *)&phba->boot_sess.conn_list[0]. | ||
| 248 | negotiated_login_options.auth_data.chap. | ||
| 249 | target_chap_name); | ||
| 250 | break; | ||
| 251 | case ISCSI_BOOT_TGT_CHAP_SECRET: | ||
| 252 | rc = sprintf(str, "%.*s\n", | ||
| 253 | phba->boot_sess.conn_list[0]. | ||
| 254 | negotiated_login_options.auth_data.chap. | ||
| 255 | target_secret_length, | ||
| 256 | (char *)&phba->boot_sess.conn_list[0]. | ||
| 257 | negotiated_login_options.auth_data.chap. | ||
| 258 | target_secret); | ||
| 259 | |||
| 260 | break; | ||
| 261 | case ISCSI_BOOT_TGT_REV_CHAP_NAME: | ||
| 262 | rc = sprintf(str, "%.*s\n", | ||
| 263 | phba->boot_sess.conn_list[0]. | ||
| 264 | negotiated_login_options.auth_data.chap. | ||
| 265 | intr_chap_name_length, | ||
| 266 | (char *)&phba->boot_sess.conn_list[0]. | ||
| 267 | negotiated_login_options.auth_data.chap. | ||
| 268 | intr_chap_name); | ||
| 269 | |||
| 270 | break; | ||
| 271 | case ISCSI_BOOT_TGT_REV_CHAP_SECRET: | ||
| 272 | rc = sprintf(str, "%.*s\n", | ||
| 273 | phba->boot_sess.conn_list[0]. | ||
| 274 | negotiated_login_options.auth_data.chap. | ||
| 275 | intr_secret_length, | ||
| 276 | (char *)&phba->boot_sess.conn_list[0]. | ||
| 277 | negotiated_login_options.auth_data.chap. | ||
| 278 | intr_secret); | ||
| 279 | break; | ||
| 280 | case ISCSI_BOOT_TGT_FLAGS: | ||
| 281 | rc = sprintf(str, "2\n"); | ||
| 282 | break; | ||
| 283 | case ISCSI_BOOT_TGT_NIC_ASSOC: | ||
| 284 | rc = sprintf(str, "0\n"); | ||
| 285 | break; | ||
| 286 | default: | ||
| 287 | rc = -ENOSYS; | ||
| 288 | break; | ||
| 289 | } | ||
| 290 | return rc; | ||
| 291 | } | ||
| 292 | |||
| 293 | static ssize_t beiscsi_show_boot_ini_info(void *data, int type, char *buf) | ||
| 294 | { | ||
| 295 | struct beiscsi_hba *phba = data; | ||
| 296 | char *str = buf; | ||
| 297 | int rc; | ||
| 298 | |||
| 299 | switch (type) { | ||
| 300 | case ISCSI_BOOT_INI_INITIATOR_NAME: | ||
| 301 | rc = sprintf(str, "%s\n", phba->boot_sess.initiator_iscsiname); | ||
| 302 | break; | ||
| 303 | default: | ||
| 304 | rc = -ENOSYS; | ||
| 305 | break; | ||
| 306 | } | ||
| 307 | return rc; | ||
| 308 | } | ||
| 309 | |||
| 310 | static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf) | ||
| 311 | { | ||
| 312 | struct beiscsi_hba *phba = data; | ||
| 313 | char *str = buf; | ||
| 314 | int rc; | ||
| 315 | |||
| 316 | switch (type) { | ||
| 317 | case ISCSI_BOOT_ETH_FLAGS: | ||
| 318 | rc = sprintf(str, "2\n"); | ||
| 319 | break; | ||
| 320 | case ISCSI_BOOT_ETH_INDEX: | ||
| 321 | rc = sprintf(str, "0\n"); | ||
| 322 | break; | ||
| 323 | case ISCSI_BOOT_ETH_MAC: | ||
| 324 | rc = beiscsi_get_macaddr(buf, phba); | ||
| 325 | if (rc < 0) { | ||
| 326 | SE_DEBUG(DBG_LVL_1, "beiscsi_get_macaddr Failed\n"); | ||
| 327 | return rc; | ||
| 328 | } | ||
| 329 | break; | ||
| 330 | default: | ||
| 331 | rc = -ENOSYS; | ||
| 332 | break; | ||
| 333 | } | ||
| 334 | return rc; | ||
| 335 | } | ||
| 336 | |||
| 337 | |||
| 338 | static mode_t beiscsi_tgt_get_attr_visibility(void *data, int type) | ||
| 339 | { | ||
| 340 | int rc; | ||
| 341 | |||
| 342 | switch (type) { | ||
| 343 | case ISCSI_BOOT_TGT_NAME: | ||
| 344 | case ISCSI_BOOT_TGT_IP_ADDR: | ||
| 345 | case ISCSI_BOOT_TGT_PORT: | ||
| 346 | case ISCSI_BOOT_TGT_CHAP_NAME: | ||
| 347 | case ISCSI_BOOT_TGT_CHAP_SECRET: | ||
| 348 | case ISCSI_BOOT_TGT_REV_CHAP_NAME: | ||
| 349 | case ISCSI_BOOT_TGT_REV_CHAP_SECRET: | ||
| 350 | case ISCSI_BOOT_TGT_NIC_ASSOC: | ||
| 351 | case ISCSI_BOOT_TGT_FLAGS: | ||
| 352 | rc = S_IRUGO; | ||
| 353 | break; | ||
| 354 | default: | ||
| 355 | rc = 0; | ||
| 356 | break; | ||
| 357 | } | ||
| 358 | return rc; | ||
| 359 | } | ||
| 360 | |||
| 361 | static mode_t beiscsi_ini_get_attr_visibility(void *data, int type) | ||
| 362 | { | ||
| 363 | int rc; | ||
| 364 | |||
| 365 | switch (type) { | ||
| 366 | case ISCSI_BOOT_INI_INITIATOR_NAME: | ||
| 367 | rc = S_IRUGO; | ||
| 368 | break; | ||
| 369 | default: | ||
| 370 | rc = 0; | ||
| 371 | break; | ||
| 372 | } | ||
| 373 | return rc; | ||
| 374 | } | ||
| 375 | |||
| 376 | |||
| 377 | static mode_t beiscsi_eth_get_attr_visibility(void *data, int type) | ||
| 378 | { | ||
| 379 | int rc; | ||
| 380 | |||
| 381 | switch (type) { | ||
| 382 | case ISCSI_BOOT_ETH_FLAGS: | ||
| 383 | case ISCSI_BOOT_ETH_MAC: | ||
| 384 | case ISCSI_BOOT_ETH_INDEX: | ||
| 385 | rc = S_IRUGO; | ||
| 386 | break; | ||
| 387 | default: | ||
| 388 | rc = 0; | ||
| 389 | break; | ||
| 390 | } | ||
| 391 | return rc; | ||
| 392 | } | ||
| 393 | |||
| 394 | static int beiscsi_setup_boot_info(struct beiscsi_hba *phba) | ||
| 395 | { | ||
| 396 | struct iscsi_boot_kobj *boot_kobj; | ||
| 397 | |||
| 398 | phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no); | ||
| 399 | if (!phba->boot_kset) | ||
| 400 | return -ENOMEM; | ||
| 401 | |||
| 402 | /* get boot info using mgmt cmd */ | ||
| 403 | boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba, | ||
| 404 | beiscsi_show_boot_tgt_info, | ||
| 405 | beiscsi_tgt_get_attr_visibility); | ||
| 406 | if (!boot_kobj) | ||
| 407 | goto free_kset; | ||
| 408 | |||
| 409 | boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba, | ||
| 410 | beiscsi_show_boot_ini_info, | ||
| 411 | beiscsi_ini_get_attr_visibility); | ||
| 412 | if (!boot_kobj) | ||
| 413 | goto free_kset; | ||
| 414 | |||
| 415 | boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba, | ||
| 416 | beiscsi_show_boot_eth_info, | ||
| 417 | beiscsi_eth_get_attr_visibility); | ||
| 418 | if (!boot_kobj) | ||
| 419 | goto free_kset; | ||
| 420 | return 0; | ||
| 421 | |||
| 422 | free_kset: | ||
| 423 | iscsi_boot_destroy_kset(phba->boot_kset); | ||
| 424 | return -ENOMEM; | ||
| 425 | } | ||
| 426 | |||
| 214 | /*------------------- PCI Driver operations and data ----------------- */ | 427 | /*------------------- PCI Driver operations and data ----------------- */ |
| 215 | static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { | 428 | static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { |
| 216 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, | 429 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, |
| @@ -268,6 +481,15 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev) | |||
| 268 | 481 | ||
| 269 | if (iscsi_host_add(shost, &phba->pcidev->dev)) | 482 | if (iscsi_host_add(shost, &phba->pcidev->dev)) |
| 270 | goto free_devices; | 483 | goto free_devices; |
| 484 | |||
| 485 | if (beiscsi_setup_boot_info(phba)) | ||
| 486 | /* | ||
| 487 | * log error but continue, because we may not be using | ||
| 488 | * iscsi boot. | ||
| 489 | */ | ||
| 490 | shost_printk(KERN_ERR, phba->shost, "Could not set up " | ||
| 491 | "iSCSI boot info."); | ||
| 492 | |||
| 271 | return phba; | 493 | return phba; |
| 272 | 494 | ||
| 273 | free_devices: | 495 | free_devices: |
| @@ -3279,6 +3501,89 @@ static void hwi_disable_intr(struct beiscsi_hba *phba) | |||
| 3279 | "In hwi_disable_intr, Already Disabled\n"); | 3501 | "In hwi_disable_intr, Already Disabled\n"); |
| 3280 | } | 3502 | } |
| 3281 | 3503 | ||
| 3504 | static int beiscsi_get_boot_info(struct beiscsi_hba *phba) | ||
| 3505 | { | ||
| 3506 | struct be_cmd_resp_get_boot_target *boot_resp; | ||
| 3507 | struct be_cmd_resp_get_session *session_resp; | ||
| 3508 | struct be_mcc_wrb *wrb; | ||
| 3509 | struct be_dma_mem nonemb_cmd; | ||
| 3510 | unsigned int tag, wrb_num; | ||
| 3511 | unsigned short status, extd_status; | ||
| 3512 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | ||
| 3513 | |||
| 3514 | tag = beiscsi_get_boot_target(phba); | ||
| 3515 | if (!tag) { | ||
| 3516 | SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); | ||
| 3517 | return -EAGAIN; | ||
| 3518 | } else | ||
| 3519 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
| 3520 | phba->ctrl.mcc_numtag[tag]); | ||
| 3521 | |||
| 3522 | wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; | ||
| 3523 | extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; | ||
| 3524 | status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; | ||
| 3525 | if (status || extd_status) { | ||
| 3526 | SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed" | ||
| 3527 | " status = %d extd_status = %d\n", | ||
| 3528 | status, extd_status); | ||
| 3529 | free_mcc_tag(&phba->ctrl, tag); | ||
| 3530 | return -EBUSY; | ||
| 3531 | } | ||
| 3532 | wrb = queue_get_wrb(mccq, wrb_num); | ||
| 3533 | free_mcc_tag(&phba->ctrl, tag); | ||
| 3534 | boot_resp = embedded_payload(wrb); | ||
| 3535 | |||
| 3536 | if (boot_resp->boot_session_handle < 0) { | ||
| 3537 | printk(KERN_ERR "No Boot Session for this pci_func," | ||
| 3538 | "session Hndl = %d\n", boot_resp->boot_session_handle); | ||
| 3539 | return -ENXIO; | ||
| 3540 | } | ||
| 3541 | |||
| 3542 | nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, | ||
| 3543 | sizeof(*session_resp), | ||
| 3544 | &nonemb_cmd.dma); | ||
| 3545 | if (nonemb_cmd.va == NULL) { | ||
| 3546 | SE_DEBUG(DBG_LVL_1, | ||
| 3547 | "Failed to allocate memory for" | ||
| 3548 | "beiscsi_get_session_info\n"); | ||
| 3549 | return -ENOMEM; | ||
| 3550 | } | ||
| 3551 | |||
| 3552 | memset(nonemb_cmd.va, 0, sizeof(*session_resp)); | ||
| 3553 | tag = beiscsi_get_session_info(phba, | ||
| 3554 | boot_resp->boot_session_handle, &nonemb_cmd); | ||
| 3555 | if (!tag) { | ||
| 3556 | SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info" | ||
| 3557 | " Failed\n"); | ||
| 3558 | goto boot_freemem; | ||
| 3559 | } else | ||
| 3560 | wait_event_interruptible(phba->ctrl.mcc_wait[tag], | ||
| 3561 | phba->ctrl.mcc_numtag[tag]); | ||
| 3562 | |||
| 3563 | wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; | ||
| 3564 | extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; | ||
| 3565 | status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; | ||
| 3566 | if (status || extd_status) { | ||
| 3567 | SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info Failed" | ||
| 3568 | " status = %d extd_status = %d\n", | ||
| 3569 | status, extd_status); | ||
| 3570 | free_mcc_tag(&phba->ctrl, tag); | ||
| 3571 | goto boot_freemem; | ||
| 3572 | } | ||
| 3573 | wrb = queue_get_wrb(mccq, wrb_num); | ||
| 3574 | free_mcc_tag(&phba->ctrl, tag); | ||
| 3575 | session_resp = nonemb_cmd.va ; | ||
| 3576 | memcpy(&phba->boot_sess, &session_resp->session_info, | ||
| 3577 | sizeof(struct mgmt_session_info)); | ||
| 3578 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | ||
| 3579 | nonemb_cmd.va, nonemb_cmd.dma); | ||
| 3580 | return 0; | ||
| 3581 | boot_freemem: | ||
| 3582 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | ||
| 3583 | nonemb_cmd.va, nonemb_cmd.dma); | ||
| 3584 | return -ENOMEM; | ||
| 3585 | } | ||
| 3586 | |||
| 3282 | static int beiscsi_init_port(struct beiscsi_hba *phba) | 3587 | static int beiscsi_init_port(struct beiscsi_hba *phba) |
| 3283 | { | 3588 | { |
| 3284 | int ret; | 3589 | int ret; |
| @@ -3841,6 +4146,7 @@ static void beiscsi_remove(struct pci_dev *pcidev) | |||
| 3841 | iscsi_host_remove(phba->shost); | 4146 | iscsi_host_remove(phba->shost); |
| 3842 | pci_dev_put(phba->pcidev); | 4147 | pci_dev_put(phba->pcidev); |
| 3843 | iscsi_host_free(phba->shost); | 4148 | iscsi_host_free(phba->shost); |
| 4149 | iscsi_boot_destroy_kset(phba->boot_kset); | ||
| 3844 | } | 4150 | } |
| 3845 | 4151 | ||
| 3846 | static void beiscsi_msix_enable(struct beiscsi_hba *phba) | 4152 | static void beiscsi_msix_enable(struct beiscsi_hba *phba) |
| @@ -3996,6 +4302,11 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, | |||
| 3996 | goto free_blkenbld; | 4302 | goto free_blkenbld; |
| 3997 | } | 4303 | } |
| 3998 | hwi_enable_intr(phba); | 4304 | hwi_enable_intr(phba); |
| 4305 | ret = beiscsi_get_boot_info(phba); | ||
| 4306 | if (ret < 0) { | ||
| 4307 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" | ||
| 4308 | "No Boot Devices !!!!!\n"); | ||
| 4309 | } | ||
| 3999 | SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n"); | 4310 | SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n"); |
| 4000 | return 0; | 4311 | return 0; |
| 4001 | 4312 | ||
