aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/firmware/iscsi_ibft.c14
-rw-r--r--drivers/scsi/be2iscsi/be_main.c190
-rw-r--r--drivers/scsi/iscsi_boot_sysfs.c28
-rw-r--r--include/linux/iscsi_boot_sysfs.h16
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
569static 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:
215static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf) 215static 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
394static 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
422free_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 ----------------- */
428static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { 384static 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
495free_devices: 443free_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;
3581boot_freemem: 3529boot_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
3535static void beiscsi_boot_release(void *data)
3536{
3537 struct beiscsi_hba *phba = data;
3538
3539 scsi_host_put(phba->shost);
3540}
3541
3542static 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
3584put_shost:
3585 scsi_host_put(phba->shost);
3586free_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 *
365iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index, 369iscsi_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}
373EXPORT_SYMBOL_GPL(iscsi_boot_create_target); 379EXPORT_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 *
387iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index, 394iscsi_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}
397EXPORT_SYMBOL_GPL(iscsi_boot_create_initiator); 405EXPORT_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 *
411iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index, 420iscsi_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}
421EXPORT_SYMBOL_GPL(iscsi_boot_create_ethernet); 431EXPORT_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
97struct iscsi_boot_kset { 104struct iscsi_boot_kset {
@@ -103,18 +110,21 @@ struct iscsi_boot_kobj *
103iscsi_boot_create_initiator(struct iscsi_boot_kset *boot_kset, int index, 110iscsi_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
108struct iscsi_boot_kobj * 116struct iscsi_boot_kobj *
109iscsi_boot_create_ethernet(struct iscsi_boot_kset *boot_kset, int index, 117iscsi_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));
113struct iscsi_boot_kobj * 122struct iscsi_boot_kobj *
114iscsi_boot_create_target(struct iscsi_boot_kset *boot_kset, int index, 123iscsi_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
119struct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name); 129struct iscsi_boot_kset *iscsi_boot_create_kset(const char *set_name);
120struct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno); 130struct iscsi_boot_kset *iscsi_boot_create_host_kset(unsigned int hostno);