diff options
-rw-r--r-- | drivers/firmware/iscsi_ibft.c | 14 | ||||
-rw-r--r-- | drivers/scsi/be2iscsi/be_main.c | 190 | ||||
-rw-r--r-- | drivers/scsi/iscsi_boot_sysfs.c | 28 | ||||
-rw-r--r-- | include/linux/iscsi_boot_sysfs.h | 16 |
4 files changed, 142 insertions, 106 deletions
diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c index ce33f4626957..c811cb107904 100644 --- a/drivers/firmware/iscsi_ibft.c +++ b/drivers/firmware/iscsi_ibft.c | |||
@@ -566,6 +566,11 @@ static mode_t __init ibft_check_initiator_for(void *data, int type) | |||
566 | return rc; | 566 | return rc; |
567 | } | 567 | } |
568 | 568 | ||
569 | static void ibft_kobj_release(void *data) | ||
570 | { | ||
571 | kfree(data); | ||
572 | } | ||
573 | |||
569 | /* | 574 | /* |
570 | * Helper function for ibft_register_kobjects. | 575 | * Helper function for ibft_register_kobjects. |
571 | */ | 576 | */ |
@@ -595,7 +600,8 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header, | |||
595 | boot_kobj = iscsi_boot_create_initiator(boot_kset, hdr->index, | 600 | boot_kobj = iscsi_boot_create_initiator(boot_kset, hdr->index, |
596 | ibft_kobj, | 601 | ibft_kobj, |
597 | ibft_attr_show_initiator, | 602 | ibft_attr_show_initiator, |
598 | ibft_check_initiator_for); | 603 | ibft_check_initiator_for, |
604 | ibft_kobj_release); | ||
599 | if (!boot_kobj) { | 605 | if (!boot_kobj) { |
600 | rc = -ENOMEM; | 606 | rc = -ENOMEM; |
601 | goto free_ibft_obj; | 607 | goto free_ibft_obj; |
@@ -610,7 +616,8 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header, | |||
610 | boot_kobj = iscsi_boot_create_ethernet(boot_kset, hdr->index, | 616 | boot_kobj = iscsi_boot_create_ethernet(boot_kset, hdr->index, |
611 | ibft_kobj, | 617 | ibft_kobj, |
612 | ibft_attr_show_nic, | 618 | ibft_attr_show_nic, |
613 | ibft_check_nic_for); | 619 | ibft_check_nic_for, |
620 | ibft_kobj_release); | ||
614 | if (!boot_kobj) { | 621 | if (!boot_kobj) { |
615 | rc = -ENOMEM; | 622 | rc = -ENOMEM; |
616 | goto free_ibft_obj; | 623 | goto free_ibft_obj; |
@@ -625,7 +632,8 @@ static int __init ibft_create_kobject(struct acpi_table_ibft *header, | |||
625 | boot_kobj = iscsi_boot_create_target(boot_kset, hdr->index, | 632 | boot_kobj = iscsi_boot_create_target(boot_kset, hdr->index, |
626 | ibft_kobj, | 633 | ibft_kobj, |
627 | ibft_attr_show_target, | 634 | ibft_attr_show_target, |
628 | ibft_check_tgt_for); | 635 | ibft_check_tgt_for, |
636 | ibft_kobj_release); | ||
629 | if (!boot_kobj) { | 637 | if (!boot_kobj) { |
630 | rc = -ENOMEM; | 638 | rc = -ENOMEM; |
631 | goto free_ibft_obj; | 639 | goto free_ibft_obj; |
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 2e214390c63b..0a9bdfa3d939 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c | |||
@@ -215,73 +215,62 @@ unlock: | |||
215 | static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf) | 215 | static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf) |
216 | { | 216 | { |
217 | struct beiscsi_hba *phba = data; | 217 | struct beiscsi_hba *phba = data; |
218 | struct mgmt_session_info *boot_sess = &phba->boot_sess; | ||
219 | struct mgmt_conn_info *boot_conn = &boot_sess->conn_list[0]; | ||
218 | char *str = buf; | 220 | char *str = buf; |
219 | int rc; | 221 | int rc; |
220 | 222 | ||
221 | switch (type) { | 223 | switch (type) { |
222 | case ISCSI_BOOT_TGT_NAME: | 224 | case ISCSI_BOOT_TGT_NAME: |
223 | rc = sprintf(buf, "%.*s\n", | 225 | rc = sprintf(buf, "%.*s\n", |
224 | (int)strlen(phba->boot_sess.target_name), | 226 | (int)strlen(boot_sess->target_name), |
225 | (char *)&phba->boot_sess.target_name); | 227 | (char *)&boot_sess->target_name); |
226 | break; | 228 | break; |
227 | case ISCSI_BOOT_TGT_IP_ADDR: | 229 | case ISCSI_BOOT_TGT_IP_ADDR: |
228 | if (phba->boot_sess.conn_list[0].dest_ipaddr.ip_type == 0x1) | 230 | if (boot_conn->dest_ipaddr.ip_type == 0x1) |
229 | rc = sprintf(buf, "%pI4\n", | 231 | rc = sprintf(buf, "%pI4\n", |
230 | (char *)&phba->boot_sess.conn_list[0]. | 232 | (char *)&boot_conn->dest_ipaddr.ip_address); |
231 | dest_ipaddr.ip_address); | ||
232 | else | 233 | else |
233 | rc = sprintf(str, "%pI6\n", | 234 | rc = sprintf(str, "%pI6\n", |
234 | (char *)&phba->boot_sess.conn_list[0]. | 235 | (char *)&boot_conn->dest_ipaddr.ip_address); |
235 | dest_ipaddr.ip_address); | ||
236 | break; | 236 | break; |
237 | case ISCSI_BOOT_TGT_PORT: | 237 | case ISCSI_BOOT_TGT_PORT: |
238 | rc = sprintf(str, "%d\n", phba->boot_sess.conn_list[0]. | 238 | rc = sprintf(str, "%d\n", boot_conn->dest_port); |
239 | dest_port); | ||
240 | break; | 239 | break; |
241 | 240 | ||
242 | case ISCSI_BOOT_TGT_CHAP_NAME: | 241 | case ISCSI_BOOT_TGT_CHAP_NAME: |
243 | rc = sprintf(str, "%.*s\n", | 242 | rc = sprintf(str, "%.*s\n", |
244 | phba->boot_sess.conn_list[0]. | 243 | boot_conn->negotiated_login_options.auth_data.chap. |
245 | negotiated_login_options.auth_data.chap. | 244 | target_chap_name_length, |
246 | target_chap_name_length, | 245 | (char *)&boot_conn->negotiated_login_options. |
247 | (char *)&phba->boot_sess.conn_list[0]. | 246 | auth_data.chap.target_chap_name); |
248 | negotiated_login_options.auth_data.chap. | ||
249 | target_chap_name); | ||
250 | break; | 247 | break; |
251 | case ISCSI_BOOT_TGT_CHAP_SECRET: | 248 | case ISCSI_BOOT_TGT_CHAP_SECRET: |
252 | rc = sprintf(str, "%.*s\n", | 249 | rc = sprintf(str, "%.*s\n", |
253 | phba->boot_sess.conn_list[0]. | 250 | boot_conn->negotiated_login_options.auth_data.chap. |
254 | negotiated_login_options.auth_data.chap. | 251 | target_secret_length, |
255 | target_secret_length, | 252 | (char *)&boot_conn->negotiated_login_options. |
256 | (char *)&phba->boot_sess.conn_list[0]. | 253 | auth_data.chap.target_secret); |
257 | negotiated_login_options.auth_data.chap. | ||
258 | target_secret); | ||
259 | |||
260 | break; | 254 | break; |
261 | case ISCSI_BOOT_TGT_REV_CHAP_NAME: | 255 | case ISCSI_BOOT_TGT_REV_CHAP_NAME: |
262 | rc = sprintf(str, "%.*s\n", | 256 | rc = sprintf(str, "%.*s\n", |
263 | phba->boot_sess.conn_list[0]. | 257 | boot_conn->negotiated_login_options.auth_data.chap. |
264 | negotiated_login_options.auth_data.chap. | 258 | intr_chap_name_length, |
265 | intr_chap_name_length, | 259 | (char *)&boot_conn->negotiated_login_options. |
266 | (char *)&phba->boot_sess.conn_list[0]. | 260 | auth_data.chap.intr_chap_name); |
267 | negotiated_login_options.auth_data.chap. | ||
268 | intr_chap_name); | ||
269 | |||
270 | break; | 261 | break; |
271 | case ISCSI_BOOT_TGT_REV_CHAP_SECRET: | 262 | case ISCSI_BOOT_TGT_REV_CHAP_SECRET: |
272 | rc = sprintf(str, "%.*s\n", | 263 | rc = sprintf(str, "%.*s\n", |
273 | phba->boot_sess.conn_list[0]. | 264 | boot_conn->negotiated_login_options.auth_data.chap. |
274 | negotiated_login_options.auth_data.chap. | 265 | intr_secret_length, |
275 | intr_secret_length, | 266 | (char *)&boot_conn->negotiated_login_options. |
276 | (char *)&phba->boot_sess.conn_list[0]. | 267 | auth_data.chap.intr_secret); |
277 | negotiated_login_options.auth_data.chap. | ||
278 | intr_secret); | ||
279 | break; | 268 | break; |
280 | case ISCSI_BOOT_TGT_FLAGS: | 269 | case ISCSI_BOOT_TGT_FLAGS: |
281 | rc = sprintf(str, "2\n"); | 270 | rc = sprintf(str, "2\n"); |
282 | break; | 271 | break; |
283 | case ISCSI_BOOT_TGT_NIC_ASSOC: | 272 | case ISCSI_BOOT_TGT_NIC_ASSOC: |
284 | rc = sprintf(str, "0\n"); | 273 | rc = sprintf(str, "0\n"); |
285 | break; | 274 | break; |
286 | default: | 275 | default: |
287 | rc = -ENOSYS; | 276 | rc = -ENOSYS; |
@@ -315,10 +304,10 @@ static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf) | |||
315 | 304 | ||
316 | switch (type) { | 305 | switch (type) { |
317 | case ISCSI_BOOT_ETH_FLAGS: | 306 | case ISCSI_BOOT_ETH_FLAGS: |
318 | rc = sprintf(str, "2\n"); | 307 | rc = sprintf(str, "2\n"); |
319 | break; | 308 | break; |
320 | case ISCSI_BOOT_ETH_INDEX: | 309 | case ISCSI_BOOT_ETH_INDEX: |
321 | rc = sprintf(str, "0\n"); | 310 | rc = sprintf(str, "0\n"); |
322 | break; | 311 | break; |
323 | case ISCSI_BOOT_ETH_MAC: | 312 | case ISCSI_BOOT_ETH_MAC: |
324 | rc = beiscsi_get_macaddr(buf, phba); | 313 | rc = beiscsi_get_macaddr(buf, phba); |
@@ -391,39 +380,6 @@ static mode_t beiscsi_eth_get_attr_visibility(void *data, int type) | |||
391 | return rc; | 380 | return rc; |
392 | } | 381 | } |
393 | 382 | ||
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 | |||
427 | /*------------------- PCI Driver operations and data ----------------- */ | 383 | /*------------------- PCI Driver operations and data ----------------- */ |
428 | static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { | 384 | static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { |
429 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, | 385 | { PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, |
@@ -482,14 +438,6 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev) | |||
482 | if (iscsi_host_add(shost, &phba->pcidev->dev)) | 438 | if (iscsi_host_add(shost, &phba->pcidev->dev)) |
483 | goto free_devices; | 439 | goto free_devices; |
484 | 440 | ||
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 | |||
493 | return phba; | 441 | return phba; |
494 | 442 | ||
495 | free_devices: | 443 | free_devices: |
@@ -3510,6 +3458,7 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba) | |||
3510 | unsigned int tag, wrb_num; | 3458 | unsigned int tag, wrb_num; |
3511 | unsigned short status, extd_status; | 3459 | unsigned short status, extd_status; |
3512 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; | 3460 | struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; |
3461 | int ret = -ENOMEM; | ||
3513 | 3462 | ||
3514 | tag = beiscsi_get_boot_target(phba); | 3463 | tag = beiscsi_get_boot_target(phba); |
3515 | if (!tag) { | 3464 | if (!tag) { |
@@ -3534,8 +3483,7 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba) | |||
3534 | boot_resp = embedded_payload(wrb); | 3483 | boot_resp = embedded_payload(wrb); |
3535 | 3484 | ||
3536 | if (boot_resp->boot_session_handle < 0) { | 3485 | if (boot_resp->boot_session_handle < 0) { |
3537 | printk(KERN_ERR "No Boot Session for this pci_func," | 3486 | shost_printk(KERN_INFO, phba->shost, "No Boot Session.\n"); |
3538 | "session Hndl = %d\n", boot_resp->boot_session_handle); | ||
3539 | return -ENXIO; | 3487 | return -ENXIO; |
3540 | } | 3488 | } |
3541 | 3489 | ||
@@ -3573,14 +3521,70 @@ static int beiscsi_get_boot_info(struct beiscsi_hba *phba) | |||
3573 | wrb = queue_get_wrb(mccq, wrb_num); | 3521 | wrb = queue_get_wrb(mccq, wrb_num); |
3574 | free_mcc_tag(&phba->ctrl, tag); | 3522 | free_mcc_tag(&phba->ctrl, tag); |
3575 | session_resp = nonemb_cmd.va ; | 3523 | session_resp = nonemb_cmd.va ; |
3524 | |||
3576 | memcpy(&phba->boot_sess, &session_resp->session_info, | 3525 | memcpy(&phba->boot_sess, &session_resp->session_info, |
3577 | sizeof(struct mgmt_session_info)); | 3526 | sizeof(struct mgmt_session_info)); |
3578 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | 3527 | ret = 0; |
3579 | nonemb_cmd.va, nonemb_cmd.dma); | 3528 | |
3580 | return 0; | ||
3581 | boot_freemem: | 3529 | boot_freemem: |
3582 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, | 3530 | pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, |
3583 | nonemb_cmd.va, nonemb_cmd.dma); | 3531 | nonemb_cmd.va, nonemb_cmd.dma); |
3532 | return ret; | ||
3533 | } | ||
3534 | |||
3535 | static void beiscsi_boot_release(void *data) | ||
3536 | { | ||
3537 | struct beiscsi_hba *phba = data; | ||
3538 | |||
3539 | scsi_host_put(phba->shost); | ||
3540 | } | ||
3541 | |||
3542 | static int beiscsi_setup_boot_info(struct beiscsi_hba *phba) | ||
3543 | { | ||
3544 | struct iscsi_boot_kobj *boot_kobj; | ||
3545 | |||
3546 | /* get boot info using mgmt cmd */ | ||
3547 | if (beiscsi_get_boot_info(phba)) | ||
3548 | /* Try to see if we can carry on without this */ | ||
3549 | return 0; | ||
3550 | |||
3551 | phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no); | ||
3552 | if (!phba->boot_kset) | ||
3553 | return -ENOMEM; | ||
3554 | |||
3555 | /* get a ref because the show function will ref the phba */ | ||
3556 | if (!scsi_host_get(phba->shost)) | ||
3557 | goto free_kset; | ||
3558 | boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba, | ||
3559 | beiscsi_show_boot_tgt_info, | ||
3560 | beiscsi_tgt_get_attr_visibility, | ||
3561 | beiscsi_boot_release); | ||
3562 | if (!boot_kobj) | ||
3563 | goto put_shost; | ||
3564 | |||
3565 | if (!scsi_host_get(phba->shost)) | ||
3566 | goto free_kset; | ||
3567 | boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba, | ||
3568 | beiscsi_show_boot_ini_info, | ||
3569 | beiscsi_ini_get_attr_visibility, | ||
3570 | beiscsi_boot_release); | ||
3571 | if (!boot_kobj) | ||
3572 | goto put_shost; | ||
3573 | |||
3574 | if (!scsi_host_get(phba->shost)) | ||
3575 | goto free_kset; | ||
3576 | boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba, | ||
3577 | beiscsi_show_boot_eth_info, | ||
3578 | beiscsi_eth_get_attr_visibility, | ||
3579 | beiscsi_boot_release); | ||
3580 | if (!boot_kobj) | ||
3581 | goto put_shost; | ||
3582 | return 0; | ||
3583 | |||
3584 | put_shost: | ||
3585 | scsi_host_put(phba->shost); | ||
3586 | free_kset: | ||
3587 | iscsi_boot_destroy_kset(phba->boot_kset); | ||
3584 | return -ENOMEM; | 3588 | return -ENOMEM; |
3585 | } | 3589 | } |
3586 | 3590 | ||
@@ -4307,11 +4311,15 @@ static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, | |||
4307 | goto free_blkenbld; | 4311 | goto free_blkenbld; |
4308 | } | 4312 | } |
4309 | hwi_enable_intr(phba); | 4313 | hwi_enable_intr(phba); |
4310 | ret = beiscsi_get_boot_info(phba); | 4314 | |
4311 | if (ret < 0) { | 4315 | if (beiscsi_setup_boot_info(phba)) |
4312 | shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" | 4316 | /* |
4313 | "No Boot Devices !!!!!\n"); | 4317 | * log error but continue, because we may not be using |
4314 | } | 4318 | * iscsi boot. |
4319 | */ | ||
4320 | shost_printk(KERN_ERR, phba->shost, "Could not set up " | ||
4321 | "iSCSI boot info."); | ||
4322 | |||
4315 | SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n"); | 4323 | SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n"); |
4316 | return 0; | 4324 | return 0; |
4317 | 4325 | ||
diff --git a/drivers/scsi/iscsi_boot_sysfs.c b/drivers/scsi/iscsi_boot_sysfs.c index 4274ce93d8f2..89700cbca16e 100644 --- a/drivers/scsi/iscsi_boot_sysfs.c +++ b/drivers/scsi/iscsi_boot_sysfs.c | |||
@@ -64,7 +64,8 @@ static void iscsi_boot_kobj_release(struct kobject *kobj) | |||
64 | struct iscsi_boot_kobj *boot_kobj = | 64 | struct iscsi_boot_kobj *boot_kobj = |
65 | container_of(kobj, struct iscsi_boot_kobj, kobj); | 65 | container_of(kobj, struct iscsi_boot_kobj, kobj); |
66 | 66 | ||
67 | kfree(boot_kobj->data); | 67 | if (boot_kobj->release) |
68 | boot_kobj->release(boot_kobj->data); | ||
68 | kfree(boot_kobj); | 69 | kfree(boot_kobj); |
69 | } | 70 | } |
70 | 71 | ||
@@ -305,7 +306,8 @@ iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset, | |||
305 | struct attribute_group *attr_group, | 306 | struct attribute_group *attr_group, |
306 | const char *name, int index, void *data, | 307 | const char *name, int index, void *data, |
307 | ssize_t (*show) (void *data, int type, char *buf), | 308 | ssize_t (*show) (void *data, int type, char *buf), |
308 | mode_t (*is_visible) (void *data, int type)) | 309 | mode_t (*is_visible) (void *data, int type), |
310 | void (*release) (void *data)) | ||
309 | { | 311 | { |
310 | struct iscsi_boot_kobj *boot_kobj; | 312 | struct iscsi_boot_kobj *boot_kobj; |
311 | 313 | ||
@@ -323,6 +325,7 @@ iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset, | |||
323 | boot_kobj->data = data; | 325 | boot_kobj->data = data; |
324 | boot_kobj->show = show; | 326 | boot_kobj->show = show; |
325 | boot_kobj->is_visible = is_visible; | 327 | boot_kobj->is_visible = is_visible; |
328 | boot_kobj->release = release; | ||
326 | 329 | ||
327 | if (sysfs_create_group(&boot_kobj->kobj, attr_group)) { | 330 | if (sysfs_create_group(&boot_kobj->kobj, attr_group)) { |
328 | /* | 331 | /* |
@@ -331,7 +334,7 @@ iscsi_boot_create_kobj(struct iscsi_boot_kset *boot_kset, | |||
331 | * the boot kobj was not setup and the normal release | 334 | * the boot kobj was not setup and the normal release |
332 | * path is not being run. | 335 | * path is not being run. |
333 | */ | 336 | */ |
334 | boot_kobj->data = NULL; | 337 | boot_kobj->release = NULL; |
335 | kobject_put(&boot_kobj->kobj); | 338 | kobject_put(&boot_kobj->kobj); |
336 | return NULL; | 339 | return NULL; |
337 | } | 340 | } |
@@ -357,6 +360,7 @@ static void iscsi_boot_remove_kobj(struct iscsi_boot_kobj *boot_kobj) | |||
357 | * @data: driver specific data for target | 360 | * @data: driver specific data for target |
358 | * @show: attr show function | 361 | * @show: attr show function |
359 | * @is_visible: attr visibility function | 362 | * @is_visible: attr visibility function |
363 | * @release: release function | ||
360 | * | 364 | * |
361 | * Note: The boot sysfs lib will free the data passed in for the caller | 365 | * Note: The boot sysfs lib will free the data passed in for the caller |
362 | * when all refs to the target kobject have been released. | 366 | * when all refs to the target kobject have been released. |
@@ -365,10 +369,12 @@ struct iscsi_boot_kobj * | |||
365 | iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index, | 369 | iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index, |
366 | void *data, | 370 | void *data, |
367 | ssize_t (*show) (void *data, int type, char *buf), | 371 | ssize_t (*show) (void *data, int type, char *buf), |
368 | mode_t (*is_visible) (void *data, int type)) | 372 | mode_t (*is_visible) (void *data, int type), |
373 | void (*release) (void *data)) | ||
369 | { | 374 | { |
370 | return iscsi_boot_create_kobj(boot_kset, &iscsi_boot_target_attr_group, | 375 | return iscsi_boot_create_kobj(boot_kset, &iscsi_boot_target_attr_group, |
371 | "target%d", index, data, show, is_visible); | 376 | "target%d", index, data, show, is_visible, |
377 | release); | ||
372 | } | 378 | } |
373 | EXPORT_SYMBOL_GPL(iscsi_boot_create_target); | 379 | EXPORT_SYMBOL_GPL(iscsi_boot_create_target); |
374 | 380 | ||
@@ -379,6 +385,7 @@ EXPORT_SYMBOL_GPL(iscsi_boot_create_target); | |||
379 | * @data: driver specific data | 385 | * @data: driver specific data |
380 | * @show: attr show function | 386 | * @show: attr show function |
381 | * @is_visible: attr visibility function | 387 | * @is_visible: attr visibility function |
388 | * @release: release function | ||
382 | * | 389 | * |
383 | * Note: The boot sysfs lib will free the data passed in for the caller | 390 | * Note: The boot sysfs lib will free the data passed in for the caller |
384 | * when all refs to the initiator kobject have been released. | 391 | * when all refs to the initiator kobject have been released. |
@@ -387,12 +394,13 @@ struct iscsi_boot_kobj * | |||
387 | iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index, | 394 | iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index, |
388 | void *data, | 395 | void *data, |
389 | ssize_t (*show) (void *data, int type, char *buf), | 396 | ssize_t (*show) (void *data, int type, char *buf), |
390 | mode_t (*is_visible) (void *data, int type)) | 397 | mode_t (*is_visible) (void *data, int type), |
398 | void (*release) (void *data)) | ||
391 | { | 399 | { |
392 | return iscsi_boot_create_kobj(boot_kset, | 400 | return iscsi_boot_create_kobj(boot_kset, |
393 | &iscsi_boot_initiator_attr_group, | 401 | &iscsi_boot_initiator_attr_group, |
394 | "initiator", index, data, show, | 402 | "initiator", index, data, show, |
395 | is_visible); | 403 | is_visible, release); |
396 | } | 404 | } |
397 | EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator); | 405 | EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator); |
398 | 406 | ||
@@ -403,6 +411,7 @@ EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator); | |||
403 | * @data: driver specific data | 411 | * @data: driver specific data |
404 | * @show: attr show function | 412 | * @show: attr show function |
405 | * @is_visible: attr visibility function | 413 | * @is_visible: attr visibility function |
414 | * @release: release function | ||
406 | * | 415 | * |
407 | * Note: The boot sysfs lib will free the data passed in for the caller | 416 | * Note: The boot sysfs lib will free the data passed in for the caller |
408 | * when all refs to the ethernet kobject have been released. | 417 | * when all refs to the ethernet kobject have been released. |
@@ -411,12 +420,13 @@ struct iscsi_boot_kobj * | |||
411 | iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index, | 420 | iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index, |
412 | void *data, | 421 | void *data, |
413 | ssize_t (*show) (void *data, int type, char *buf), | 422 | ssize_t (*show) (void *data, int type, char *buf), |
414 | mode_t (*is_visible) (void *data, int type)) | 423 | mode_t (*is_visible) (void *data, int type), |
424 | void (*release) (void *data)) | ||
415 | { | 425 | { |
416 | return iscsi_boot_create_kobj(boot_kset, | 426 | return iscsi_boot_create_kobj(boot_kset, |
417 | &iscsi_boot_ethernet_attr_group, | 427 | &iscsi_boot_ethernet_attr_group, |
418 | "ethernet%d", index, data, show, | 428 | "ethernet%d", index, data, show, |
419 | is_visible); | 429 | is_visible, release); |
420 | } | 430 | } |
421 | EXPORT_SYMBOL_GPL(iscsi_boot_create_ethernet); | 431 | EXPORT_SYMBOL_GPL(iscsi_boot_create_ethernet); |
422 | 432 | ||
diff --git a/include/linux/iscsi_boot_sysfs.h b/include/linux/iscsi_boot_sysfs.h index f1e6c184f14f..f0a2f8b0aa13 100644 --- a/include/linux/iscsi_boot_sysfs.h +++ b/include/linux/iscsi_boot_sysfs.h | |||
@@ -92,6 +92,13 @@ struct iscsi_boot_kobj { | |||
92 | * properties. | 92 | * properties. |
93 | */ | 93 | */ |
94 | mode_t (*is_visible) (void *data, int type); | 94 | mode_t (*is_visible) (void *data, int type); |
95 | |||
96 | /* | ||
97 | * Driver specific release function. | ||
98 | * | ||
99 | * The function should free the data passed in. | ||
100 | */ | ||
101 | void (*release) (void *data); | ||
95 | }; | 102 | }; |
96 | 103 | ||
97 | struct iscsi_boot_kset { | 104 | struct iscsi_boot_kset { |
@@ -103,18 +110,21 @@ struct iscsi_boot_kobj * | |||
103 | iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index, | 110 | iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index, |
104 | void *data, | 111 | void *data, |
105 | ssize_t (*show) (void *data, int type, char *buf), | 112 | ssize_t (*show) (void *data, int type, char *buf), |
106 | mode_t (*is_visible) (void *data, int type)); | 113 | mode_t (*is_visible) (void *data, int type), |
114 | void (*release) (void *data)); | ||
107 | 115 | ||
108 | struct iscsi_boot_kobj * | 116 | struct iscsi_boot_kobj * |
109 | iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index, | 117 | iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index, |
110 | void *data, | 118 | void *data, |
111 | ssize_t (*show) (void *data, int type, char *buf), | 119 | ssize_t (*show) (void *data, int type, char *buf), |
112 | mode_t (*is_visible) (void *data, int type)); | 120 | mode_t (*is_visible) (void *data, int type), |
121 | void (*release) (void *data)); | ||
113 | struct iscsi_boot_kobj * | 122 | struct iscsi_boot_kobj * |
114 | iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index, | 123 | iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index, |
115 | void *data, | 124 | void *data, |
116 | ssize_t (*show) (void *data, int type, char *buf), | 125 | ssize_t (*show) (void *data, int type, char *buf), |
117 | mode_t (*is_visible) (void *data, int type)); | 126 | mode_t (*is_visible) (void *data, int type), |
127 | void (*release) (void *data)); | ||
118 | 128 | ||
119 | struct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name); | 129 | struct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name); |
120 | struct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno); | 130 | struct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno); |