diff options
Diffstat (limited to 'drivers/scsi/cxgb3i/cxgb3i_iscsi.c')
-rw-r--r-- | drivers/scsi/cxgb3i/cxgb3i_iscsi.c | 129 |
1 files changed, 86 insertions, 43 deletions
diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c index e185dedc4c1f..fff8e4327644 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c +++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c | |||
@@ -53,36 +53,52 @@ static LIST_HEAD(cxgb3i_snic_list); | |||
53 | static DEFINE_RWLOCK(cxgb3i_snic_rwlock); | 53 | static DEFINE_RWLOCK(cxgb3i_snic_rwlock); |
54 | 54 | ||
55 | /** | 55 | /** |
56 | * cxgb3i_adapter_add - init a s3 adapter structure and any h/w settings | 56 | * cxgb3i_adpater_find_by_tdev - find the cxgb3i_adapter structure via t3cdev |
57 | * @t3dev: t3cdev adapter | 57 | * @tdev: t3cdev pointer |
58 | * return the resulting cxgb3i_adapter struct | ||
59 | */ | 58 | */ |
60 | struct cxgb3i_adapter *cxgb3i_adapter_add(struct t3cdev *t3dev) | 59 | struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *tdev) |
61 | { | 60 | { |
62 | struct cxgb3i_adapter *snic; | 61 | struct cxgb3i_adapter *snic; |
63 | struct adapter *adapter = tdev2adap(t3dev); | ||
64 | int i; | ||
65 | 62 | ||
66 | snic = kzalloc(sizeof(*snic), GFP_KERNEL); | 63 | read_lock(&cxgb3i_snic_rwlock); |
67 | if (!snic) { | 64 | list_for_each_entry(snic, &cxgb3i_snic_list, list_head) { |
68 | cxgb3i_api_debug("cxgb3 %s, OOM.\n", t3dev->name); | 65 | if (snic->tdev == tdev) { |
69 | return NULL; | 66 | read_unlock(&cxgb3i_snic_rwlock); |
67 | return snic; | ||
68 | } | ||
70 | } | 69 | } |
71 | spin_lock_init(&snic->lock); | 70 | read_unlock(&cxgb3i_snic_rwlock); |
71 | return NULL; | ||
72 | } | ||
73 | |||
74 | static inline int adapter_update(struct cxgb3i_adapter *snic) | ||
75 | { | ||
76 | cxgb3i_log_info("snic 0x%p, t3dev 0x%p, updating.\n", | ||
77 | snic, snic->tdev); | ||
78 | return cxgb3i_adapter_ddp_info(snic->tdev, &snic->tag_format, | ||
79 | &snic->tx_max_size, | ||
80 | &snic->rx_max_size); | ||
81 | } | ||
82 | |||
83 | static int adapter_add(struct cxgb3i_adapter *snic) | ||
84 | { | ||
85 | struct t3cdev *t3dev = snic->tdev; | ||
86 | struct adapter *adapter = tdev2adap(t3dev); | ||
87 | int i, err; | ||
72 | 88 | ||
73 | snic->tdev = t3dev; | ||
74 | snic->pdev = adapter->pdev; | 89 | snic->pdev = adapter->pdev; |
75 | snic->tag_format.sw_bits = sw_tag_idx_bits + sw_tag_age_bits; | 90 | snic->tag_format.sw_bits = sw_tag_idx_bits + sw_tag_age_bits; |
76 | 91 | ||
77 | if (cxgb3i_adapter_ddp_init(t3dev, &snic->tag_format, | 92 | err = cxgb3i_adapter_ddp_info(t3dev, &snic->tag_format, |
78 | &snic->tx_max_size, | 93 | &snic->tx_max_size, |
79 | &snic->rx_max_size) < 0) | 94 | &snic->rx_max_size); |
80 | goto free_snic; | 95 | if (err < 0) |
96 | return err; | ||
81 | 97 | ||
82 | for_each_port(adapter, i) { | 98 | for_each_port(adapter, i) { |
83 | snic->hba[i] = cxgb3i_hba_host_add(snic, adapter->port[i]); | 99 | snic->hba[i] = cxgb3i_hba_host_add(snic, adapter->port[i]); |
84 | if (!snic->hba[i]) | 100 | if (!snic->hba[i]) |
85 | goto ulp_cleanup; | 101 | return -EINVAL; |
86 | } | 102 | } |
87 | snic->hba_cnt = adapter->params.nports; | 103 | snic->hba_cnt = adapter->params.nports; |
88 | 104 | ||
@@ -91,46 +107,71 @@ struct cxgb3i_adapter *cxgb3i_adapter_add(struct t3cdev *t3dev) | |||
91 | list_add_tail(&snic->list_head, &cxgb3i_snic_list); | 107 | list_add_tail(&snic->list_head, &cxgb3i_snic_list); |
92 | write_unlock(&cxgb3i_snic_rwlock); | 108 | write_unlock(&cxgb3i_snic_rwlock); |
93 | 109 | ||
94 | return snic; | 110 | cxgb3i_log_info("t3dev 0x%p open, snic 0x%p, %u scsi hosts added.\n", |
111 | t3dev, snic, snic->hba_cnt); | ||
112 | return 0; | ||
113 | } | ||
95 | 114 | ||
96 | ulp_cleanup: | 115 | /** |
97 | cxgb3i_adapter_ddp_cleanup(t3dev); | 116 | * cxgb3i_adapter_open - init a s3 adapter structure and any h/w settings |
98 | free_snic: | 117 | * @t3dev: t3cdev adapter |
99 | kfree(snic); | 118 | */ |
100 | return NULL; | 119 | void cxgb3i_adapter_open(struct t3cdev *t3dev) |
120 | { | ||
121 | struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev); | ||
122 | int err; | ||
123 | |||
124 | if (snic) | ||
125 | err = adapter_update(snic); | ||
126 | else { | ||
127 | snic = kzalloc(sizeof(*snic), GFP_KERNEL); | ||
128 | if (snic) { | ||
129 | spin_lock_init(&snic->lock); | ||
130 | snic->tdev = t3dev; | ||
131 | err = adapter_add(snic); | ||
132 | } else | ||
133 | err = -ENOMEM; | ||
134 | } | ||
135 | |||
136 | if (err < 0) { | ||
137 | cxgb3i_log_info("snic 0x%p, f 0x%x, t3dev 0x%p open, err %d.\n", | ||
138 | snic, snic ? snic->flags : 0, t3dev, err); | ||
139 | if (snic) { | ||
140 | snic->flags &= ~CXGB3I_ADAPTER_FLAG_RESET; | ||
141 | cxgb3i_adapter_close(t3dev); | ||
142 | } | ||
143 | } | ||
101 | } | 144 | } |
102 | 145 | ||
103 | /** | 146 | /** |
104 | * cxgb3i_adapter_remove - release the resources held and cleanup h/w settings | 147 | * cxgb3i_adapter_close - release the resources held and cleanup h/w settings |
105 | * @t3dev: t3cdev adapter | 148 | * @t3dev: t3cdev adapter |
106 | */ | 149 | */ |
107 | void cxgb3i_adapter_remove(struct t3cdev *t3dev) | 150 | void cxgb3i_adapter_close(struct t3cdev *t3dev) |
108 | { | 151 | { |
152 | struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev); | ||
109 | int i; | 153 | int i; |
110 | struct cxgb3i_adapter *snic; | 154 | |
155 | if (!snic || snic->flags & CXGB3I_ADAPTER_FLAG_RESET) { | ||
156 | cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, f 0x%x.\n", | ||
157 | t3dev, snic, snic ? snic->flags : 0); | ||
158 | return; | ||
159 | } | ||
111 | 160 | ||
112 | /* remove from the list */ | 161 | /* remove from the list */ |
113 | write_lock(&cxgb3i_snic_rwlock); | 162 | write_lock(&cxgb3i_snic_rwlock); |
114 | list_for_each_entry(snic, &cxgb3i_snic_list, list_head) { | 163 | list_del(&snic->list_head); |
115 | if (snic->tdev == t3dev) { | ||
116 | list_del(&snic->list_head); | ||
117 | break; | ||
118 | } | ||
119 | } | ||
120 | write_unlock(&cxgb3i_snic_rwlock); | 164 | write_unlock(&cxgb3i_snic_rwlock); |
121 | 165 | ||
122 | if (snic) { | 166 | for (i = 0; i < snic->hba_cnt; i++) { |
123 | for (i = 0; i < snic->hba_cnt; i++) { | 167 | if (snic->hba[i]) { |
124 | if (snic->hba[i]) { | 168 | cxgb3i_hba_host_remove(snic->hba[i]); |
125 | cxgb3i_hba_host_remove(snic->hba[i]); | 169 | snic->hba[i] = NULL; |
126 | snic->hba[i] = NULL; | ||
127 | } | ||
128 | } | 170 | } |
129 | |||
130 | /* release ddp resources */ | ||
131 | cxgb3i_adapter_ddp_cleanup(snic->tdev); | ||
132 | kfree(snic); | ||
133 | } | 171 | } |
172 | cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, %u scsi hosts removed.\n", | ||
173 | t3dev, snic, snic->hba_cnt); | ||
174 | kfree(snic); | ||
134 | } | 175 | } |
135 | 176 | ||
136 | /** | 177 | /** |
@@ -170,7 +211,8 @@ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic, | |||
170 | shost = iscsi_host_alloc(&cxgb3i_host_template, | 211 | shost = iscsi_host_alloc(&cxgb3i_host_template, |
171 | sizeof(struct cxgb3i_hba), 1); | 212 | sizeof(struct cxgb3i_hba), 1); |
172 | if (!shost) { | 213 | if (!shost) { |
173 | cxgb3i_log_info("iscsi_host_alloc failed.\n"); | 214 | cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_alloc failed.\n", |
215 | snic, ndev); | ||
174 | return NULL; | 216 | return NULL; |
175 | } | 217 | } |
176 | 218 | ||
@@ -188,7 +230,8 @@ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic, | |||
188 | pci_dev_get(snic->pdev); | 230 | pci_dev_get(snic->pdev); |
189 | err = iscsi_host_add(shost, &snic->pdev->dev); | 231 | err = iscsi_host_add(shost, &snic->pdev->dev); |
190 | if (err) { | 232 | if (err) { |
191 | cxgb3i_log_info("iscsi_host_add failed.\n"); | 233 | cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_add failed.\n", |
234 | snic, ndev); | ||
192 | goto pci_dev_put; | 235 | goto pci_dev_put; |
193 | } | 236 | } |
194 | 237 | ||