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 | ||