aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/be2iscsi/be_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/be2iscsi/be_main.c')
-rw-r--r--drivers/scsi/be2iscsi/be_main.c311
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
215static 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
293static 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
310static 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
338static 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
361static 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
377static 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
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
214/*------------------- PCI Driver operations and data ----------------- */ 427/*------------------- PCI Driver operations and data ----------------- */
215static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = { 428static 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
273free_devices: 495free_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
3504static 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;
3581boot_freemem:
3582 pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
3583 nonemb_cmd.va, nonemb_cmd.dma);
3584 return -ENOMEM;
3585}
3586
3282static int beiscsi_init_port(struct beiscsi_hba *phba) 3587static 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
3846static void beiscsi_msix_enable(struct beiscsi_hba *phba) 4152static 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